2014-01-29 53 views
1

我有两个表:一个存储数据,另一个存储锁以指示用户何时使用该数据。我想从第一个表中选择一些项目,以使它们符合多个条件,并且在另一个表中没有相应的锁定,然后将这些项目的锁定添加到第二个表格。由于许多用户可能会同时尝试锁定物品,因此有必要以原子方式完成此操作。将INSERT ... SELECT语句原子化为

我已经写了下面的SQL语句来尝试这样做,但我收到错误Deadlock found when trying to get lock;

INSERT INTO table2 (id, user, date) 
    SELECT id, ?, NOW() 
    FROM table1 
    LEFT JOIN table2 USING id 
    WHERE locked IS NULL AND <several conditions on table1> 
    ORDER BY date 'DESC' 
    LIMIT 15; 

有什么办法可以使这个原子操作没有锁定表吗?目前我正在使用一个事务,如果它不成功,就重新尝试,但是我对这是否可以避免感兴趣。我在InnoDB上使用MySQL版本5.0.95。

感谢

编辑

已经给出一些这方面的进一步的思考,我意识到,虽然锁定表1是不可接受的,我可以锁定表2。由于我实际上无法锁定表中的表(因为如果选择锁定其中一个表,我必须锁定所有表),我可以使用GET_LOCK创建互斥锁,以防止多个进程同时调用此代码。我还没有机会测试这种方法,但感觉它可能是比事务更轻量级的解决方案。

+0

与您的问题无关,但如果锁定是table2中的字段,则必须将其上的过滤器从where子句移至join子句。否则,你实际上有一个内部联接。 –

+0

由于我不知道不同类型的连接,因此我肯定需要详细了解连接如何工作。如果第一个表中的大部分项目都有相应的锁,我认为您的建议可以提高性能?由于表2通常是空的,它是否提供任何其他好处? – tgt

回答

1

不,这是交易的全部内容。他们在组织了一堆陈述,一个原子操作成功或失败的整体。

Here你能找到乐观pesimistic锁,也许你能找到一些有用的解释。你可以在InnoDB中找到一些关于锁定机制的细节(pesimistic locking)。 Here你可以找到关于如何在mysql中实现乐观锁定的指导。

希望我帮了忙!