mysql 死锁检查
今天看了一篇关于死锁检查的blog.
Advanced InnoDB Deadlock Troubleshooting – What SHOW INNODB STATUS Doesn’t Tell You, and What Diagnostics You Should be Looking At
One common cause for deadlocks when using InnoDB tables is from the existence of foreign key constraints and the shared locks (S-lock) they acquire on referenced rows.
The reason I want to discuss them though is because they are often a bit tricky to diagnose, especially if you are only looking at the SHOW ENGINE INNODB STATUS output (which might be a bit counter-intuitive since one would expect it to contain this info).
Let me show a deadlock error to illustrate (below is from SHOW ENGINE INNODB STATUS\g):
------------------------
LATEST DETECTED DEADLOCK
------------------------
111109 20:10:03
*** (1) TRANSACTION:
TRANSACTION 65839, ACTIVE 19 sec, OS thread id 4264 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 6 lock struct(s), heap size 1024, 3 row lock(s), undo log entries 1
MySQL thread id 3, query id 74 localhost 127.0.0.1 root Updating
UPDATE parent SET age=age+1 WHERE id=1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6833 page no 3 n bits 72 index `PRIMARY` of table
`test`.`parent` trx id 65839 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 *** (2) TRANSACTION:
TRANSACTION 65838, ACTIVE 26 sec, OS thread id 768 starting index read,
thread declared inside InnoDB 500
mysql tables in use 1, locked 1
7 lock struct(s), heap size 1024, 4 row lock(s), undo log entries 2
MySQL thread id 4, query id 75 localhost 127.0.0.1 root Updating
UPDATE parent SET age=age+1 WHERE id=2
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 6833 page no 3 n bits 72 index `PRIMARY` of table
`test`.`parent` trx id 65838 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6833 page no 3 n bits 72 index `PRIMARY` of table
`test`.`parent` trx id 65838 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 *** WE ROLL BACK TRANSACTION (1)
Now, we do see a lot about what caused the deadlock above, but we are only seeing *half* of the picture.
Allow me to explain ..
First of all, note transaction #1 has been running for 19 seconds, while transaction #2 for 26 seconds. So, the output is referring to the newer transaction as #1 and the older as #2 (also somewhat counter-intuitive, but good to be aware of).
Now, what we can see clearly is this:
Transaction #1 (“UPDATE parent .. WHERE id=1″) is waiting on a lock from Transaction #2 (“UPDATE parent .. WHERE id=2″).
Thus TX #2 holds a lock (RECORD LOCKS space id 6833 page no 3 n bits 72 index, heap no 2), but is waiting on (RECORD LOCKS space id 6833 page no 3 n bits 72 index, heap no 3 – held by TX #1).
Clearly the 2 updates should not cause a conflict in and of themselves. Thus we know something must have happened earlier in the transaction(s).
For reference, here is how to reproduce it:
CREATE TABLE `parent` (
`id` INT NOT NULL AUTO_INCREMENT,
`age` INT NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB; CREATE TABLE `child` (
`id` INT NOT NULL AUTO_INCREMENT,
`age` INT NOT NULL,
`parent_id` INT NOT NULL,
PRIMARY KEY (`id`),
KEY `parent_id` (`parent_id`),
CONSTRAINT `fk_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)
) ENGINE=InnoDB; INSERT INTO parent (id, age) VALUES (1, 50);
INSERT INTO parent (id, age) VALUES (2, 60);
INSERT INTO child (id, age, parent_id) VALUES (1, 20, 1);
INSERT INTO child (id, age, parent_id) VALUES (2, 20, 1);
Then, open 2 connections (T1 and T2 – note order is opposite compared to what is shown in SHOW INNODB STATUS):
T1:
BEGIN;
UPDATE child SET age=age+1, parent_id=2 WHERE id=1;
UPDATE parent SET age=age+1 WHERE id=1;
T2:
BEGIN;
UPDATE child SET age=age+1, parent_id=2 WHERE id=2;
UPDATE parent SET age=age+1 WHERE id=1;
<-- T2 Hangs
T1:
UPDATE parent SET age=age+1 WHERE id=2;
<-- Deadlock (T1 completes, T2 is rolled back)
But why does this deadlock? Well, it is due to the foreign key. In fact, this example would not deadlock at all if no foreign key was defined on `parent`.`id`.
So then what exactly is preventing T2 from completing?
Here is what is happening behind the scenes, so-to-speak:
T1#1:
Obtains the following 2 locks:
X lock on `child` where id=1 <-- due to the actual "UPDATE child" statement itself
S lock on `parent` where id=2 <-- due to the FK on parent.id
(Note this S lock means other S locks can be obtained on this row, but not X locks -- which is the crux of this issue).
T1#2:
Obtains the following lock:
X lock on `parent` where id=1 <-- due to the actual "UPDATE parent" statement itself
T2#1:
Obtains the following 2 locks:
X lock on `child` where id=2 <-- due to the actual "UPDATE child" statement itself
S lock on `parent` where id=2 <-- due to the FK (again, this is okay since it is also a S-lock)
T2#2:
Tries to obtain the following, but hangs due to the existing X-lock from T1#2:
X lock on parent where id=1
T1#3:
Tries to obtain the following lock:
X lock on parent where id=2
However, since there are 2 S-locks on this row already (one from T1 and T2), and T1 now wants an X-lock on the same row, then there is a conflict.
Now this would normally just wait for the S-locks to be released, but since T2 is already "hung" waiting on the other lock to be released from T1, we now have the deadlock.
T1 wins the dispute, T2 rolls back thus releasing its locks, and T1 completes.
So all in all, quite a bit is going on there, but you only see about half of this information from the LATEST DETECTED DEADLOCK section of SHOW ENGINE INNODB STATUS output. And had I not posted the SHOW CREATE TABLE status (and prior tx statements), it'd be unclear as to what happened exactly.
Well, so how do you find out exactly what happened when locking problems happen to you?
SHOW INNODB STATUS only tells you so much. Furthermore, once the deadlock occurs, the winner moves on, and the loser is rolled back. *Meaning*, there is no longer any information about these "transactions" in the output as they are in the "past" now.
Therefore, in general, if you're having any locking issues (deadlocks, lock wait timeouts, hangs due to semaphore waits, and so forth), do yourself a favor and capture all of the following outputs at the time, if possible, to give you the best likelihood in tracking down the issue:
- SHOW ENGINE INNODB STATUS
- This is generally very good, but it can get truncated, and simply may not contain every bit of info you need.
- Enable InnoDB Lock Monitor (enable the InnODb Lock Monitor by simply creating any innodb table named innodb_lock_monitor)
- This logs a lot of extra lock information in the SHOW ENGINE INNODB STATUS output, but it can get truncated too.
- Run "mysqladmin debug"
- Logs all lock info to the error log. Great because it logs all locks (i.e., none truncated) and it logs LOCK TABLE locks, which do not appear in SHOW INNODB STATUS even if on an InnoDB table, because LOCK TABLE is external to the InnoDB storage engine. Not so great because a bit cryptic to read, and I wouldn't solely reply on it, as it's often most helpful in conjuntion with other details).
- SHOW FULL PROCESSLIST
- This will show all connected threads. Specifically, when it comes to 'hidden' locks, it would show a user that has been connected, but idle (but who could have issued a LOCK TABLE command).
- Error log
- Of course, always check out the error log for messages and/or anything out of the ordinary. (Not to mention extra data will be logged to it from "mysqladmin debug" and innodb_lock_monitor.)
- SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS, INNODB_LOCK_WAITS, and INNODB_TRX tables
- This is only available as of MySQL 5.1 and newer (and you must be using the InnoDB Plugin), but since most of you will be running this, they contain great information. In fact, I've written a past post on Debugging InnoDB Locks using the new InnoDB Plugin’s Information Schema Tables which contains even more details on using these 3 tables for troubleshooting.
- SHOW CREATE TABLE outputs for each table involved
结合之前看何登成的技术blog.自己有以下几点总结:
1、要尽力让自己的更新、删除、查询操作走索引。一方面索引可以提高查询效率,另一方面可以减少对不必要的记录加锁。
2、要注意repeatable-read 这种事务隔离级别下的间隙锁,如果业务上允许虚幻度的现象发生,则可以考虑使用read-commited事务隔离级别。
3、业务上要注意sql加锁的顺序,保证多个事务不要用不一致的顺序对记录加锁。而且要注意分析二级索引带来的对聚簇索引(即主键索引)的隐含加锁问题。可以参考这里的分析:http://hedengcheng.com/?p=771
4、业务上少用或者不用lock in share mode ,for update 这样的显示加锁,而应该尽量走快照读。
5、写sql时,注意用explain命令分析执行计划,能走索引的走索引,能走覆盖索引的走覆盖索引(避免查询出不必要的列)。
但是目前还没有找到比较好用的死锁检测工具,这块正在研究中。。。
前面blog介绍的比较好用的是SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS, INNODB_LOCK_WAITS, and INNODB_TRX tables
这个sql,查询锁的信息,正在学习中。。
mysql 死锁检查的更多相关文章
- mysql死锁检查
1.查看当前数据库进程 show processlist; show full processlist; #前者只显示前100条,后者显示所有的进程 2.一键杀死某个用户的所有进程 select ...
- MySQL 死锁问题分析
转载: MySQL 死锁问题分析 线上某服务时不时报出如下异常(大约一天二十多次):"Deadlock found when trying to get lock;". Oh, M ...
- Mysql死锁问题解决方式 & 聚簇索引、隔离级别等知识
参考了这篇文章:http://www.cnblogs.com/LBSer/p/5183300.html <mysql死锁问题分析> 写的不错. 如果Mysql死锁,会报出: 1.1 死锁 ...
- 【错误记录】flask mysql 死锁
最近使用flask-sqlalchemy时,进行测试的时候发现日志中打印出了MySql死锁错误,查看Mysql日志发现是因为有俩条sql出现了死锁: Deadlock found when tryin ...
- Mysql死锁如何排查:insert on duplicate死锁一次排查分析过程
前言 遇到Mysql死锁问题,我们应该怎么排查分析呢?之前线上出现一个insert on duplicate死锁问题,本文将基于这个死锁问题,分享排查分析过程,希望对大家有帮助. 死锁案发还原 表结构 ...
- Mysql 死锁分析
1. 结论 死锁检查机制 当事务A需要获取一个行锁时(例如更新一行数据),假如需要获取行1的锁 检查其他事务有没有已获取了行1的锁. 如果有,例如事务B已获取了行1的锁. 继续检查事务B在等待的锁,如 ...
- 为什么MySQL死锁检测会严重降低TPS
在大量的客户端,更新数据表的同一行时,会造成数据库的吞吐量大幅降低. 很多数据库的前辈和同行分别通过实验和源码的方法,定位到了罪魁祸首----MySQL死锁检测 实验方式:http://blog.cs ...
- Mysql 死锁问题
Innodb锁系统(4) Insert/Delete 锁处理及死锁示例分析 http://mysqllover.com/?p=431 关于innodb死锁 http://afei2.sinaapp.c ...
- 一次MySQL死锁问题解决
一次MySQL死锁问题解决 一.环境 CentOS, MySQL 5.6.21-70, JPA 问题场景:系统有定时批量更新数据状态操作,每次更新上千条记录,表中总记录数约为500W左右. 二.错误日 ...
随机推荐
- IIS、SQL SERVER和VS的安装顺序
正确安装顺序:先安装IIS,再安装SQL SERVER,最后安装VS. 如果先安装VS后安装的IIS,则需要找到对应的.net framework目录下,执行aspnet_regiis.exe,重新注 ...
- sp.ui.rte.js参数错误
出现这个错误的原因是,在新建页面我用spd隐藏了两行不需要的填写的控件. 去掉这两个隐藏属性就可以了.
- Android编程: fragment组件、菜单和Intent组件
学习内容:fragment组件.菜单和Intent组件 ====fragment组件====1.fragment是一种自我容纳,模块化的,嵌入在一个Activity里面的视图组件 可以在运行时动 ...
- iOS开发HTTPS实现之信任SSL证书和自签名证书
iOS开发HTTPS实现之信任SSL证书和自签名证书 转自:http://www.jianshu.com/p/6b9c8bd5005a/comments/5539345 (收录一下供自己学习用的) 字 ...
- linux下的clock skew detected
今天在虚拟机上用GCC编译一个程序的时候,出现了下面的错误: make: warning: Clock skew detected. Your build may be incomplete 试了ma ...
- 软件工程随堂小作业——随机四则运算Ⅱ之算法思路(C++)
1.题目避免重复: (1)利用系统时间来产生随机数,重复率会降低. (2)建立链表,逐个判断.可读取写入文件. 2.可定制(数量/打印方式): (1)格式有默认值; (2)可以选择重新设置分几列和每行 ...
- android 怎么动态设置button 的style
网上找了很多,还是没有直接的解决办法,button没有setstyle这个方法.因此我的解决办法如下: 直接动态设置各个属性 Button themeBtn = new Button(this); t ...
- 《JavaScript高级程序设计》第4章 变量、作用域和内存问题
4.1 基本类型和引用类型 5种基本类型:Undefined.Null.Boolean.Number和String,这5种基本类型是按值访问的,因为可以操作保存在变量中的实际的值. 引用类型:可能由多 ...
- bzoj 3293 数学整理
和1045一模一样,找到这道题的时候还愣了下神,最后发现样例都是 一样的,直接粘了1045的代码,具体题解看 http://www.cnblogs.com/BLADEVIL/p/3468729.htm ...
- short-path problem (Spfa) 分类: ACM TYPE 2014-09-02 00:30 103人阅读 评论(0) 收藏
#include <cstdio> #include <iostream> #include <cstring> #include <queue> #i ...