部分锁定特定属性的表

时间:2015-09-29 10:29:55

标签: php mysql locking

我们希望防止数据库中的某些并发问题(我们使用事件源并希望在事件是有效事件时将事件插入事件日志中。)

问题是我们需要检查是否允许某个操作(需要SELECT查询和php中的一些检查),然后运行INSERT查询以实际执行操作。

现在,我们可以简单地锁定整个表,执行检查,如果成功,则插入(并删除锁定)。

这个问题是它会锁定整个表,这是一种过度杀伤(这个表上会有很多查询)。我想要做的是锁定所有想要为特定object_id执行此选择插入操作的查询,但允许对所有其他object_id's的查询继续,就像没有锁定一样。< / p>

我搜索了一下但找不到锁属性命令。在innoDB中似乎有一个锁定行命令,但它并不是我们想要的(我想我不是100%确定它的作用)。 我们当然可以尝试手动处理锁(在某个单独的锁定表中检查是否存在带object_id的列,并等待直到没有),但这感觉有点腥和容易出错。

所以,这是实际的问题:是否可以为列的特定值(object_id)锁定表? 如果锁定仅针对特定的SELECT-INSERT查询而不是针对独立的SELECT,那将是非常棒的,但现在这并不重要。

2 个答案:

答案 0 :(得分:2)

考虑使用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()将释放先前设置的锁。

GET_LOCK() docs

我实际上也使用这种方法来锁定我们的应用程序缓存(即使它不使用数据库),所以它也有数据库以外的范围。

答案 1 :(得分:0)

如果尚未将表迁移到innodb,则使用事务。