2012-08-16 47 views
3

當一個更好的解決方案的任何一個對我來說是更好的解決方案,用於代碼:MySQL的PHP​​鎖表,有沒有同時expacting連接

<?php 

try { 
    $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $password); 

    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $dbh->beginTransaction(); 

    $dbh->exec("LOCK TABLES test2 WRITE"); 

    $row = $dbh->query('SELECT * from test2 WHERE c > 0 LIMIT 1'); 

    $stmt = $dbh->prepare("UPDATE test2 SET c=c-1 WHERE a=:a and c>0"); 
    $stmt->bindParam(':a', $row['a']); 
    $stmt->execute(); 

    /** 
    ... 
    .... 
    ..... 
    **/ 

    $dbh->exec("UNLOCK TABLES"); 

    $dbh->commit(); 
    $dbh = null; 
} catch (PDOException $e) { 
    error_log("Error!: " . $e->getMessage() . "\n", 3, "./my-errors.log"); 
    exit(); 
} 

當我到了該腳本同時連接,每個連接應該有他從表test2(字段A)自己的行。

感謝您的想法:-)

+1

爲什麼不在一個查詢中執行「UPDATE」? – Brad 2012-08-16 16:44:13

+0

您是否嘗試過使用交易? 這裏有幾個例子: http://stackoverflow.com/questions/2708237/php-mysql-transactions-examples – Ozzyberto 2012-08-16 16:47:27

+0

我不認爲交易會起作用。我測試了它們。 '$ dbh-> beginTransaction();'沒有數據庫違規,所以事務不會拋出錯誤。 – Oliver 2012-08-16 20:25:42

回答

1

如果你不需要知道a參數,你可以用下面的查詢

UPDATE test2 SET c=c-1 WHERE c>0 LIMIT 1; 
+0

我需要知道'a'參數來做其他的事情 – Oliver 2012-08-16 20:18:54

0

LOCK TABLESUNLOCK TABLES自動關閉您的交易。你需要一個SELECT .. FOR UPDATE,忘記鎖定和解鎖表。

SELECT FOR UPDATE在行級別鎖定。其他執行SELECT FOR UPDATE將等待第一次轉換的結束,如果他們假裝獲得相同的記錄。