我有一个表COMMANDS,用户可以同时插入数据。
每次插入后,我必须进行一些(耗时的)计算,并将结果保存到另一个表RESULTS中。
同时,所有用户也会从COMMANDS中读取数据。
我的问题是:
在插入新的$command之后,我在计算中使用该表中的所有行。每一行都会影响计算,也可能会影响以前的$commands,因为我想锁定这个表以进行新的插入,直到当前计算完成并保存结果。但我也不想阻止其他用户查看COMMANDS的当前状态。
不久,我想要锁定一个表以供写入,而不锁定以供读取。
我使用的是InnoDB引擎。我读了一些关于锁定的文档,但我完全搞混了。
共享和排他锁,意向锁,缝隙锁...
这看起来很愚蠢,但目前我正在使用下面这样的机制
public function storeNewCommand($command){
// $busy_flag is an app level global that can be read by all user sessions
if($busy_flag){
usleep(10000);
return $this->storeNewCommand($command);
}
$busy_flag = true; //(lock)
/*
...insert new $command to COMMANDS
...do calculations using all comands including last one
...store results in RESULTS
*/
$busy_flag = false; //(unlock)
}我知道一定有更好、更聪明的解决方案来解决这个问题,而不需要循环和睡眠。但我不知道该用哪一个。
发布于 2017-10-19 00:52:37
如果您可以在少于lock_wait_timeout的时间内完成冗长的工作,那么可以使用BEGIN...COMMIT。(就我个人而言,我会将其限制在2秒内,而不是50秒。)
否则,设计一些其他的方法--有一个每个作者都尊重的表,说你在这个“关键部分”是“忙”的。它可能不需要多于1列或2列的单行表格。
在获取互斥锁时,请确保将fetch、set等封装在事务中,并对失败做出反应。在获得锁之后,然后继续执行较慢的操作。最后释放锁。
注意:如果发生崩溃或软件错误,释放锁的代码可能永远不会执行。因此,最好包括一个时间戳,再加上一些需要注意的东西,即互斥锁已经很长一段时间没有被释放了。它可以让他们给你发邮件告诉你这个问题,并清除锁。
https://stackoverflow.com/questions/46814716
复制相似问题