mysqldeletein死锁_deleteupdatewhere…in语句导致死锁问题分析

更新时间:2023-06-22 22:25:54 阅读: 评论:0

mysqldeletein死锁_deleteupdatewhere…in语句导致死锁问题
分析
1、问题描述
测试中发现delete\update语句在并发测试时经常会导致发⽣死锁。
2、问题分析
在mariadb中,update或delete使⽤ where(…,…,…) in (…,…,..) 的写法会导致全表扫描,加⼤锁冲突的概率,造成死锁。
例1:
MySQL
MariaDB [lzk]> show create table b\G
*************************** 1. row ***************************
Table: b
Create Table: CREATE TABLE `b` (
`a` int(11) NOT NULL DEFAULT '0',
`b` int(11) NOT NULL DEFAULT '0',
`c` int(11) NOT NULL DEFAULT '0',
`d` int(11) NOT NULL DEFAULT '0',
`e` int(11) NOT NULL DEFAULT '0',
`f` int(11) DEFAULT NULL,
PRIMARY KEY (`a`,`b`,`c`,`d`,`e`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
MariaDB [lzk]> explain delete from b where a=1 and b=2 and c=1 and d=1 and e=1;
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | lect_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | b | range | PRIMARY | PRIMARY | 20 | NULL | 1 | Using where |
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in t (0.00 c) --直接根据主键定位到记录
MariaDB [lzk]> explain delete from b where (a,b,c,d,e) in ((1,1,1,1,1));
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | lect_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+溥仪墓
| 1 | SIMPLE | b | ALL | NULL | NULL | NULL | NULL | 18 | Using where |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in t (0.00 c) --全表扫描
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
MariaDB[lzk]>showcreatetableb\G
***************************1.row*************************** Table:b
CreateTable:CREATETABLE`b`(
`a`int(11)NOT NULLDEFAULT'0',
`b`int(11)NOT NULLDEFAULT'0',
`c`int(11)NOT NULLDEFAULT'0',
`d`int(11)NOT NULLDEFAULT'0',
虾仁玉子豆腐`e`int(11)NOT NULLDEFAULT'0',
`f`int(11)DEFAULTNULL,
PRIMARY KEY(`a`,`b`,`c`,`d`,`e`)
)ENGINE=InnoDBDEFAULTCHARSET=utf8COLLATE=utf8_bin
MariaDB[lzk]>explaindeletefrombwherea=1andb=2andc=1andd=1ande=1;
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+ |id|lect_type|table|type|possible_keys|key|key_len|ref|rows|Extra|
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+ |1|SIMPLE|b|range|PRIMARY|PRIMARY|20|NULL|1|Usingwhere|
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+ 1rowint(0.00c)--直接根据主键定位到记录
MariaDB[lzk]>explaindeletefrombwhere(a,b,c,d,e)in((1,1,1,1,1));
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
|id|lect_type|table|type|possible_keys|key|key_len|ref|rows|Extra|
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
|1|SIMPLE|b|ALL|NULL|NULL|NULL|NULL|18|Usingwhere|
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
1rowint(0.00c)--全表扫描
场景1:
当会话1:start transaction;
delete from b where (a,b,c,d,e) in ((1,1,1,1,1));
会话2:start transaction;
delete from b where (a,b,c,d,e) in ((1,1,2,1,1));
此时会话2会产⽣锁等待。
⽽场景2:
当会话1:start transaction;
联通怎么查流量delete from b where where a=1 and b=1 and c=1 and d=1 and e=1;
会话2:start transaction;
delete from b where where a=1 and b=1 and c=2 and d=1 and e=1;
不会产⽣锁等待。
例2:
MySQL
MariaDB [test]> explain update b t c='qwe' where (a,b) in ((1,10));
+------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| id  | lect_type | table | type  | possible_keys | key    | key_len | ref  | rows    | Extra      |
+------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
|    1 | SIMPLE      | b    | index | NULL          | PRIMARY | 8      | NULL | 9278400 | Using where | +------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
1 row in t (0.00 c)--全索引扫描
MariaDB [test]> explain update b t c='qwe' where a=1 and b=10;
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id  | lect_type | table | type  | possible_keys | key    | key_len | ref  | rows | Extra      |
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|    1 | SIMPLE      | b    | range | PRIMARY      | PRIMARY | 8      | NULL |    1 | Using where |
时尚围巾
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in t (0.00 c)--直接根据主键定位到记录
1
2
3
4
5
6
7
费列罗热量
8
9
10
11
鼻子肥大
12
13
14
15
MariaDB[test]>explainupdatebtc='qwe'where(a,b)in((1,10));
+------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
|id  |lect_type|table|type |possible_keys|key    |key_len|ref |rows  |Extra      |
+------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
|  1|SIMPLE    |b    |index|NULL        |PRIMARY|8      |NULL|9278400|Usingwhere|
+------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
1rowint(0.00c)--全索引扫描
MariaDB[test]>explainupdatebtc='qwe'wherea=1andb=10;
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|id  |lect_type|table|type |possible_keys|key    |key_len|ref |rows|Extra      |
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1|SIMPLE    |b    |range|PRIMARY      |PRIMARY|8      |NULL|  1|Usingwhere|
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1rowint(0.00c)--直接根据主键定位到记录
3、解决办法
不使⽤delete\update where… in的写法,改为delete\update where … and …or
4、半⼀致性读仍会死锁问题
在read-committed隔离级别下,update会使⽤半⼀致性读,为什么还是有⼏率发⽣死锁?
根据场景复现后,show engine innodb status查看死锁信息,发现发⽣死锁的事务会占有很多锁,不符合innodb半⼀致读的特性:
MySQL
------------------------
LATEST DETECTED DEADLOCK
------------------------
2016-03-30 15:19:46 7f79e7fec700
*** (1) TRANSACTION:
TRANSACTION 132876, ACTIVE 9 c fetching rows
mysql tables in u 1, locked 1
LOCK WAIT 252 lock struct(s), heap size 96696, 226 row lock(s), undo log entries 1
MySQL thread id 5, OS thread handle 0x7f79e8bb5700, query id 15 redhat64-26 10.47.160.26 root updating
update test.c t c = '94414' where (a,b) in ((1,'5167'))
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
劳动协议书范本RECORD LOCKS space id 6 page no 6 n bits 496 index `PRIMARY` of table `test`.`c` trx id 132876 lock_mode X locks rec but not gap waiting
Record lock, heap no 211 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
0: len 4; hex 80000001; asc    ;;
射手座图片
1: len 4; hex 80000358; asc    X;;
2: len 6; hex 00000000c7fb; asc      ;;
3: len 7; hex 06000001671e10; asc    g  ;;

本文发布于:2023-06-22 22:25:54,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1016558.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:死锁   问题   导致   等待
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图