2012-05-14 183 views
6

我有一个关于mysql提交和交易的问题。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

您是否使用InnoDB或MyISAM表? – Daan

+0

@Daan我使用InnoDB – weltschmerz

回答

12

在InnoDB中,你并不需要显式启动或单查询结束交易,如果你没有改变自动提交的默认设置,这是“上”。如果启用自动提交,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.814.2.8.9部分得到解答。如果查询失败,您的MySQL驱动程序将返回一条错误消息,指出原因;如果需要,您的应用程序应该重新发布查询。

最后,在您的示例代码中,您使用了mysql_query。如果您正在编写新的代码,请停止使用旧的,缓慢的和不推荐使用的PHP库mysql_,并使用mysqli_或PDO代替:)

+0

真棒,谢谢! InnoDB自动只锁定行吗?我怎样才能检查我的表是否有自动提交?以及如何设置索引(我正在使用phpmyadmin) – weltschmerz

+0

您可以发出'SHOW VARIABLES LIKE'autocommit'查询,或单击phpMyAdmin主页上的'variables'。创建一个索引是通过转到适当的数据库和表格,点击'structure'并使用你在那里看到的表单来创建一个索引来完成的。或者你可以发出SQL语句,例如'ALTER TABLE table ADD INDEX(field)'。我不确定你的意思是“InnoBD自动只锁定行” - 它肯定不会自动锁定整个表,如果这就是你的意思:) – Daan

+0

Autocommit是:)主键总是作为索引吗?我有我的表中的主键,并希望添加索引,但它表示它只能与主键相同... – weltschmerz