Mic*_*oel 7 mysql deadlock parallelism isolation-level
在多个并行批处理中运行处理作业,它基本上读取大块行以更新一些行 - 这里可以使用较低的事务级别,因为我知道在此任务运行时不会更新相关值,因此在调用每个存储之前我运行的过程:
set session transaction isolation level read uncommitted
然后调用存储过程,它获取要处理的 ID 子集。整体操作的SQLFiddle:http ://sqlfiddle.com/#!9/192d62 (有点做作但保持原始查询的结构)
我问的原因是死锁继续发生并查看监视器输出,有一个线程请求共享锁,而另一个线程在同一空间上持有排他锁(反之亦然)-不应设置该事务级别来阻止需要对于共享锁?除了 之外,还有其他理由获得共享锁repeatable-read吗?
使用 InnoDB。
相关锁信息来自show engine innodb status(编辑以匹配来自 SQLFiddle 的表名):
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 481628 page no 24944 n bits 112 index `PRIMARY` of table `events` trx id 27740892 lock mode S locks rec but not gap waiting
Run Code Online (Sandbox Code Playgroud)
和
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 481628 page no 24944 n bits 112 index `PRIMARY` of table `events` trx id 27740898 lock_mode X locks rec but not gap waiting
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 481628 page no 25267 n bits 112 index `PRIMARY` of table `events` trx id 27740898 lock_mode X locks rec but not gap waiting
Run Code Online (Sandbox Code Playgroud)
请注意,SQLFiddle 中的查询 1 和 2 匹配引擎输出中的第一个和第二个条目。的PRIMARY关键是仅在所述id柱(如可在小提琴可以看出)
“读取块,但只更新其中的一些”......
SELECT a chunk -- separate transaction, don't care about locking, etc
munch on that chunk to figure out the 'few' ids to update
BEGIN;
SELECT ... WHERE id IN (list of the few) FOR UPDATE;
minimal other work
UPDATE them;
COMMIT; -- plus checks for deadlocks, etc, and restart the code.
Run Code Online (Sandbox Code Playgroud)
这个想法是从事务中提取尽可能多的耗时代码,从而使事务更快,从而最大限度地减少冲突的可能性。(不,它可能不会消除所有僵局,但它应该有所帮助。)
另请注意:如果可能,请在所有线程中以相同的顺序浏览该表。当一个线程运行id IN (1,2)而另一个线程运行时,就会发生死锁IN (2,1)。如果两者都这样做IN (1,2),那么就会出现延迟,而不是僵局。
另一个提示:让块变小。