2012-02-16 15 views
1

將Django與PostgreSQL(8.x)後端結合使用,我有一個需要跳過一個ID塊的模型。在給出49999之後,我希望下一個ID是70000而不是50000(因爲該塊是保留給其他實例用ID明確添加的源的 - 我知道這不是一個好設計,但這是我必須使用的)。如何安全地在Django中轉發主鍵序列?

這樣做的正確/最安全的地方是什麼?

我知道我可以設置與

SELECT SETVAL(
    (SELECT pg_get_serial_sequence('myapp_mymodel', 'id')), 
    70000, 
    false 
); 

但什麼時候Django的實際拉從時序的編號序列? 難道我重寫MyModel.save(),調用其超,然後搶我的光標,並與

SELECT currval(
    (SELECT pg_get_serial_sequence('myapp_mymodel', 'id')) 
); 

檢查?

我相信,即使保存模型失敗,django也可以提前執行一個序列,所以我想確保每當它遇到它前進的數字時 - 是否比save()有更好的地方?

P.S .:即使這是要走的路 - 我真的可以弄清楚save()會話的currval嗎?如果我抓住連接和遊標,並執行第二條SQL語句,我是不是在另一個會話中,因此不會得到一個currval?

謝謝你的任何指針。

編輯:我有一種感覺,這必須在數據庫級別上進行(併發性問題),並公佈了相應的PostgreSQL的問題 - How can I forward a primary key sequence in PostgreSQL safely?

+1

爲什麼不直接在數據庫上手動運行並使用它?試圖通過Django的方式來實現它在id爲49999的實際實例上,這樣做更值得。如果id在70000之後纔是安全的,那麼這就是你應該開始的地方。 – 2012-02-16 15:49:10

+0

我同意克里斯。這聽起來像任何這樣的代碼也是一個測試的痛苦。 – 2012-02-16 19:34:07

+0

手動運行的問題在於,當發生這種情況時,我必須這樣做。有不止一個差距。它們是由兩個不同系統(在線/離線)發出的數字,但最終在同一個數據庫中。交替的塊。 – 2012-02-17 02:11:02

回答

0

我的下一個念頭,就是不使用主鍵的順序,而是總是從我使用了最新的數字前檢查/更新一個單獨的計數器表中明確指定ID - 這應該是安全的併發問題。唯一的問題是,雖然我有一個地方添加模型實例,但Django或第三方應用程序的其他部分仍然可能依賴於隱含的ID,我不想破壞它。

,但同樣的機制恰好在Postgres的水平可以輕鬆實現 - 我相信這是解決方案:

  • 不要使用串行主鍵,使用DEFAULT my_next_id()
  • 按照相同的邏輯爲「單級無間隙序列」 - http://www.varlena.com/GeneralBits/130.php - my_next_id()執行的更新之後是選擇
  • 而不是隻增加1,檢查是否一個邊界被穿越,如果是,增加甚至進一步
+0

P.S .:這實際上可以像Django一樣完成,我相信。類似的概念,但使用django的「默認」主鍵可調用。不幸的是,其他一些任務已經優先考慮,但我會在接下來的兩週內發佈django-only解決方案(不需要黑客):)。 – 2012-02-29 11:10:11

+0

不幸的是,[Django bug#11390](https://code.djangoproject.com/ticket/11390)目前僅限於Django專有的解決方案。 – 2012-04-09 10:11:24

0

正如我還沒有發現這樣的一個「自動化」的方式然而,我想以下解決方法 - 這將是我的特殊情況是可行的:

  1. 用MAXVALUE 49999 NO CYCLE
  2. 當達到49999設置序列,下保存()將運行進入postgres錯誤是例外,再加註爲形式的錯誤
  3. 捕撈「你已經用完了數字,請重新下一個塊,然後再試一次。」
  4. 提供一個視圖,用戶可以激活下一個塊,即執行「ALTER SEQUENCE my_seq重新啓動具有70000 MAXVALUE 89999"

我不安捕捉異常時自動執行重新啓動:

try: 
    instance.save() 
except RunOutOfIdsException: 
    restart_id_sequence() 
    instance.save() 

)爲我擔心兩個並行保存(「跑出IDS會導致兩個單獨的重新啓動,以及隨後的vi這種獨特的約束是有限的。 (基本上是相同的概念,原來的問題)

相關問題