用于PHP的数据库中立表锁定库

时间:2011-11-04 14:33:52

标签: php pdo propel race-condition table-locking

我有一个场景,我认为我需要针对所有活动(读取和写入)锁定一个表。我正在使用Propel 1.6.x并打算编写一个额外的小库来处理锁定。

我的用例是一个版本表,其主键为(id,creator,version)。列对(id,creator)实际上是另一个表上的PK。插入新行时,将在PHP代码中读取MAX(版本),然后将其插入行类以便以后保存。在最大值和保存之间,存在竞争条件,其中另一个进程可以获得相同的最大值,然后当然其中一个插入因非唯一性而失败。

为了避免需要锁定,我宁愿使用子选择进行保存,例如:

INSERT INTO
    test_model_test_organiser_versionable
(id, creator, version)
VALUES (
    3,
    1, 
    (
        SELECT COALESCE(MAX(version), 1)
        FROM test_model_test_organiser_versionable
        WHERE id = 3
        AND creator = 1
    )
);

然而,Propel不支持这一点,如果我通过PDO这样做,我不会(afaik)有办法发现赋予复合PK'版本'部分的价值。

现在,我可以有一个额外的自动递增列,因为在插入后可以读取自动递增的值以查找行,因此我可以在Propel中进行重新选择。但是如果我能帮助的话,我想避免使用无关的专栏 - 在我看来似乎不那么优雅。

所以...我的感觉是包裹最大和最大保存锁定中的呼叫是可行的方法。这将必须锁定整个表IMO,并防止读取和写入(否则后续的最大调用将不会等待,因此将导致非唯一性再次失败)。

我需要这个与Propel支持的所有平台一起工作,所以 - 除非有一个更好的方法我应该采取 - 是否有一个PHP库可以对任何PDO数据库进行锁定?如果没有,我可以自己做 - 但是如果其他人已经对各种dbs进行了测试驴工作(设置MSSQL Server? - 不,谢谢:),这很好。

1 个答案:

答案 0 :(得分:1)

当MAX()和INSERT / UPDATE完成时,我完全锁定了表。我发现这些有效:

  • MySQL:LOCK TABLES my_table WRITE
  • PostgreSQL:LOCK TABLE my_table IN SHARE ROW EXCLUSIVE MODE

我计划在适当的时候查找并测试Oracle,MSSQL和SQLite的相同内容 - 但前两个可能是F / OSS项目中最受欢迎的。