mysql 什么情况下出现mysql死锁解决方法

博客访问: 54756
博文数量: 15
博客积分: 58
博客等级: 民兵
技术积分: 246
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: Mysql/postgreSQL
MySQL 死锁信息解读
什么是死锁?
《数据库系统概念》一书中对死锁的描述:如果存在一个事务集,该集合中的每个事务在等待该集合中的另一个事务,那么我们说系统处于死锁状态。更确切的说,存在一个等待事务集{T0,T1,T2…Tn},其中T0在等待T1锁住的数据项,T1正在等待T2锁住的数据项,……,Tn-1正等待Tn锁住的数据项,且Tn正等待T0锁住的数据项。这种情况下,没有一个事务能取得进展。
为什么会一直等下去?
因为事务加锁是遵循”两阶段封锁协议(two-phase locking protocol)”的,即只有在事务结束(commit或者rollback)时,才会释放整个事务加的所有锁。
两阶段封锁协议要求每个事务分两个阶段提出加锁和解锁请求:
a.&&&&&& 增长阶段(growing phase):事务可以获得锁,但不能释放锁;
b.&&&&&& 缩减阶段(shrinking phase):事务可以释放锁,但不能获得新锁;
&& 两阶段封锁协议作用是什么?
&& 在并发事务的情况下,保证事务执行的串行化。
死锁的处理
死锁处理通常有两种方法:
a.&&&&&& 死锁预防(deadlock prevention): 保证系统永远不进入死锁状态;
b.&&&&&& 死锁检测(deadlock detection)及死锁恢复(deadlock recovery): 允许系统进入死锁状态,然后试用死多检测和死锁恢复机制进行恢复。
&& 很容易看出,这两种方法都会引起事务回滚。具体以上两种方法的原理,请参考《数据库系统概念》一书,在此不多解释。
MySQL在死锁的处理上采用的是死锁检测,当检测到死锁后,选择其中代价较少的一个事务进行回滚。
MySQL5.6版本之前,死锁只能通过SHOW
ENGINE INNODB STATUS命令,查看最后的一个死锁信息。当然可以定期采集死锁信息记录在某个文件中,Percona的pt-deadlock-logger工具可实现。MySQL5.6版本,有个新的参数innodb_print_all_deadlocks,可以控制将所有死锁信息输出到mysqld的error日志文件中。
补充:比较好的习惯是,在应用中捕获deadlock error(MySQL error no. 1213)并且重试事务。
如何阅读MySQL死锁信息
MySQL 死锁发生的前提是多于2个事务互相等待锁,但是INNODB
STATUS中LATEST DETECTED DEADLOCK信息只有最后2个事务的信息。另外,死锁信息中也只记录了最后执行的sql语句,没有记录的sql语句可能才是真正持有或请求锁的语句。所以,分析死锁还需要从代码层面根据死锁记录的sql语句找完整的事务sql语句。另外,持有锁的事务一般是第二个事务。
接下来,我们通过几个例子来看看mysql 记录的死锁信息里面都有些什么信息。
例子1:Percona版本
1.------------------------
2.LATEST DETECTED DEADLOCK
3.------------------------
4. 05:17:38
7f7bdb9a9700
5.*** (1) TRANSACTION:
6.TRANSACTION 2332, ACTIVE
158 sec starting index read
7.mysql tables in use 1,
8.LOCK WAIT 3 lock struct(s),
heap size 360, 2 row lock(s)
9.MySQL thread id 2, OS
thread handle 0x7f7bdb9ea700, query id 39 localhost root updating
10.*** (1) WAITING FOR THIS
LOCK TO BE GRANTED:
11.RECORD LOCKS space id 11
page no 3 n bits 80 index `PRIMARY` of table `yxb`.`deadlock_test` trx id
2332 lock_mode X locks rec but not gap waiting
12.*** (2) TRANSACTION:
13.TRANSACTION 2333, ACTIVE 96
sec starting index read
14.mysql tables in use 1,
15.3 lock struct(s), heap size
360, 2 row lock(s), undo log entries 1
16.MySQL thread id 3, OS
thread handle 0x7f7bdb9a9700, query id 40 localhost root updating
17.delete from deadlock_test
where id=1
18.*** (2) HOLDS THE LOCK(S):
19.RECORD LOCKS space id 11
page no 3 n bits 80 index `PRIMARY` of table `yxb`.`deadlock_test` trx id
2333 lock_mode X locks rec but not gap
20.*** (2) WAITING FOR THIS
LOCK TO BE GRANTED:
21.RECORD LOCKS space id 11
page no 3 n bits 80 index `PRIMARY` of table `yxb`.`deadlock_test` trx id
2333 lock_mode X locks rec but not gap waiting
22.*** WE ROLL BACK TRANSACTION
1-3行:最后的死锁信息标题;
4行:& 死锁发生时间;
5&12行: 事务信息开始标记;
6&13行:事务id,事务持续时间,事务状态;
7&14行:当前sql使用的表数目,tables
in use 1并非代表该事务仅涉及到1个表,可能是多个表,只是当前sql只操作一个表;
8&15行:该行信息要多关注,n row
lock(s)表示该事务有多少个行锁,undo log entries n代表有多少数据修改(多少条undo信息,delete,update会产生undo,insert不会),n lock struct(s)代表有多少个锁结构,(意向表锁IX或IS锁算一个,然后一个page上的所有X锁或者S算都只各算一个),该信息可以看出涉及的数据分布的page多少(),可以通过这些数据知道事务的复杂性;
9&16行:thread id和mysql账号信息;
10&11行:该事务在等待在什么位置加什么锁,RECORD
LOCKS space id 11 page no 3 n bits 80 index `PRIMARY` of table
`yxb`.`deadlock_test` trx id 2332 lock_mode X locks rec but not gap waiting
RECORD LOCKS表示记录锁;
b)space id 11 是指innodb表空间的id号,如果id为0,则表示使用的是共享表空间,在innodb_file_per_table情况下,每个独立表空间有自己的space id号;
no 3, 指该锁是在第3个page上;
`PRIMARY` of table `yxb`.`deadlock_test` trx id 2332 lock_mode X locks rec but not
gap,表示id为2332的事务等待在yxb.deadlock_test表的主键上加X 锁,并非间隙锁;
&& 如果是S锁,产生S锁的情况有以下几种:
use of SELECT … LOCK IN SHARE MODE
2) on foreign key referenced record(s)
3) with INSERT INTO… SELECT, shared locks on source table
12行:事务信息开始标记;
17行:发生死锁时第二个事务里面的最后一个sql;
18&19行:该事务持有的锁,正是第一个事务想要请求的锁;
20&21行:等待的锁信息;
22行:指出哪个事务被回滚;
现在对死锁信息的内容基本都说清楚什么意思了。那么我们来分析下,上面这个死锁。
1)& 事务2在`yxb`.`deadlock_test`表的主键上持有X 锁,但是该X锁不是事务2里面的SQL:delete from
deadlock_test where id=1所加的锁,而是事务2里面的其他语句加的锁;
2)& 事务1在等待对`yxb`.`deadlock_test`的主键上加X锁,但是该锁已经被事务2持有,所以该加锁过程被阻塞,需要等待事务1中该锁释放;
3)& 事务2 SQL:delete from
deadlock_test where id=1要对id=1的主键上加锁,但是该加锁请求被阻塞,因为事务1已经对id=1的主键上加了锁(S|X锁都有可能);
4)& 因为遵循两阶段封锁协议,事务的锁之后在commit或rollback的时候,才会释放,不会在事务中途释放,所以事务1和事务2进入互相等待的死循环,产生死锁;
例子2:MySQL社区版,每个记录锁会将记录内容打印出来。
10:41:12 7f6f912d7700
2 *** (1) TRANSACTION:
3 TRANSACTION 2164000, ACTIVE 27 sec
starting index read
4 mysql tables in use 1, locked 1
5 LOCK WAIT 3 lock struct(s), heap size
360, 2 row lock(s), undo log entries 1
6 MySQL thread id 9, OS thread handle
0x7f6f, query id 87 localhost ro ot updating
7 update t1 set name = 'b' where id = 3
8 *** (1) WAITING FOR THIS LOCK TO BE
9 RECORD LOCKS space id 1704 page no 3
n bits 72 index `PRIMARY` of table `tes t`.`t1` trx id 2164000 lock_mode X
locks rec but not gap waiting
10 Record lock, heap no 4 PHYSICAL
RECORD: n_fields 5; info bit s 0
11 0: len 4; hex ;;
12 1: len 6; hex ; asc !
13 2: len 7; hex
14 3: len 4; hex ;;
15 4: len 1; hex 63;;
17 *** (2) TRANSACTION:
18 TRANSACTION 2164001, ACTIVE 18 sec
starting index read
19 mysql tables in use 1, locked 1
20 3 lock struct(s), heap size 360, 2
row lock(s), undo log entries 1
21 MySQL thread id 10, OS thread handle
0x7f6f912d7700, query id 88 localhost r oot updating
22 update t1 set name = 'c' where id =
23 *** (2) HOLDS THE LOCK(S):
24 RECORD LOCKS space id 1704 page no 3
n bits 72 index `PRIMARY` of table `tes t`.`t1` trx id 2164001 lock_mode X
locks rec but not gap
25 Record lock, heap no 4 PHYSICAL
RECORD: n_fields 5; info bit s 0
26 0: len 4; hex ;;
27 1: len 6; hex ; asc !
28 2: len 7; hex
29 3: len 4; hex ;;
30 4: len 1; hex 63;;
32 *** (2) WAITING FOR THIS LOCK TO BE
33 RECORD LOCKS space id 1704 page no 3
n bits 72 index `PRIMARY` of table `tes t`.`t1` trx id 2164001 lock_mode X
locks rec but not gap waiting
34 Record lock, heap no 3 PHYSICAL
RECORD: n_fields 5; info bit s 0
35 0: len 4; hex ;;
36 1: len 6; hex ; asc ! ;;
37 2: len 7; hex f5;;
38 3: len 4; hex ;;
39 4: len 1; hex 62;;
社区版本和Percona版本相比会将记录锁对应的内容打印出来。
以这个为例,说明下各行代表的意思。
11 0: len 4; hex ;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //cluster index(主键),去掉最高位8,值是3;
12 1: len 6; hex ; asc ! !;;&&&&&&&&&&&&&&&&&& //最新修改这个记录的事务id,转化成十进制是2164001&;
13 2: len 7; hex
asc ! ;;&&&&&&&&&&&&&&&& //rollback point,指向undo log;
14 3: len 4; hex ;;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //从该行以下是各个字段的值;
15 4: len 1; hex 63;;
如何避免死锁?
a)&&&&&& 降低事务复杂度,一个事务里包含太多sql,在高并发情况下很容易产生死锁,所以避免使用复杂的大事务;
b)&&&&&& 不要使用外键,唯一键不要过于长、复杂;
c)&&&&&& 如果是因为GAP 锁导致的死锁,那么可以将事务隔离级别修改为RC避免GAP锁解决;
a)&&&&&& 死锁的概念;
b)&&&&&& 应用需要捕捉死锁错误,当发现死锁时进行事务重试;
c)&&&&&& MySQL 死锁信息分析;
d)&&&&&& 避免死锁的方法;
e)&&&&&& 还有一个很重要的点,就是了解MySQL加锁的原理,什么时候加什么锁,这个登博文章说的再清楚不过了:;
《数据库系统概念第五版》
阅读(1514) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。比特客户端
您的位置:
详解大数据
详解大数据
详解大数据
详解大数据
MySQL死锁分析及解决的方法
  死锁问题的相关知识是本文我们主要要介绍的内容,接下来我们就来一一介绍这部分内容,希望能够对您有所帮助。
  1、MySQL常用引擎的锁机制
  MyISAM和MEMORY采用表级锁(table-level locking)
  BDB采用页面锁(page-level locking)或表级锁,默认为页面锁
  InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁
  2、各种锁特点
  表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低
  行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高
  页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
  3、各种锁的适用场景
  表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用
  行级锁则更适合于有大量按索引条件并发更新数据,同时又有并发查询的应用,如一些在线事务处理系统
  4、死锁
  是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
  表级锁不会产生死锁。所以解决死锁主要还是针对于最常用的InnoDB。
  5、死锁举例分析
  在MySQL中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果sql语句操作了主键索引,MySQL就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。
  在UPDATE、DELETE操作时,MySQL不仅锁定WHERE条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的next-key locking。
  例如,一个表db。tab_test,结构如下:
  id:主键;
  state:状态;
  time:时间;
  索引:idx_1(state,time)
  出现死锁日志如下:
  ?***(1) TRANSACTION:
  ?TRANSACTION 0 , ACTIVE 0 sec, process no 11393, thread id 278546 starting index read
  ?mysql tables in use 1, locked 1
  ?LOCK WAIT 3 lock struct(s), heap size 320
  ?MySQL thread id 83, query id
dcnet03 dcnet Searching rows for update
  ?update tab_test set state=1064,time=now() where state=1061 and time & date_sub(now(), INTERVAL 30 minute) (任务1的sql语句)
  ?***(1) WAITING FOR THIS LOCK TO BE GRANTED: (任务1等待的索引记录)
  ?RECORD LOCKS space id 0 page no 849384 n bits 208 index `PRIMARY` of table `db/tab_test` trx id 0
_mode X locks rec but not gap waiting
  ?Record lock, heap no 92 PHYSICAL RECORD: n_fields 11; info bits 0
  ?0: len 8; hex 629c;; 1: len 6; hex
asc (; 2: len 7; hex 10; asc @ ;; 3: len 8; hex 50b2; asc P ;; 4: len 8; hex 502a; asc P*;; 5: len 8; hex 5426; asc T&;; 6: len 8; hex d29c; asc A,; 7: len 23; hex e636f6d2f6 870; /;; 8: len 8; hex 042b; asc +;; 9: len 4; hex 474bfa2b; asc GK +;; 10: len 8; hex 4e24; asc N$;;
  ?*** (2) TRANSACTION:
  ?TRANSACTION 0 , ACTIVE 0 sec, process no 11397, OS thread id 344086 updating or deleting, thread declared inside InnoDB 499
  ?mysql tables in use 1, locked 1
  ?3 lock struct(s), heap size 320, undo log entries 1
  ?MySQL thread id 84, query id
dcnet03 dcnet Updating update tab_test set state=1067,time=now () where id in (9921180) (任务2的sql语句)
  ?*** (2) HOLDS THE LOCK(S): (任务2已获得的锁)
  ?RECORD LOCKS space id 0 page no 849384 n bits 208 index `PRIMARY` of table `db/tab_test` trx id 0
lock_mode X locks rec but not gap
  ?Record lock, heap no 92 PHYSICAL RECORD: n_fields 11; info bits 0
  ?0: len 8; hex 629c;; 1: len 6; hex
asc (; 2: len 7; hex 10; asc @ ;; 3: len 8; hex 50b2; asc P ;; 4: len 8; hex 502a; asc P*;; 5: len 8; hex 5426; asc T&;; 6: len 8; hex d29c; asc A,; 7: len 23; hex e636f6d2f6 870; /hand.; 8: len 8; hex 042b; asc +;; 9: len 4; hex 474bfa2b; asc GK +;; 10: len 8; hex 4e24; asc N$;;
  ?*** (2) WAITING FOR THIS LOCK TO BE GRANTED: (任务2等待的锁)
  ?RECORD LOCKS space id 0 page no 843102 n bits 600 index `idx_1` of table `db/tab_test` trx id 0
lock_mode X locks rec but not gap waiting
  ?Record lock, heap no 395 PHYSICAL RECORD: n_fields 3; info bits 0
  ?0: len 8; hex 0425; asc %;; 1: len 8; hex d29c; asc A,; 2: len 8; hex 629c;;
  ?*** WE ROLL BACK TRANSACTION (1)
  ?(回滚了任务1,以解除死锁)
  原因分析:
  当“update tab_test set state=1064,time=now() where state=1061 and time & date_sub(now(), INTERVAL 30 minute)”执行时,MySQL会使用idx_1索引,因此首先锁定相关的索引记录,因为idx_1是非主键索引,为执行该语句,MySQL还会锁定主键索引。
  假设“update tab_test set state=1067,time=now () where id in (9921180)”几乎同时执行时,本语句首先锁定主键索引,由于需要更新state的值,所以还需要锁定idx_1的某些索引记录。
  这样第一条语句锁定了idx_1的记录,等待主键索引,而第二条语句则锁定了主键索引记录,而等待idx_1的记录,这样死锁就产生了。
  6、解决办法
  拆分第一条sql,先查出符合条件的主键值,再按照主键更新记录:
  ?select id from tab_test where state=1061 and time & date_sub(now(), INTERVAL 30 minute);
  ?update tab_test state=1064,time=now() where id in(......);
  关于MySQL死锁问题的实例分析及解决方法就介绍到这里了,希望本次的介绍能够对您有所收获!
[ 责任编辑:之极 ]
去年,手机江湖里的竞争格局还是…
甲骨文的云战略已经完成第一阶段…
软件信息化周刊
比特软件信息化周刊提供以数据库、操作系统和管理软件为重点的全面软件信息化产业热点、应用方案推荐、实用技巧分享等。以最新的软件资讯,最新的软件技巧,最新的软件与服务业内动态来为IT用户找到软捷径。
商务办公周刊
比特商务周刊是一个及行业资讯、深度分析、企业导购等为一体的综合性周刊。其中,与中国计量科学研究院合力打造的比特实验室可以为商业用户提供最权威的采购指南。是企业用户不可缺少的智选周刊!
比特网络周刊向企业网管员以及网络技术和产品使用者提供关于网络产业动态、技术热点、组网、建网、网络管理、网络运维等最新技术和实用技巧,帮助网管答疑解惑,成为网管好帮手。
服务器周刊
比特服务器周刊作为比特网的重点频道之一,主要关注x86服务器,RISC架构服务器以及高性能计算机行业的产品及发展动态。通过最独到的编辑观点和业界动态分析,让您第一时间了解服务器行业的趋势。
比特存储周刊长期以来,为读者提供企业存储领域高质量的原创内容,及时、全面的资讯、技术、方案以及案例文章,力求成为业界领先的存储媒体。比特存储周刊始终致力于用户的企业信息化建设、存储业务、数据保护与容灾构建以及数据管理部署等方面服务。
比特安全周刊通过专业的信息安全内容建设,为企业级用户打造最具商业价值的信息沟通平台,并为安全厂商提供多层面、多维度的媒体宣传手段。与其他同类网站信息安全内容相比,比特安全周刊运作模式更加独立,对信息安全界的动态新闻更新更快。
新闻中心热点推荐
新闻中心以独特视角精选一周内最具影响力的行业重大事件或圈内精彩故事,为企业级用户打造重点突出,可读性强,商业价值高的信息共享平台;同时为互联网、IT业界及通信厂商提供一条精准快捷,渗透力强,覆盖面广的媒体传播途径。
云计算周刊
比特云计算周刊关注云计算产业热点技术应用与趋势发展,全方位报道云计算领域最新动态。为用户与企业架设起沟通交流平台。包括IaaS、PaaS、SaaS各种不同的服务类型以及相关的安全与管理内容介绍。
CIO俱乐部周刊
比特CIO俱乐部周刊以大量高端CIO沙龙或专题研讨会以及对明星CIO的深入采访为依托,汇聚中国500强CIO的集体智慧。旨为中国杰出的CIO提供一个良好的互融互通 、促进交流的平台,并持续提供丰富的资讯和服务,探讨信息化建设,推动中国信息化发展引领CIO未来职业发展。
IT专家新闻邮件长期以来,以定向、分众、整合的商业模式,为企业IT专业人士以及IT系统采购决策者提供高质量的原创内容,包括IT新闻、评论、专家答疑、技巧和白皮书。此外,IT专家网还为读者提供包括咨询、社区、论坛、线下会议、读者沙龙等多种服务。
X周刊是一份IT人的技术娱乐周刊,给用户实时传递I最新T资讯、IT段子、技术技巧、畅销书籍,同时用户还能参与我们推荐的互动游戏,给广大的IT技术人士忙碌工作之余带来轻松休闲一刻。
微信扫一扫
关注Chinabyte> 博客详情
1、查询是否锁表show OPEN TABLES where In_use & 0;
2、查询进程
&&&&show processlist&&查询到相对应的进程===然后 kill&&&&id
查看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;&
查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;&
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥博客分类:
先了解一下什么是GAP LOCK
在INNODB中,record-level lock大致有三种:Record, Gap, and Next-KeyLocks。简单的说,RECORDLOCK就是锁住某一行记录;而GAPLOCK会锁住某一段范围中的记录;NEXT-KEYLOCK则是前两者加起来的效果。
下面是MYSQL官方文档中相关内容的链接
有资料里说MYSQL的GAP LOCK最初是为了避免Phantom (幻象读)的问题,关于幻象读这里就不多做解释了,可以参考如下链接
可是毕竟GAPLOCK导致了锁定范围的增大,在某些情况下可能会造成一些不符合预期的现象。下面是一个简单的测试例子,先对GAP LOCK有个感性的认识
mysql& desc ts_column_log_test
+------------+-------------+------+-----+---------------------+----------------+
| Null | Key |Default
+------------+-------------+------+-----+---------------------+----------------+
| PRI |NULL
| auto_increment |
| MUL |NULL
| start_time | timestamp
| end_time
|timestamp
| 0:00:00|
| data_time
| timestamp
|varchar(30) | NO
+------------+-------------+------+-----+---------------------+----------------+
6 rows in set (0.01 sec)
mysql& select * from ts_column_log_
+----+--------+---------------------+---------------------+---------------------+---------+
| id | col_id |start_time
|data_time
+----+--------+---------------------+---------------------+---------------------+---------+
11:51:11 |
11:51:11 |
00:00:00 | running |
20 | 11:51:16 |
11:51:16 |
00:00:00 | running |
120 | 11:51:20 |
11:51:20 |
00:00:00 | running |
+----+--------+---------------------+---------------------+---------------------+---------+
3 rows in set (0.00 sec)
开启两个不同的会话,分别执行一些语句观察一下结果:
mysql& set autocommit=0;
mysql& delete from ts_column_log_testwhere col_id=10;
Query OK, 0 rows affected (0.00sec)
--此时[2,20)这个区间内的记录都已经被GAP LOCK锁住了,如果在其他事务中尝试插入这些值,则会等待
mysql& set autocommit=0;
mysql& INSERT INTO ts_column_log_test(col_id, start_time, end_time, data_time, status) VALUES (1, NULL, NULL,'', 'running');
mysql& INSERT INTO ts_column_log_test(col_id, start_time, end_time, data_time, status) VALUES (2, NULL, NULL,'', 'running');
mysql& INSERT INTO ts_column_log_test(col_id, start_time, end_time, data_time, status) VALUES (19, NULL, NULL,'', 'running');
上面的实验很简单,大家可以自己测一下。这里解释一下会产生这种现象的原因:session1中的delete语句中指定条件where col_id=10,这时MYSQL会去扫描索引,但是这个时候delete语句获取的不是一个RECORD LOCK,而是一个NEXT-KEY LOCK。以当前值(10)为例,会向左扫描至col_id=2这条记录,向右扫描至col_id=20这条记录,锁定区间为前闭后开,即[2,20)。
下面是摘自官方手册里的一句话:
DELETE FROM ... WHERE ... sets an exclusivenext-key lock on every record the search encounters.
下面的链接里面有INNODB中各种不同的语句可能持有哪些锁的解释
明白了GAPLOCK是怎么回事,下面看下可能产生的问题吧
有时候我们会多个进程或线程并行的对同一张表进行操作,并且使用了事务,那么就可能会有问题,举个例子:
delete from ts_column_log_test wherecol_id=10;
INSERT INTO ts_column_log_test (col_id,start_time, end_time, data_time, status) VALUES (10, NULL, NULL, '','running');
delete from ts_column_log_test wherecol_id=11;
INSERT INTO ts_column_log_test (col_id,start_time, end_time, data_time, status) VALUES (11, NULL, NULL, '','running');
假设上面是你程序的两个进程需要做的操作,在没有并发的情况下,可能运行正常,因为每个事务在MYSQL中最终都是串行执行,中间并没有其他事务同时进行;可并发高了以后,可能在MYSQL中实际运行的语句顺序就会变成下面这个样子:
10:00:00 delete from ts_column_log_test wherecol_id=10;
0:00:00 delete from ts_column_log_test where col_id=11;
10:00:00 INSERT INTO ts_column_log_test (col_id,start_time, end_time, data_time, status) VALUES (10, NULL, NULL, '','running');
0:00:00 INSERT INTO ts_column_log_test (col_id, start_time, end_time,data_time, status) VALUES (11, NULL, NULL, '', 'running');
这个时候,你可能就会得到错误提示ERROR ): Deadlock found wh try restarting transaction。
原因是前两条语句都已经获得了[2,20)这个区间内记录的S锁,然后两个事务又分别对该区间段内的col_id=10这个位置请求X锁,这时就发生死锁,谁都请求不到X锁,因为互相都持有S锁。
解决方案有两种
1、改变程序中数据库操作的逻辑
2、取消GAP LOCK机制
Gap locking can be disabled explicitly.This occurs if you change the transaction isolation level to READ COMMITTED orenable the innodb_locks_unsafe_for_binlog system variable.
浏览: 1439785 次
来自: 杭州
leibnitz 写道hi,我想知道,无论在92还是94版本, ...
hi,我想知道,无论在92还是94版本,更新时(如Puts)都 ...
不错,谢谢!
不错,谢谢!
tengyizu 写道大牛怎么解决的啊
我也遇到这样的问题
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 mysql 模拟死锁 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信