2012-05-14 229 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