我们希望防止数据库中的某些并发问题(我们使用事件源,并希望在事件有效的情况下将事件插入事件日志)。
问题是,我们需要检查是否允许某个操作(在php中需要SELECT查询和某些检查),然后运行INSERT查询才能实际执行该操作。
现在,我们可以简单地锁定整个表,进行检查,如果它们成功,则插入(并移除锁)。
这样做的问题是,它锁定了整个表,这太过分了(这个表上会有很多查询)。我想要做的是锁定所有希望对特定object_id执行select-insert操作的查询,但允许对所有其他object_id's的查询继续进行,就好像没有锁一样。
我搜索了一下,但是找不到锁属性命令。在innoDB中似乎有一个锁行命令,但这并不是我们真正想要的(我想我不能百分之百确定它能做什么)。当然,我们可以尝试手动处理锁(检查某个单独的锁表中是否存在带有object_id的列,然后等待直到没有),但这感觉有点可疑,而且容易出错。
因此,实际的问题是:是否可以为列的特定值(object_id)锁定表?如果锁只保存在特定的SELECT-INSERT查询中,而不是针对独立SELECT的查询,那就太棒了,但是现在这并没有多大关系。
发布于 2015-09-29 11:42:17
考虑使用GET_LOCK()的手动任意锁;
选择特定于要锁定的行的名称。例如'xxx_event_id_y'。其中'xxx'是特定于过程和表的字符串,'y'是事件id。
调用SELECT GET_LOCK('xxx_event_id_y',30)锁定名称'xxx_event_id_y'..。如果名称可用,它将返回1并设置锁;如果30秒后锁不可用,则返回0(第二个参数是超时)。
当您完成时使用DO RELEASE_LOCK('xxx_event_id_y')。
请注意,您必须在每个事务中使用与您想要等待的相同的名称,并且在事务中再次调用GET_LOCK()将释放先前设置的锁。
docs
实际上,我也使用这个方法来锁定我们的应用程序缓存(即使它不使用DB),所以它在数据库之外也有作用域。
发布于 2015-09-29 11:48:19
如果尚未完成,则将表迁移到innodb,并使用事务。
https://stackoverflow.com/questions/32841633
复制相似问题