初探傳統關聯式資料庫如何處理高併發情境

前言 近年來隨著網路發展愈來愈快,高併發的場景愈來愈常見,高併發性能是指系統能夠有效地處理大量同時訪問和操作數據的能力,這在網路應用、金融系統、電子商務等領域愈來愈重要.隨著數據量的不斷增長和用戶需求的不斷擴展,我們需要確保我們的資料庫系統能夠承受高負載、高併發的壓力,同時保持良好的性能和穩定性。在這樣的背景下,優化資料庫的設計和架構、實施有效的併發控制策略成為至關重要的任務。 本篇是研究了一般 RDBMs 如何處理高併發問題的常見解法 Lock 機制 我們都知道寫程式的時候,如果有兩個 process/thread 要對同筆資料進行操作,為了避免資料的不一致,我們常會加上鎖的機制,臨時將該資源上鎖,僅允許一次只能被一個 process/thread 更動.同樣的,RDBMs 也有相同的機制來處理這種情形,這也是傳統資料庫處理高併發的最基本原理 SELECT … FOR UPDATE 為了避免兩個 transaction 同時對同筆資料進行操作,造成資料不一致的問題,一般常見的 RDBMs 都有提供底下這個 SQL 語法 BEGIN SELECT ... FOR UPDATE <各式針對該資料的操作, ex: UPDATE, DELETE...> COMMIT 一旦開啟新的 transaction 並執行這段 SQL 語法,在還沒 COMMIT 以前,資料庫將會替當前這筆資料加上鎖,鎖住這些即將要被更動的資料,因為資料庫悲觀的認為他們隨時有可能被修正(悲觀鎖),一旦上鎖後,下一個 tx 要進行操作時,都需要等待該鎖釋放後才能進行 至於這個鎖是行級鎖還是表級鎖,以及這個排他鎖會鎖哪些操作(SELECT? INSERT? UPDATE? DELETE?),則因各種資料庫背後的機制而不同 以 MySQL(InnoDB)為例,如果 SELECT 的對象加上 WHERE 條件是主鍵或有加上索引,則僅會加上行級鎖,鎖住當前查詢到的資料.但如果 WHERE 條件不是主鍵或非索引,則整個資料表都會被鎖住.正因如此,一旦 SELECT ... FOR UPDATE 沒寫好,MySQL 是有可能把整個資料表都鎖住,造成其他 transaction 需要等待鎖釋放才能進行操作,進而增加 latency 而影響使用者體驗.(以上前提要是 MySQL 的 InnoDB 作為 storage engine,因為 MyISAM 預設都是表級鎖)...

<span title='2024-05-05 00:49:13 +0800 +0800'>May 5, 2024</span>&nbsp;·&nbsp;3 min&nbsp;·&nbsp;611 words&nbsp;·&nbsp;Madi