背景
上回书<<一个由mysql事务隔离级别造成的问题分析>>
说到, 有两个实例去更新一条记录, 一条成功, 一条失败. 成功的认为自己获取到的记录, 于是
开开心心的把任务进行处理, 但是在他试图将任务状态更新为处理成功时, 去发现任务被别人锁了...
具体问题
抢到任务的进程
2015-11-23 19:42:01|INFO|exec_task.php|40||get one task: 11
...
//开始处理
2015-11-23 19:42:01|INFO|exec_task.php|107||line_count: 9
2015-11-23 19:42:01|INFO|exec_task.php|147||fork child success: 8346
2015-11-23 19:42:01|INFO|exec_task.php|264||[0] pid: 8346, start: 0, stop: 0
2015-11-23 19:42:01|INFO|exec_task.php|147||fork child success: 8347
2015-11-23 19:42:01|INFO|exec_task.php|264||[1] pid: 8347, start: 1, stop: 1
2015-11-23 19:42:01|INFO|exec_task.php|147||fork child success: 8348
2015-11-23 19:42:01|INFO|exec_task.php|264||[2] pid: 8348, start: 2, stop: 2
2015-11-23 19:42:01|INFO|exec_task.php|147||fork child success: 8349
2015-11-23 19:42:01|INFO|exec_task.php|264||[3] pid: 8349, start: 3, stop: 3
2015-11-23 19:42:01|INFO|exec_task.php|147||fork child success: 8350
2015-11-23 19:42:01|INFO|exec_task.php|264||[4] pid: 8350, start: 4, stop: 4
...
2015-11-23 19:42:01|INFO|exec_task.php|159||child procss exit ,start to merge result file
//处理结束,更新状态,结果发现等待锁超时
2015-11-23 19:42:52|ERR|function.inc.php|113||SQL fail: Lock wait timeout exceeded; try restarting transaction
没有抢到任务的进程
2015-11-23 19:42:51|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:51|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
....
2015-11-23 19:42:52|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:53|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:53|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:53|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
2015-11-23 19:42:53|INFO|function.inc.php|100||task_id 11 is locked by another process, get next task
即由于没有抢到任务的进程在2015-11-23 19:42:52
的时候,正在死循环, 事务没有提交, 把记录给锁了, 所以抢到任务的进程
想把记录更新的时候, 出现等待锁超时.
一个事务没有提交,把记录锁了, 导致另一个事务无法更新, 听起来很正常对吧.
请注意, 没有抢到任务的进程并没有更新到task_id = 11
的记录,却把这个记录锁了.
问题重现
这个问题其实很好重现. 见以下操作记录:
表结构
create database if not exists ae;
create table ae.task (
id int primary key,
status int);
问题综述
在两个事务同时更新同一条记录的情况下, 一个事务因另一个事务将记录修改导致的条件不满足而更新不成功, 更新不成功的事务还是会把这条记录锁住.
来源:oschina
链接:https://my.oschina.net/u/97321/blog/535976