我对mysql提交和事务有疑问。
我有几个执行mysql查询的php语句。
我只想说以下内容吗?
mysql_query("START TRANSACTION");
//more queries here
mysql_query("COMMIT");
这到底是做什么的?它有什么用?对于更新,删除和插入,我还发现这可以阻止其他查询阅读:
mysql_query("LOCK TABLES t1 WRITE, t2 WRITE");
//more queries here
mysql_query("UNLOCK TABLES t1, t2");
这会阻止任何性质的其他查询,还是仅写入/选择?
另一个问题:假设一个查询正在运行并阻止其他查询。另一个查询尝试访问被阻止的数据 - 并且它看到它被阻止。它是如何进行的?是否等到数据再次被解除阻塞并重新执行查询?它是否失败并需要重复?如果是这样,我该怎么检查?
非常感谢!
丹尼斯
答案 0 :(得分:14)
在InnoDB中,如果您没有更改autocommit的默认设置(“on”),则无需为单个查询显式启动或结束事务。如果启用了自动提交,则InnoDB会自动将事务中的每个SQL查询括起来,这相当于START TRANSACTION; query; COMMIT;
。
如果在InnoDB中明确使用START TRANSACTION
并启用了自动提交,那么在START TRANSACTION
语句之后执行的任何查询都将被执行,或者所有查询都将失败。这在银行业环境中非常有用,例如:如果我将500美元转移到您的银行账户,只有从我的银行余额中扣除了金额并将其添加到您的银行账户后,该操作才会成功。所以在这种情况下,你会运行像
START TRANSACTION;
UPDATE customers SET balance = balance - 500 WHERE customer = 'Daan';
UPDATE customers SET balance = balance + 500 WHERE customer = 'Dennis';
COMMIT;
这可以确保两个查询都能成功运行,或者不运行,但不能只运行一个。 当您应该使用交易时,This post还有更多内容。
在InnoDB中,您很少需要锁定整个表格;与MyISAM不同,InnoDB支持行级锁定。这意味着客户端不必锁定整个表,迫使其他客户端等待。客户端应该只锁定他们实际需要的行,允许其他客户端继续访问他们需要的行。
您可以阅读有关InnoDB交易here的更多信息。有关死锁的问题,请参阅文档的14.2.8.8和14.2.8.9部分。如果查询失败,您的MySQL驱动程序将返回一条错误消息,指出原因;如果需要,您的应用应该重新发出查询。
最后,在您的示例代码中,您使用了mysql_query
。如果您正在编写新代码,请停止使用旧的,缓慢的,已弃用的mysql_
库来代替PHP并使用mysqli_
或PDO代替:)