1. 程式人生 > 其它 >mysql_阻塞和死鎖

mysql_阻塞和死鎖

什麼是阻塞

由於不同鎖之間的相容關係,造成一個事務需要等待另一個事務釋放其所佔用的資源的現象 稱為 阻塞

如何發現阻塞

mysql_8.0

SELECT waiting_pid as '被阻塞的執行緒',
       waiting_query as '被阻塞的SQL',
       blocking_pid as '阻塞執行緒',
       blocking_query as '阻塞SQL',
       waiting_age as '阻塞時間',
       sql_kill_blocking_query as '建議操作'
FROM
		sys.innodb_lock_waits
WHERE
		( UNIX_TIMESTAMP() - UNIX_TIMESTAMPP(wait_started) ) > 30;

這裡的 30 是三十秒的意思

如何處理阻塞

  1. 終止佔用資源的事務(治標不治本)
  2. 優化佔用資源事務的SQL,使其儘快釋放資源

什麼是死鎖

並行執行的多個事務相互之間佔有了對方所需要的資源

比如:

事務一
BEGIN;
Update course set score = 9.7 where course_id = 35;
update user set score = score - 10 where user_id = 10;
事務二
BEGIN;
update user set score = score + 10 where user_id = 10;
Update course set score = 9.8 where course_id = 35;

由於事務一和事務二 where條件一致,在一定的條件下會導致死鎖,比如事務一在執行第一條sql時對該資源加排他鎖,同時事務二對另一資源加上了排他鎖,當兩個事務在執行它們的第二條SQL時,會分別等待對方的排他鎖釋放,導致死鎖發生

如何發現死鎖

將死鎖記錄到錯誤日誌中
set global innodb_print_all_deadlocks = on;
死鎖日誌例子(整理後):
TRANSACTION 1704, ACTIVE 119 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MYSQL thread id 12, OS thread handle 14025222817xxxxx, query id 170 localhost root update
update imc_user set score = score + 10 where user_id = 10

這裡記錄的可能不是導致產生死鎖的那個SQL, 而是事務中發生死鎖時正在執行的那個SQL,所以還是根據這個線索去程式中尋找問題的癥結所在

如何處理事務的死鎖

1. mysql 在發生死鎖時會自行回滾佔用資源少的事務(但這樣就影響到了業務,治標不治本)

2. 將發現的造成死鎖的事務程式碼按相同的順序去佔用資源,資源可以將死鎖降為阻塞