我有一個名爲ticket
的表,它有一個名爲number
的字段和一個名爲client
的外鍵,它需要像自動字段一樣工作(每個新記錄增加1),除了客戶端鏈需要能夠指定起始號碼。這不是一個獨特的領域,因爲多個客戶無疑會使用相同的號碼(例如從1001
開始)。在我的應用我獲取該行最高number
,並使用該number
+ 1
使下記錄的number
。這一切都發生在單個事務中(取得和保存新記錄)。在高負荷情況下,我是否真的不必擔心ticket
會得到不正確的(重複的)number
,或者交易是否會保護這種可能性? (注意:我正在使用PostgreSQL 9.x)如果在事務中完成,我可以信任手動排序Postgres中的整數字段嗎?
回答
沒有鎖定整個表上每個插入/更新,沒有。事務處理PostgreSQL的方式意味着作爲併發事務結果出現的新行不會相互衝突;這就是會發生什麼。
您需要確保更新實際上導致相同的行發生衝突。你基本上需要實現類似於PostgreSQL本地序列所使用的機制。
我會做的是在您的client
列引用的表格中添加另一列,以表示您將使用的序列的last_val
。因此,每一筆交易看起來有點像這樣:
BEGIN;
SET TRANSACTION SERIALIZABLE;
UPDATE clients
SET footable_last_val = footable_last_val + 1
WHERE clients.id = :client_id;
INSERT INTO footable(somecol, client_id, number)
VALUES (:somevalue,
:client_id,
(SELECT footable_last_val
FROM clients
WHERE clients.id = :client_id));
COMMIT;
這樣第一次更新到客戶表失敗由於到達前插入一個版本衝突。
版本衝突?你是否假設交易以可序列化模式運行? (而不是默認的「讀取提交」)。 – 2012-03-22 18:42:23
@Daniel:嗯,是的,我假設。我被我使用的框架寵壞了;這是默認設置的。 – SingleNegationElimination 2012-03-22 18:45:49
@TokenMacGuy - 你使用Django嗎?這是我使用的框架。 – orokusaki 2012-03-26 14:39:22
你不必擔心重複的號碼。
典型問題的方案是:事務T1讀取N,並創建一個新行N + 1。但是在T1提交之前,另一個事務T2將N視爲此客戶端的最大值,並創建另一個N + 1 =>衝突的新行。
有很多方法可以避免這種情況;這裏是一個簡單的plpgsql代碼,它實現了一種方法,假設一個唯一的索引(客戶端,數字)。解決方案是讓插入同時運行,但在發生唯一索引違規時,重新刷新值直到它被接受爲止(它不是一個繁忙的循環,因爲併發插入被阻塞,直到其他事務提交)
do
$$
begin
loop
BEGIN
-- client number is assumed to be 1234 for the sake of simplicity
insert into the_table(client,number)
select 1234, 1+coalesce(max(number),0) from the_table where client=1234;
exit;
EXCEPTION
when unique_violation then -- nothing (keep looping)
END;
end loop;
end$$;
該示例與PG文檔中的UPSERT implementation有點相似。 將客戶端ID作爲輸入,它很容易轉換爲plpgsql函數。
- 1. 模式更改可以在MySQL中的事務中完成嗎?
- 2. 我可以在中等信任的ASP.NET中運行分佈式事務嗎?
- 3. 有人可以幫我完成我的java任務嗎?
- 4. 我可以在塊中創建Drupal自動完成文本字段嗎?
- 5. mysql事務可以在mysql事件調度程序中完成嗎?
- 6. 如何在Scala Slick中完成Postgres中的單獨事務
- 7. 我們可以在datagrid中手動調整行的大小嗎?
- 8. 有人可以幫我完成管道上的任務嗎?
- 9. 我可以在Dojo Charts中使用「渲染完成」事件嗎?
- 10. 有任何方法可以在任務完成之前暫停'mousemove'事件嗎?
- 11. 你可以手動在Python中對列表進行排序嗎?
- 12. 有人可以幫我完成C編程任務嗎?
- 13. 根據完成順序排序任務
- 14. 如果數據集由udp客戶端接收到,我們可以信任數據完整性嗎?
- 15. 我可以信任ceil()的結果的實數轉換嗎?
- 16. 我可以在生成器中運行耙子任務嗎?
- 17. 我可以信任JavaScript中的聲明執行順序嗎?
- 18. 是否可以使用用戶信息自動完成Sharepoint中的字段?
- 19. 我可以在android中完全重新啓動服務嗎?
- 20. 任何人都可以協助完成這項任務嗎?
- 21. 我可以在XSD生成的類中填零整數嗎?
- 22. 我可以在Postgres中找到我的PLPython函數嗎?
- 23. 如果任務是活動窗口,任務會更快完成嗎?
- 24. 任務MaxDegreeOfParallelism可以在完成處理文件後報告嗎?
- 25. 我可以在elasticsearch查詢中指定結果字段嗎?
- 26. 我可以在草圖中自動執行任務嗎?
- 27. 邏輯時鐘協議可以提供事件的完整排序嗎?
- 28. 如何以Linq查詢中的字符串字段中的整數排序
- 29. 在Django中可以默認基於float字段的整數字段嗎?
- 30. 您可以在Salesforce.com中創建整數自定義字段嗎?
如果事務回滾,該怎麼辦? – 2012-03-22 17:14:03
@mattb - 這並不意味着數據庫中什麼都不會改變,因此下一個'number'會再次可用?我不打算在多次交易中用同一位重試操作。 – orokusaki 2012-03-22 17:28:56
你有一個唯一的索引(客戶端,號碼),如果沒有,爲什麼不呢? – 2012-03-22 18:42:50