postgresql - Postgres : Optimising concurrent same row updates

标签 postgresql go sql-update

问题

我正在使用 PostgreSQL v10 + golang,并且遇到了一个我认为非常常见的 SQL 问题:

  • 我有一个表“计数器”,其中包含 current_valuemax_value 整数列。
  • 严格来说,一旦 current_value >= max_value,我就会放弃该请求。
  • 我有几个 Kubernetes pod,对于每个 API 调用,它们可能会将“计数器”表中同一行(在最坏的情况下)的 current_value 增加 1(可以被认为是从分布式主机对同一数据库的并发更新)。

在我当前的幼稚实现中,对同一行的多个更新自然会相互阻塞(如果重要的话,隔离级别是“已提交读”)。 在最坏的情况下,每秒大约有 10 个以上的请求会更新同一行。这会造成瓶颈并损害性能,这是我无法承受的。


可能的解决方案

我想到了几个解决这个问题的想法,但它们都牺牲了完整性或性能。对于这个看似常见的问题,唯一一个保留两者的听起来不太干净:

只要计数器 current_valuemax_value 的距离相对安全(delta > 100),就将更新请求发送到每秒刷新的 channel ,或者因此,由一个工作人员聚合更新并立即请求它们。否则(增量 <= 100),在事务上下文中进行更新(并遇到瓶颈,但仅适用于少数情况)。这将加快更新请求的速度,直到几乎达到限制,从而有效地解决瓶颈。


这可能有助于解决我的问题。但是,我忍不住认为有更好的方法来解决这个问题。

我在网上没有找到很好的解决方案,尽管我的启发式方法可行,但感觉不干净且缺乏完整性。

非常欢迎创造性的解决方案!


编辑:

感谢 @laurenz-albe 的建议,我尝试缩短行被锁定到事务的 COMMIT 之间的持续时间。将所有更新推送到事务末尾似乎已经成功了。现在我可以每秒处理超过 100 个请求并保持完整性!

最佳答案

每秒 10 个并发更新是少得离谱。只要确保事务尽可能短,就不会出现问题。

你最大的问题将是VACUUM,因为大量更新对于 PostgreSQL 来说是最糟糕的工作负载。确保您创建的表的 fillfactor 为 70 左右,并且 current_value 编入索引,以便获得热门更新。 p>

关于postgresql - Postgres : Optimising concurrent same row updates,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55539927/

相关文章:

ruby-on-rails - 验证 rails 3 中 postgres 整数字段的数值

一次更新中的 SQL 多个 SET?

postgresql - 是否可以在 PostgreSQL 中限制所有带有 tenant_id 的查询?

sql - Go 中数据库迁移的正确策略

go - 检查 nil 后从结构体中赋值

go - 通过 flag.PrintDefaults() 设置输出顺序

MySQL - 搜索 table1.field 的内容并将其替换为 table2.otherfield 的内容

c# - UPDATE语句Visual Studio C#.net中的语法错误

mysql - 如何在 heroku 的 laravel 项目中添加另一个数据库

ruby-on-rails - 尝试将 ruby​​ 哈希插入 Postgres 数据库