Mysql InnoDb中的锁定等待超时
我创建了一个mysql表,其中(date、name、id、money_-spend)列的主键是(date、name、id)(因为这种组合总是唯一的),InnoDb是存储引擎 日期-日期数据类型, 姓名-瓦尔查尔(30), id-varchar(100) 我有一个逻辑,即在多个更新查询中并行触发。对于Eg(现在考虑这两个) T1: T2: 并行运行这2个事务会导致T2超时,因为T1获得了锁 事务隔离级别-可重复读取隔离级别 InnoDb引擎状态Mysql InnoDb中的锁定等待超时,mysql,indexing,innodb,Mysql,Indexing,Innodb,我创建了一个mysql表,其中(date、name、id、money_-spend)列的主键是(date、name、id)(因为这种组合总是唯一的),InnoDb是存储引擎 日期-日期数据类型, 姓名-瓦尔查尔(30), id-varchar(100) 我有一个逻辑,即在多个更新查询中并行触发。对于Eg(现在考虑这两个) T1: T2: 并行运行这2个事务会导致T2超时,因为T1获得了锁 事务隔离级别-可重复读取隔离级别 InnoDb引擎状态 LOCK WAIT 19543 lock stru
LOCK WAIT 19543 lock struct(s), heap size 376, 1407774 row lock(s)
MySQL thread id 105402, OS thread handle 0x2ba11d68a700, query id 16862373 10.11.3.212 connect-dev Sending data
update test_database.users set money_spend = 1005 where date between "2020-01-01" and "2020-01-10" and name = "Tammy";
------- TRX HAS BEEN WAITING 2 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 154606 page no 243093 n bits 78 index `PRIMARY` of table `test_database`.`users` trx id 44023639357 lock_mode X waiting
Record lock, heap no 78 PHYSICAL RECORD: n_fields 30; compact format; info bits 0
0: len=3; bufptr=0x2b9fea4e2d5e; hex= 8fc95b; asc [;;
1: len=8; bufptr=0x2b9fea4e2d61; hex= 4170706e65787573; asc John;;
2: len=8; bufptr=0x2b9fea4e2d69; hex= 3230393835373832; asc 20985782;;
3: len=6; bufptr=0x2b9fea4e2d71; hex= 000a3f47ff22; asc ?G ";;
4: len=7; bufptr=0x2b9fea4e2d77; hex= 0f011040350d5b; asc @5 [;;
从innoDb的状态来看,T2似乎在试图获取一个以“John”为名称的记录的锁,但由于以“John”为名称的记录已经被T1锁定,T2超时
问题:既然InnoDb支持行级锁定,事务(T1)不应该只对日期介于“2020-01-01”和“2020-01-10”之间且名称为“John”的记录获取锁定。既然索引的名称部分不同(T2的名称为“Tammy”),为什么它会给T2事务一个暂停时间将主键重新排列为
主键(名称、日期、id)
。这样,所需的所有行(在任一查询中)都将在表中相邻。这比分散行(使用(日期、名称等)
)更有效
加快查询速度将帮助一个查询在另一个查询可能与之冲突之前完成
使行连续可以避免某些“间隙锁定”情况。(我不知道这是否与此相关,但似乎与此相关。)
使用=
测试的列需要位于“范围测试”之前
更多索引提示:
如果
id
是一个AUTO_INCREMENT
,那么模式是“让我们先在主键中放置一些列,以加速一些查询,然后在末尾添加id
,以确保它是唯一的(我不知道这是否是您正在做的;但这与当前的讨论无关。)将主键重新排列为主键(名称、日期、id)
。这样,所有需要的行(在任一查询中)都将在表中相邻。这比分散行(使用(日期、名称,…)
更有效
加快查询速度将帮助一个查询在另一个查询可能与之冲突之前完成
让行连续可以避免一些“间隙锁定”的情况(我不知道这是否与此相关,但似乎与此相关)
使用=
测试的列需要位于“范围测试”之前
更多索引提示:
如果
id
是一个AUTO_INCREMENT
,那么模式是“让我们先在主键中放置一些列以加快某些查询,然后在末尾添加id
,以确保它是唯一的。(我不知道这是否是您正在做的;但这与当前的讨论无关。)表中有哪些索引?@Shadow only primary(日期、名称、id)。没有任何辅助项。日期、名称和id是索引中字段的确切顺序吗?@Shadow yes这是确切顺序。似乎索引的名称部分在锁定中被忽略了。说明中的键长度是多少?表上有哪些索引?@Shadow only primary(日期、名称、id)。没有任何辅助项。日期、名称和id是索引中字段的确切顺序吗?@Shadow yes这是确切顺序。似乎索引的名称部分在锁定中被忽略了。“解释”中的键长度是什么?您能否在这个答案中添加mysql文档或性能博客中的参考?如果能了解范围查找如何影响索引使用,那就太好了@影子-我怀疑我简单的一句话经验法则是否在文档中明确说明。同时,我的博客基于索引和搜索的工作原理。(所以,我承认我的博客不是一个“性能博客”。)你能在这个答案中添加mysql文档或性能博客的引用吗?如果能了解范围查找如何影响索引使用,那就太好了@影子-我怀疑我简单的一句话经验法则是否在文档中明确说明。同时,我的博客基于索引和搜索的工作原理。(因此,我承认我的博客不是一个“性能博客”。)
update test_database.users set money_spend = 1005
where date between "2020-01-01" and "2020-01-10"
and name = "Tammy";
LOCK WAIT 19543 lock struct(s), heap size 376, 1407774 row lock(s)
MySQL thread id 105402, OS thread handle 0x2ba11d68a700, query id 16862373 10.11.3.212 connect-dev Sending data
update test_database.users set money_spend = 1005 where date between "2020-01-01" and "2020-01-10" and name = "Tammy";
------- TRX HAS BEEN WAITING 2 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 154606 page no 243093 n bits 78 index `PRIMARY` of table `test_database`.`users` trx id 44023639357 lock_mode X waiting
Record lock, heap no 78 PHYSICAL RECORD: n_fields 30; compact format; info bits 0
0: len=3; bufptr=0x2b9fea4e2d5e; hex= 8fc95b; asc [;;
1: len=8; bufptr=0x2b9fea4e2d61; hex= 4170706e65787573; asc John;;
2: len=8; bufptr=0x2b9fea4e2d69; hex= 3230393835373832; asc 20985782;;
3: len=6; bufptr=0x2b9fea4e2d71; hex= 000a3f47ff22; asc ?G ";;
4: len=7; bufptr=0x2b9fea4e2d77; hex= 0f011040350d5b; asc @5 [;;