2013-07-03 21 views
1

這可能不是現實世界的問題,但更像是一個學習主題。手動增加主鍵 - 交易和競速條件

使用PHP,MySQL和PDO,我知道所有關於auto_increment和lastInsertId()的內容。考慮到主鍵沒有auto_incerment屬性,我們必須使用類似SELECT MAX(id) FROM table的東西來檢索最後一個ID,手動增加它,然後INSERT INTO table (id) VALUES (:lastIdPlusOne)。將整個代碼包裝在beginTransactioncommit中。

這種方法安全嗎?如果用戶A和B同時加載該腳本,那麼最後會發生什麼?這兩個交易將失敗?或者兩者都會成功(例如,如果最後一個ID是10,A將插入11,B將插入12)?

請注意,因爲我是一位PHP開發人員,因此我對MySQL的行爲更感興趣。

+3

您必須確保您使用[鎖定讀取](http://dev.mysql.com/doc/en/innodb-locking-reads.html)在第一個位置獲取MAX() (選擇)查詢;它會阻塞,直到事務提交。但是,這是非常糟糕的設計,應該*不*用於生產系統。 – eggyal

+0

@eggyal:謝謝,非常翔實的文章,我認爲這是一個可靠的解決方案。不幸的是評論不能被標記爲答案。 – FatDog47

回答

0

這是@eggyal評論,我在這裏引用:

你必須確保你使用locking read來獲取MAX()在第(選擇)查詢;它會阻塞,直到事務提交。但是,這是非常糟糕的設計,不應該用於生產系統。

0

如果兩者得到相同的最大值,那麼首先插入的將成功,其他(s)將失敗。

爲了在不使用auto_increment字段的情況下解決這個問題,您可以在插入之前使用觸發器執行作業(new.id = max),即相同的邏輯,但是在觸發器中,因此數據庫服務器是控制它。

不確定,但如果這是100%安全的主 - 主複製環境中的服務器故障的情況下。