我在inndob表上有一个恒定的'select ...for update‘查询流。
主要条件是它选择'column1‘小于100的所有字段。
在后台,有一些常量插入正在进行,这可能涉及到'column1‘小于100的插入,但这不是问题。如果第一个select for update未命中它,因为它发生在执行查询时,或者正在获取结果数组时,下一个select for update将捕获它,我很高兴将第一个查询标记为未命中,因为它“太晚了”。
如果我有10个这样的'select for update‘查询在等待,因为inndob字段锁定,我应该自己处理它们的排队,还是让数据库来排序?我认为处理这个问题的正确方法是自己对查询进行排队?
所以当脚本到达
$sql = "SELECT * FROM ... FOR UDPATE"事先,检查队列数组(?),如果队列数组不为空,则将此脚本调用放在队列数组的末尾,然后每隔几毫秒检查一次队列数组,直到它达到队列中的第1号?
我的想法是正确的吗?重要的是,我现在就把它弄对了,而不是以后再回来。
编辑:有什么我可以添加的东西来增加回复的可能性:)
发布于 2013-05-15 07:09:01
InnoDB应该会为您处理排队。如果有一个事务正在处理相关行上的锁,那么第二个事务试图用另一个SELECT FOR UPDATE语句获取相同的锁,那么第二个语句将一直等到第一个事务提交。
你可以自己测试一下:
START TRANSACTION。SELECT ... FOR UPDATE。然后,SHOW ENGINE INNODB STATUS并观察事务及其锁。您应该会看到输出中包含类似以下内容:每个会话的事务列表:-TRANSACTION 3B17,ACTIVE 4 sec starting index read MySQL tables in use 1,locked 1 lock WAIT 2 LOCK struct(s),heap size 376,1 row lock(s) mysql线程id 2,OS线程句柄0x7ff27ae2d700,查询id 28 192.168.56.1 root select data select* from FOR id < 100用于更新- trx已等待4秒等待授予此锁:记录锁定空间id 266页no 3 n位72表test的索引PRIMARY。foo trx id 3B17 lock_mode X waiting表test的索引PRIMARY。事务事务id 3B17事务X等待-事务3B16,活动70秒2锁结构,堆大小376,2行锁MySQL线程id 1,OS线程句柄0x7ff27ae6e700,查询id 29 192.168.56.1根显示引擎innodb状态表锁表test。foo trx id 3B16锁模式IX记录锁空间id 266页no 3 n位72表PRIMARY表test。foo trx id 3B16 lock_mode X
请注意,在上面,事务3B16持有锁,而事务3B17正在等待锁。
事务3B16显示它当前正在运行"show engine innodb status“,但它仍然持有在之前的SELECT中获得的锁...用于更新。即使该语句已完成,事务仍未完成,并且在事务完成时将释放锁。
如果事务3B17等待的时间超过lock_wait_timeout秒,并且第一个事务仍未提交或回滚,则等待语句将放弃并产生以下错误:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionhttps://stackoverflow.com/questions/16552291
复制相似问题