我們正試圖儘可能以最簡單的方式限制SIP服務器上的註冊數量。更具體地說,我們決定限制users
表中的條目數量。服務器作爲DBMS運行PostgreSQL。如何用PostgreSQL限制特定表中的行數?
是否可以限制特定表中的條目數?例如,我們希望將行數限制爲100,並且除非刪除一些舊錶,否則我們不希望該表上有更多條目。
請指教。
我們正試圖儘可能以最簡單的方式限制SIP服務器上的註冊數量。更具體地說,我們決定限制users
表中的條目數量。服務器作爲DBMS運行PostgreSQL。如何用PostgreSQL限制特定表中的行數?
是否可以限制特定表中的條目數?例如,我們希望將行數限制爲100,並且除非刪除一些舊錶,否則我們不希望該表上有更多條目。
請指教。
這是可能的,但這是解決這個問題的一個很不好的方法。您必須創建一個觸發器,獲取表上的EXCLUSIVE
鎖,然後在允許提交前檢查表上的count()
,或者如果插入操作會添加太多行,則執行RAISE EXCEPTION
來中止事務。
兩個觸發器,實際上;一個BEFORE INSERT OR DELETE
觸發器,該觸發器執行LOCK TABLE ... IN EXCLUSIVE MODE
和AFTER INSERT
觸發器,該觸發器檢查表的COUNT
並確定是否引發異常。簡單的BEFORE
觸發器是不夠的,因爲它不能確定INSERT
是否可能添加多行,所以多值插入或INSERT ... SELECT
可能會導致超出限制。
想要更新表的其他會話將不得不等待,直到執行INSERT
的事務完成。如果該應用程序不是爲此設計的,則很容易導致死鎖。
當應用程序INSERT
s進入會話表時,它可能不會收到錯誤,因此它可能無法正常處理。這是不太可能給用戶一個整潔的「太多註冊」錯誤。
我還沒有寫過這樣的示例觸發器,因爲我認爲這絕對是可怕的想法。如果您想限制SIP服務器上註冊的用戶數量,請適當配置您的SIP服務器。如果沒有這種配置選項,請修改它以添加一個或使用不同的SIP服務器,確實有。
像往常一樣,谷歌把我在這裏:
CONSTRAINT nomore_than_x_rows
CHECK(table_id < 101);
給出相應的ID型系列的
只有在用戶永遠不會被刪除的情況下,該技巧才能正常工作,因爲如果刪除用戶,新ID將會高於100。 –
我不知道如果一個稍微不同的方法可能代替觸發器的工作,如100項在表中,每個SIP「用戶」需要聲明一個條目,並且隨後的嘗試阻止或失敗,如果他們無法獲得條目。正如你所說的克雷格,我認爲一個更合適的解決方案是修復應用程序。 – bma
@bma可以工作,但是很容易出現競爭條件,如果不重新採用相同類型的單線程方法或更多的應用程序更改就很難解決。在併發插入和刪除的情況下,你如何選擇哪一個?如果Pg支持'LIMIT 1 SKIP LOCKED'或者你可以做到這一點,但是目前沒有這樣的東西。 –