从MySQL documentation获取的共享模式中的选择锁定示例:
作为锁定读取有用的情况的示例,假设您要将新行插入表子项,并确保子行在表parent中具有父行。 假设您使用一致读取来读取父表,并确实在表中看到要插入的子行的父行。你能安全地将子行插入表子吗?不,因为其他会话有可能在此期间从表父级中删除父行,而不会意识到它。
解决方案是使用LOCK IN SHARE MODE:
以锁定模式执行SELECT<?php
DB::query("start transaction");
$q = DB::query("SELECT parentID FROM parent WHERE NAME = 'Jones'
LOCK IN SHARE MODE;");
if( count($q) === 1)
DB::query("insert into child set parentName = 'Jones', ... other data");
DB::query("commit;");
?>
SELECT ... LOCK IN SHARE MODE在任何读取的行上设置共享模式锁定。其他会话可以读取行,但在事务提交之前无法修改它们。
在我们执行查询 start transaction之后,如果代码执行失败(php错误,操作系统错误,电源故障......)会发生什么?从父级中选择parentID,其中name ='Jones' 锁定共享模式; 。行保持锁定多长时间以进行更新和删除?我想确保即使执行失败,该行也不会保持锁定状态(让我们说PHP失败但MySQL仍在运行)。 MySQL如何处理这种情况。我想在最坏的情况下,超时发生如下:
ERROR 1205(HY000):超出锁定等待超时;尝试重新启动交易
和MySQL解锁锁定的行。或者是否有更好的机制。
答案 0 :(得分:1)
如果错误导致连接关闭 - MySql回滚整个事务,并释放所有锁。
如果连接未关闭(电源故障,应用程序挂起等) - MySql将在wait_timeout
或interactive_timeout
个变量定义的时间后关闭连接。关闭连接会导致活动事务回滚,并释放所有锁定。
wait_timeout - &gt; http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout
interactive_timeout - &gt; http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_interactive_timeout