1)MyISAM 被 InnoDB 替代的重要原因之一是什麼?
-
MyISAM 引擎就不支援行鎖,只能使用表鎖,同一張表上任何時刻只能有一個更新在執行,影響到業務併發度。
-
InnoDB 是支援行鎖的。
2)兩階段鎖協議是什麼?
-
在 InnoDB 事務中,行鎖是在需要的時候才加上的,但並不是不需要了就立刻釋放,而是要等到事務結束時才釋放
3)知道了兩階段鎖協議,對我們使用事務有什麼幫助呢?
-
如果你的事務中需要鎖多個行,要把最可能造成鎖衝突、最可能影響併發度的鎖儘量往後放
4)根據兩階段協議來實戰優化的案例?
-
買電影票業務,我們應該把影院賬戶餘額增加這個語句放在最後,因為可能有很多的使用者在同時買票。不要因為事務佔有鎖而影響我們其他的人買票,降低系統的併發度。
5)如果這個影院做活動,可以低價預售一年內所有的電影票,而且這個活動只做一天。於是在活動時間開始的時候,你的 MySQL 就掛了。你登上伺服器一看,CPU 消耗接近 100%,但整個資料庫每秒就執行不到 100 個事務。這是什麼原因呢?
-
發生死鎖
6)MYSQL中死鎖的解決策略?
-
一種策略是,直接進入等待,直到超時。這個超時時間可以通過引數 innodb_lock_wait_timeout 來設定。
-
另一種策略是,發起死鎖檢測,發現死鎖後,主動回滾死鎖鏈條中的某一個事務,讓其他事務得以繼續執行。將引數 innodb_deadlock_detect 設定為 on(預設值就是on),表示開啟這個邏輯。
7)死鎖的預設超時時間是多少?
-
50s
8)既然這麼大不好,那為什麼我們不把等待超時時間設定為1s呢?
-
如果真的出現死鎖的話那還好說,萬一只是簡單的等待那就造成誤傷了。
9)實際上我們應該選擇哪種死鎖的解決方案呢?
-
選擇上面6)的第二種,主動死鎖檢測
10)主動死鎖檢測有哪些缺點?
-
主動檢測的業務:每當一個事務被鎖的時候,就要看看它所依賴的執行緒有沒有被別人鎖住,如此迴圈,最後判斷是否出現了迴圈等待,也就是死鎖。
-
假設有 1000 個併發執行緒要同時更新同一行,那麼死鎖檢測操作就是 100 萬這個量級的。最終沒有死鎖的話消耗大量的CPU資源,表面上看上去cpu很忙,但是缺沒幹了幾件正事。
11)既然主動檢測特別耗CPU,那怎麼解決由這種熱點行更新導致的效能問題呢?
-
就是如果你能確保這個業務一定不會出現死鎖,可以臨時把死鎖檢測關掉。
-
另一個思路是控制併發度,並且這個併發控制要做在資料庫服務端。因為客戶端有很多。
-
如果你有中介軟體,可以考慮在中介軟體實現;如果你的團隊有能修改 MySQL 原始碼的人,也可以做在 MySQL 裡面。基本思路就是,對於相同行的更新,在進入引擎之前排隊。這樣在 InnoDB 內部就不會有大量的死鎖檢測工作了。
12)如果團隊裡暫時沒有資料庫方面的專家,不能實現這樣的方案,能不能從設計上優化這個問題呢?
-
將一行改成邏輯上的多行來減少鎖衝突。以影院賬戶為例,可以考慮放在多條記錄上,比如 10 個記錄,影院的賬戶總額等於這 10 個記錄的值的總和,每次要增加金額隨便選一條就行。
-
這類方案需要根據業務邏輯做詳細設計,退票的時候當一部分行記錄變成 0 的時候,程式碼要有特殊處理。