MySQL會發生死鎖嗎?


SHOW ENGINE INNODB STATUS;來查看死鎖日志:

SHOW PROCESSLIST;查看進程

MySQL的InnoDB引擎事務有4種隔離級別,主要是為了保證數據的一致性。

InnoDB引擎提供了行級鎖,表鎖。MyISAM提供了表鎖,如題,MySQL會發生死鎖嗎?

會,在InnoDB引擎下,RR(REPEATABLE-READ)級別,如果多個事務爭搶同一個資源,會發生死鎖。在RR級別下,MySQL提供了next-key lock。假如一個索引的行有10,11,13,20
那么可能的next-key lock的包括:
(無窮小, 10]
(10,11]
(11,13]
(13,20]
(20, 無窮大)

即:當你查詢12時,如果數據未查到,那么將對(12,13]范圍內的數據進行鎖定。next-key lock的定義可以到官方具體查看,這里做個演示。

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(200) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1111 DEFAULT CHARSET=utf8; 
 
image-20190304142624761
//查看隔離級別, show variables like '%tx_isolation%'; // 設置隔離界別 SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE} // 不設置自動提交 SET autocommit = 0; 

死鎖演示

  1. 首先將隔離級別都設置為RR級別的,並且不讓事務自動提交
  2. 根據上面的數據,在事務1中查詢
// 得到空結果集,此時鎖定的范圍是(33,100] select * FROM user where id=33 for update; 
  1. 在事務2中也進行查詢
// 查詢到空的結果,在事務2中鎖定的范圍是(34,100] select * FROM user where id=34 for update 
  1. 在事務1中插入數據
// 雖然事務1鎖定了范圍,事務2也鎖定了范圍 insert into user values(35,'ac',10); 
 
image-20190304143355381
  1. 在事務2中也插入數據
insert into user values(34,'ac',10) 
 
image-20190304143707234
  1. 可以發現已經發生了死鎖

解決辦法

  1. 設置死鎖的超時時長

innodb_lock_wait_timeout=500

  1. 查詢到當前正在鎖定的事務線程,將其殺死
// 可以看到正在運行的事務線程,還有運行狀態 SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; //trx_mysql_thread_id為上一條命令獲取的結果,將具體的數字替換一下即可。 kill trx_mysql_thread_id 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM