回答

收藏

在PostgreSQL处理竞争条件

技术问答 技术问答 243 人阅读 | 0 人回复 | 2023-09-14

我有几个工作人员,每个工作人员都有和PostgreSQL连接。工人用不同的桌子操作。
" v" ?+ F$ h& p  ?! P9 U员工处理系统外部的并行请求。被访问的表之一是用户表。当我收到一些信息时,我首先需要确保表中有用户记录。如果没有记录,我希望先创建一个。! Z9 E# S" I6 T. D4 R
我正在使用以下成语:
# m. r" d. {8 [if [user does not exist] then [create user]的代码[user does not exist]是:
, c4 ?$ p  c( i$ C: S. LSELECT id FROM myschema.users WHERE userId='xyz'然后测试是否返回任何行。
8 J$ v: `; D- S/ v/ V5 ?8 T# W(简化)代码[create user]为:! ^, j, N, V& w7 I
INSERT INTO myschema.users VALUES ('xyz')当我的系统处理和 同一    与用户有关    我经常收到不同信息的并行流PostgreSQL错误:* R$ W& `2 Y  N3 N& M
Key (id)=(xyz) already exists这是因为这种情况发生了SELECT命令不返回任何行,然后另一名工作人员创建用户,我的任何工作人员都试图执行操作,导致示例并发错误。
9 V+ v4 m6 S, l$ ^1 ^5 Z& U/ }0 E1 p& Y根据PostgreSQL默认情况下,每当我隐式启动事务时,只要我不提交表格,表格就会被锁定。我没有使用自动提交。我只在块里提交事务,比如整个if-else块之后。
! u  G- {  g/ l9 o$ J+ o, N的确,我可以这样做if-else直接放东西SQL但它通常不能解决我的锁定问题。我认为赢家将全力以赴的例子将起作用,并试图执行SELECT命令的第一名工作人员将有锁,直到调用COMMIT。) B$ O0 ^$ z' I  M. }- w2 g  u8 E
我在SO我读了很多不同的主题,但我仍然不确定什么是正确的解决方案。我应该使用表的显式锁,因为隐式锁不起作用?如何确保只有一名工人同时有一张桌子?
- k4 G1 k) ~% x0 o$ q; R# n4 j                                                               
* s, ~2 y; N+ a- G: j4 l! h    解决方案:                                                               
  Y2 L( F. m0 g! R6 p                                                                您必须关心事务隔离级别。应将其设置为 SERIALIZABLE”。
/ d% H0 a5 A4 _5 h6 ~7 h. e原因是Phantom Reads-事务不会锁定整个表,只会锁定已被事务读取的行。
* s' f3 y* B. q2 l5 ~% Z+ Y; D/ I因此,如果将新数据插入另一个事务,它们将不会被锁定,并且会出现错误。
4 Y8 [9 O" Q$ S& \7 s! z这种情况可以通过阻止所有其他事务来避免,直到它完成。0 G% N2 m! H4 C# h  Z8 f8 N% ~* o
您可以通过
1 A9 U  i% H  I) d. |6 JSET TRANSACTION ISOLATION LEVEL SERIALIZABLE;文档:http :
" N. ~5 y8 U' ]5 ^9 q3 n$ b//www.postgresql.org/docs/9.1/static/transaction-2 K& |3 ^6 {! n1 M/ B
iso.html
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则