日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

10、MySQL锁等待,死锁,死锁检测

發布時間:2025/3/20 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 10、MySQL锁等待,死锁,死锁检测 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用數據庫時,有時會出現死鎖。對于實際應用來說,就是出現系統卡頓。

死鎖是指兩個或兩個以上的事務在執行過程中,因爭奪資源而造成的一種互相等待的現象。就是所謂的鎖資源請求產生了回路現象,即死循環,此時稱系統處于死鎖狀態或系統產生了死鎖。常見的報錯信息為“Deadlock found when trying to get lock...”。

上圖中,很明顯是右側的四輛汽車造成了死鎖。

死鎖發生以后,只有部分或完全回滾其中一個事務,才能打破死鎖。多數情況下只需要重新執行因死鎖回滾的事務即可。下面我們通過一個實例來了解死鎖是如何產生的。

例 1
為了方便讀者閱讀,操作之前我們先查詢 tb_student 表的數據和表結構。

mysql> SELECT * FROM tb_student; +----+------+------+------+------+ | id | name | age | sex | num | +----+------+------+------+------+ | 1 | 張三 | 31 || 4 | | 2 | 李四 | 28 || 4 | | 3 | 王五 | 13 || 4 | | 4 | 張四 | 13 || 4 | | 5 | 王四 | 15 || 4 | | 6 | 趙六 | 12 || 4 | +----+------+------+------+------+ 6 rows in set (0.01 sec) mysql> DESC tb_student; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(4) | NO | PRI | NULL | auto_increment | | name | varchar(25) | NO | | NULL | | | age | int(11) | YES | MUL | NULL | | | sex | char(1) | YES | | NULL | | | num | int(11) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 5 rows in set (0.00 sec)

以下操作需要打開兩個會話窗口,即下面所提到的 A窗口和 B窗口。

在 A窗口中執行以下命令:

mysql> BEGIN; mysql> UPDATE tb_student SET num=5 WHERE age=13;

緊接著在 B窗口中執行以下命令。由于 age 是索引字段,與 A窗口中更新的是不同行的數據,所以這時不會出現鎖等待現象。

mysql> BEGIN; mysql> UPDATE tb_student SET num=8 WHERE age=15;

然后在 A窗口中,執行以下命令,這時就會出現鎖等待現象了。

mysql> UPDATE tb_student SET num=10 WHERE age=15;

最后在 B窗口中,執行以下命令,這時會出現相互等待資源的現象,也就是死鎖現象。

mysql> UPDATE tb_student SET num=12 WHERE age=13; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

我們可以通過 SHOW ENGINE INNODB STATUS 命令查看死鎖的信息,運行結果如下(這里只展示了部分信息):

LATEST DETECTED DEADLOCK ------------------------ 2020-08-24 16:22:23 0x3944 *** (1) TRANSACTION: TRANSACTION 22656, ACTIVE 108 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 5 lock struct(s), heap size 1136, 6 row lock(s), undo log entries 2 MySQL thread id 33, OS thread handle 8808, query id 1689 localhost ::1 root updating UPDATE tb_student SET num=10 WHERE age=15 *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 197 page no 8 n bits 80 index index_age of table `test`.`tb_student` trx id 22656 lock_mode X waiting Record lock, heap no 5 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 0: len 4; hex 8000000f; asc ;; 1: len 4; hex 80000005; asc ;; ......

通過以上日志,我們就能確定造成死鎖的事務和 SQL 語句。

死鎖檢測

InnoDB 的并發寫操作會觸發死鎖,同時 InnoDB 也提供了死鎖檢測機制。通過設置 innodb_deadlock_detect 參數的值來控制是否打開死鎖檢測。

  • innodb_deadlock_detect = ON:默認值,打開死鎖檢測。數據庫發生死鎖時,系統會自動回滾其中的某一個事務,讓其它事務可以繼續執行。
  • innodb_deadlock_detect = OFF:關閉死鎖檢測。發生死鎖時,系統會用鎖等待來處理。

鎖等待是指在事務過程中產生的鎖,其它事務需要等待上一個事務釋放鎖,才能占用該資源。如果該事務一直不釋放,就需要持續等待下去,直到超過了鎖等待時間。當超過鎖等待允許的最大時間,就會出現死鎖,然后當前事務執行失敗,自動執行回滾操作。

MySQL 通過 innodb_lock_wait_timeout 參數控制鎖等待的時間,單位是秒。

mysql> SHOW VARIABLES LIKE '%innodb_lock_wait%'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_lock_wait_timeout | 120 | +--------------------------+-------+ 1 row in set, 1 warning (0.02 sec)

在實際應用中,我們要盡量防止鎖等待現象的發生,下面介紹幾種避免死鎖的方法:

  • 如果不同程序會并發存取多個表,或者涉及多行記錄時,盡量約定以相同的順序訪問表,這樣可以大大降低死鎖的發生。
  • 業務中要及時提交或者回滾事務,可減少死鎖產生的概率。
  • 在同一個事務中,盡可能做到一次鎖定所需要的所有資源,減少死鎖產生概率。
  • 對于非常容易產生死鎖的業務部分,可以嘗試使用升級鎖粒度,通過表鎖定來減少死鎖產生的概率(表級鎖不會產生死鎖)。

總結

以上是生活随笔為你收集整理的10、MySQL锁等待,死锁,死锁检测的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。