
如果我们的业务处于起步阶段,并且并发度很低,那么几年我们就不会遇到僵局问题. 相反,我们的业务并发度很高,然后不时爆发. 僵局的问题肯定使我们非常抓狂. 但是,当出现僵局问题时,许多没有经验的学生的第一反应就是成为一只鸵鸟: 这件事很深刻,我听不懂,顺其自然,这并非一直发生. 实际上,如果您仔细阅读了我们写的有关MySQL中语句锁定分析的三篇文章:
通过分析本文中的死锁日志,解决死锁问题应该不会那么令人困惑.
为了使故事顺利进行,我们需要构建一个表格:
CREATE TABLE hero ( id INT, name VARCHAR(100), country varchar(100), PRIMARY KEY (id), KEY idx_name (name)) Engine=InnoDB CHARSET=utf8;
我们为英雄表的id列创建了聚集索引,为name列创建了辅助索引. 该英雄表主要用于存储来自三个王国的一些英雄. 我们在表中插入一些记录:
INSERT INTO hero VALUES (1, 'l刘备', '蜀'), (3, 'z诸葛亮', '蜀'), (8, 'c曹操', '魏'), (15, 'x荀彧', '魏'), (20, 's孙权', '吴');

表中的数据现在如下所示:
mysql> SELECT * FROM hero;+----+------------+---------+| id | name | country |+----+------------+---------+| 1 | l刘备 | 蜀 || 3 | z诸葛亮 | 蜀 || 8 | c曹操 | 魏 || 15 | x荀彧 | 魏 || 20 | s孙权 | 吴 |+----+------------+---------+5 rows in set (0.00 sec)
您完成了.
我们首先创建一个发生死锁的场景,然后在会话A和会话B中执行两个事务死锁分析,如下所示:

让我们对其进行分析:

以上是从向语句中添加哪些锁来分析死锁情况的角度来看的,但是在实际应用中,我们甚至可能不知道最后有死锁的语句,我们需要根据MySQL进行死锁死锁日志发生锁定时,会反向定位导致死锁的语句,以优化我们的业务.
设计InnoDB的叔叔向我们提供了SHOW ENGINE INNODB STATUS命令,以查看有关InnoDB存储引擎的一些状态信息,包括最后一次死锁发生时系统的锁定状态. 当以上示例中出现死锁时,我们运行以下命令:
mysql> SHOW ENGINE INNODB STATUS\G...省略了好多其他信息------------------------LATEST DETECTED DEADLOCK------------------------2019-06-20 13:39:19 0x70000697e000*** (1) TRANSACTION:TRANSACTION 30477, ACTIVE 10 sec starting index readmysql tables in use 1, locked 1LOCK WAIT 3 lock struct(s), heap size 1160, 2 row lock(s)MySQL thread id 2, OS thread handle 123145412648960, query id 46 localhost 127.0.0.1 root statisticsselect * from hero where id = 3 for update*** (1) WAITING FOR THIS LOCK TO BE GRANTED:RECORD LOCKS space id 171 page no 3 n bits 72 index PRIMARY of table `dahaizi`.`hero` trx id 30477 lock_mode X locks rec but not gap waitingRecord lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000003; asc ;; 1: len 6; hex 000000007517; asc u ;; 2: len 7; hex 80000001d0011d; asc ;; 3: len 10; hex 7ae8afb8e8919be4baae; asc z ;; 4: len 3; hex e89c80; asc ;;*** (2) TRANSACTION:TRANSACTION 30478, ACTIVE 8 sec starting index readmysql tables in use 1, locked 13 lock struct(s), heap size 1160, 2 row lock(s)MySQL thread id 3, OS thread handle 123145412927488, query id 47 localhost 127.0.0.1 root statisticsselect * from hero where id = 1 for update*** (2) HOLDS THE LOCK(S):RECORD LOCKS space id 171 page no 3 n bits 72 index PRIMARY of table `dahaizi`.`hero` trx id 30478 lock_mode X locks rec but not gapRecord lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000003; asc ;; 1: len 6; hex 000000007517; asc u ;; 2: len 7; hex 80000001d0011d; asc ;; 3: len 10; hex 7ae8afb8e8919be4baae; asc z ;; 4: len 3; hex e89c80; asc ;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:RECORD LOCKS space id 171 page no 3 n bits 72 index PRIMARY of table `dahaizi`.`hero` trx id 30478 lock_mode X locks rec but not gap waitingRecord lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000001; asc ;; 1: len 6; hex 000000007517; asc u ;; 2: len 7; hex 80000001d00110; asc ;; 3: len 7; hex 6ce58898e5a487; asc l ;; 4: len 3; hex e89c80; asc ;;*** WE ROLL BACK TRANSACTION (2)------------...省略了好多其他信息
我们只关心最近发生的死锁信息,因此我们将分别分析和分析“最新检测到的死锁”部分. 让我们看一下此输出死锁日志的含义:
在查看死锁日志时,首先查看死锁事务正在等待获取锁语句的内容.
在此示例中,会话S被阻止的语句是:

select * from hero where id = 3 for update
会话B被阻止:
select * from hero where id = 1 for update
然后记住: 找出这两个语句在您自己的业务代码中所在的事务中的其他语句.
找到死锁事务中的所有语句后,根据有关事务获取的锁和正在等待的锁的信息来分析死锁发生过程.
从死锁日志中可以看出,SESSION A为英雄表集群索引上的id值为1的记录获得了类型X的严重记录锁(这实际上是从SESSION B等待的锁中获得的) ),查看SESSION A中的语句是由以下语句引起的(针对语句锁定分析了三篇文章):

select * from hero where id = 1 for update;
会话B还为英雄表上具有聚集索引id值为3的记录获得了X型规范记录锁定. 查看SESSION B中的语句死锁分析,发现该语句是由以下语句引起的. 文章):
select * from hero where id = 3 for update;
然后,SESSION A正在等待X型严重记录锁定,该锁定具有由以下语句引起的集群表索引id值为3的记录:
select * from hero where id = 3 for update;
然后,会话B正在等待X型严重记录锁定,以获取英雄表的ID索引为1的记录. 这是由以下语句引起的:
select * from hero where id = 1 for update;
然后根据死锁日志恢复整个死锁形成过程.
本文转载
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-151537-1.html
没办法
一是少数民族封建统治