這絕對是可以做到的。 MyISAM不提供交易鎖定功能,所以忘記了諸如FOR UPDATE
之類的內容。示例代碼中兩條語句之間的競爭條件確實存在空間。你實施它的方式,就像說話的bur。一樣。它的功能非常棒,並不是它效果不錯! :-)
我不明白你在這個SQL做什麼:
select max(number)+1 m from confirmed where isNew = ?
是number
值獨特的整個表,或只在集合,其中isNew
具有一定的價值?如果number
的值在整個表中是唯一的,它會工作嗎?這將更容易創建,調試和維護。
您需要一個獲取數字的多連接安全方法。
你可以試試這個SQL。它將在一個語句中設置最大數量。
UPDATE confirmed
SET number = (SELECT 1+ MAX(number) FROM confirmed WHERE isNew = ?)
WHERE dataid = ?
這將表現糟糕。如果沒有(isNew, number)
上的複合索引,並且沒有聲明這兩列,那麼它將表現得非常糟糕。
如果您可以使用整個表格中唯一的數字,我建議您爲自己創建一個sequence
設置,每次使用時都會返回一個唯一的數字。您需要使用一系列連續的SQL語句來執行此操作。這是怎麼回事。
首先,當您創建表格時,創建一個表格以使用名爲sequence
(或任何您喜歡的名稱)。這是一個單列表格。
CREATE TABLE sequence (
sequence_id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`sequence_id`)
) AUTO_INCREMENT = 990000
這將使序列表開始在990,000處發出數字。
其次,當您在應用程序中需要唯一編號時,請執行以下操作。
INSERT INTO sequence() VALUES();
DELETE FROM sequence WHERE sequence_id < LAST_INSERT_ID();
UPDATE confirmed
SET number = LAST_INSERT_ID()
WHERE dataid = ?
這是怎麼回事? MySQL函數LAST_INSERT_ID()
返回最近自動增量生成的ID號碼的值。因爲您在sequence
表中插入了一行,所以它會返回生成的ID號。 DELETE FROM
命令使該表避免了增加磁盤空間;我們不關心舊的身份證號碼。
LAST_INSERT_ID()
是連接安全的。如果軟件在不同的數據庫連接上使用它,它們都會得到自己的值。
如果您需要知道最後插入的ID號,你可以發出這樣的SQL:
SELECT LAST_INSERT_ID() AS sequence_id
,你就會得到它返回。
如果您使用的是Oracle或PostgreSQL而不是MySQL,您會發現它們提供的基本上是這樣的SEQUENCE對象。
下面是對另一個類似問題的答案。
Fastest way to generate 11,000,000 unique ids
可怕......僅僅使用一個AUTO_INCREMENT int和用它做。你的代碼受到競爭條件的影響,並且將永遠如此。 –
是否有你需要使用MyISAM作爲你的表引擎的原因?這與汽車公司時髦的事情,只會增加你的困境。首先重新思考你的模式,然後找出你的計劃。 – Zarathuztra
auto_increment無法使用,因爲根據提及的其他字段(isNew) – kbeat