php – 锁定SQL表,然后执行事务,以便在select值上插入条件
发布时间:2020-12-13 17:12:54 所属栏目:PHP教程 来源:网络整理
导读:我需要完成以下任务: 我需要在同一个表中插入两行,或者两者都插入,或者两者都不插入(原子插入两行). 我使用InnoDB表上的事务执行此操作,如下所示: $db-beginTransaction();# Using PDO prepared statments,execute the following queries:INSERT INTO t1 s
我需要完成以下任务:
我需要在同一个表中插入两行,或者两者都插入,或者两者都不插入(原子插入两行). 我使用InnoDB表上的事务执行此操作,如下所示: $db->beginTransaction(); # Using PDO prepared statments,execute the following queries: INSERT INTO t1 set uid=42,foo=1 INSERT INTO t1 set uid=42,foo=2 $db->commit(); 但是,如果表中没有列的值为“42”的行,我也只希望插入这些行. 所以我这样做: $stmt = $db->prepare("SELECT id FROM t1 WHERE uid != ?"); $stmt->execute(array(42)); if($stmt->fetchColumn() < 0){ # There is no row with uid=42,so # perform insertions here as per above. INSERT INTO t1 set uid=42,foo=1 INSERT INTO t1 set uid=42,foo=2 } 但是这里存在竞争条件,因为在检查该行之后,在插入新行之前,可以插入具有uid = 42的行. 我该怎么解决这个问题? 我可以锁定表,然后在表锁内执行InnoDB事务吗? 我可以在事务内部选择以检查uid = 42的现有行吗?这种竞争条件是免费的吗? 解决方法
您可以使用信号量类型的体系结构.例如,创建一个名为“信号量”的表或任何您想要调用它的表.假设表中只有一个字段,该字段是唯一的,称为“sem”.现在,运行“INSERT INTO信号量SET sem = 42”;
好吧,那个INSERT语句是原子的,并且意味着在其他人试图插入42之后的那一刻,他们会得到一个错误,说明重复的密钥. 然后,在原始表中执行插入操作.在交易中完成所有这些.在SQL中它看起来像这样: BEGIN TRANSACTION; INSERT INTO semaphore SET sem = 42; INSERT INTO t1 set uid=42,foo=1; INSERT INTO t1 set uid=42,foo=2; COMMIT; DELETE FROM semaphore WHERE sem = 42; 你之后删除的原因有两个: >我想你不需要删除它,但我们应该去干净的数据;) 侧注:信号量通常在自动增量字段不起作用时使用.然后使用一个只有一条记录的信号量表来序列化插入并阻止主键. 希望能帮助到你 :) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |