【问题标题】:aggregate check before modifying data and locking修改数据和锁定之前的聚合检查
【发布时间】:2016-07-26 03:35:35
【问题描述】:
想象以下场景,我们有一个表,其中插入的行带有一些约束。
例如,
- SELECT COUNT(*) FROM table WHERE ....
- 检查,如果计数小于某个值
- 如果条件为真 - INSERT ...,否则 - ROLLBACK
如果我们没有很多并发查询,它就可以工作。
处理并发请求有以下几种方式:
- 将计数器保存到另一个表或 Redis。并在每次更新时管理此计数器。
- 在每次插入前锁定整个表。
我正在使用 PostgreSQL。解决这种情况的最佳方法是什么?
【问题讨论】:
标签:
postgresql
locking
aggregate
【解决方案1】:
尝试在每个用户会话中明确地使用statement_timeout 和lock_timeout set。详情请看here。
【解决方案2】:
锁定表非常极端,会严重损害并发性。
在单独的表中维护一个计数器会更好;它本质上会序列化INSERTs(下一个事务只能在上一个事务使用COMMIT 释放锁后更新计数器)。
第三种方法是使用SERIALIZABLE 事务。如果涉及的所有交易都是SERIALIZABLE,那么只要您在单个交易中执行SELECT count(*) ...和INSERT,您的条件就会自动得到保证。
缺点是事务可能会因序列化错误而中止,您必须准备好重试它们。