如何在多线程环境中安全地插入/更新 Postgres 中的值

发布于 2024-12-17 13:48:00 字数 521 浏览 3 评论 0原文

我在 PostgreSQL 中有一个如下所示的表,

 create table item_counts {
  item string,
  view_count int}

我想使用该表来跟踪 item 的出现,并根据需要增加计数。最初表未填充,因此当第一次观察到新值时插入新值,否则 view_count 会增加。速度和多任务处理都是问题。

我知道我可以做

rows_affected = execute("update item_counts set view_count = view_count + 1 
  where item = ?")
if rows_affected == 0:
   execute("insert into item_counts ...")

但是,这在多线程环境中是不安全的,所以我必须将其包装到事务中。这反过来会降低速度,因为每次插入/更新后都会发生提交。

有什么建议如何以干净有效的方式做到这一点?

I have a table in PostgreSQL that looks like this

 create table item_counts {
  item string,
  view_count int}

I would like to use the table to keep track of occurrences of item, incrementing the counts as necessary. Initially the table is unpopulated, so a new value is inserted iff it is observed for the first time, otherwise the view_count is increased. Speed and multitasking are both concerns.

I know I can do

rows_affected = execute("update item_counts set view_count = view_count + 1 
  where item = ?")
if rows_affected == 0:
   execute("insert into item_counts ...")

However, this is unsafe in a multithreaded environment, so I would have to wrap it into a transaction. This would in turn decrease the speed, since a commit would occur after each insert/update.

Any suggestions how to do it in a clean and efficient way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不羁少年 2024-12-24 13:48:00

或者,您可以在违反唯一异常时检查点、插入和更新(回滚检查点)。它是否更好值得怀疑,特别是如果您希望进行大部分更新。

此外,并发情况下的事务在提交时仍可能失败。

另外,您可以执行 insert select,插入表中没有的内容(使用 self-left-join 或 where not contains 子句,无论您喜欢什么),然后更新 if它产生 0 个受影响的行。

也许,最好在服务器端的函数中执行此操作。

Alternatively, you can checkpoint, insert and update on violating unique exception (rolling back the checkpoint). Whether it's better is doubtful, especially if you expect to by mostly-update.

Also the transaction in case of concurrency may still fail at commit.

Also, you can do the insert select, inserting what's NOT in the table (using self-left-join or where not exists clause, whatever pleases you) and then update if it yields 0 affected rows.

And, perhaps, it's best if you do that in a function on the server side.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文