我们正在尝试以最简单的方式限制 SIP 服务器上的注册数量。更具体地说,我们决定限制表中的条目数users
。服务器将 PostgreSQL 作为 DBMS 运行。
是否可以限制特定表中的条目数?例如,我们希望将行数限制为 100,并且我们不希望该表上有更多条目,除非删除一些旧条目。
请指教。
我们正在尝试以最简单的方式限制 SIP 服务器上的注册数量。更具体地说,我们决定限制表中的条目数users
。服务器将 PostgreSQL 作为 DBMS 运行。
是否可以限制特定表中的条目数?例如,我们希望将行数限制为 100,并且我们不希望该表上有更多条目,除非删除一些旧条目。
请指教。
这是可能的,但这是解决此问题的一种非常糟糕的方法。您必须创建一个触发器来获取EXCLUSIVE
表上的锁,然后在允许提交之前检查表上的锁,count()
或者,如果插入会添加太多行,则执行 aRAISE EXCEPTION
以中止事务。
实际上有两个触发器;一个BEFORE INSERT OR DELETE
执行 the的触发器LOCK TABLE ... IN EXCLUSIVE MODE
和一个AFTER INSERT
检查COUNT
table 并决定是否引发异常的触发器。一个简单的BEFORE
触发器是不够的,因为它无法判断是否INSERT
可能添加多于一行,因此多值插入或INSERT ... SELECT
可能导致超出限制。
其他想要更新表的会话将不得不等到事务INSERT
完成。如果应用程序不是为此而设计的,则很容易导致死锁。
该应用程序可能不希望在INSERT
进入会话表时出现错误,因此它可能无法优雅地处理该错误。不太可能给用户一个简洁的“注册过多”错误。
我没有为此编写示例触发器,因为我认为这样做绝对是一个糟糕的主意。如果您想限制在您的 SIP 服务器中注册的用户数量,请适当配置您的 SIP 服务器。如果没有这样的配置选项,修改它以添加一个或使用一个不同的 SIP服务器。
有点晚了,但我们遇到了同样的问题,所以我想分享我的解决方案。我假设该user
表有一些父键或一些关系。您可以通过锁定父记录并检查满足您条件的用户总数来在事务中执行此操作。如果小于limit
则可以插入新用户。如果您尝试在另一个事务中执行此操作,您将被锁定直到第一个事务完成,或者您可以使用SKIP LOCKED
获取空结果并完成事务。
代码:
BEGIN;
SELECT * FROM user_parent WHERE /* condition */ FOR UPDATE;
SELECT count(1) FROM "user" WHERE /* condition */;
// check count in your code
// if count <= limit; then continue; else ROLLBACK
// INSERT your users
COMMIT;
像往常一样,谷歌把我带到了这里:
CONSTRAINT nomore_than_x_rows
CHECK( table_id < 101 );
鉴于 id 是串行类型