如果 2 个事务几乎同时读取和写入 POSTGRES

问题描述 投票:0回答:1

表中的一个条目有一个列,其类型是一个字符串,我用它来存储另一个表中某些行的主键 id,以及一些其他数据。例如,它看起来像“1:yes_2:no_3:no_”。我有一个方法可以读取字符串的值,并在将新结果写入数据库之前用其他内容替换部分读取的字符串。例如;

def replace(person):
    cur.exeucte(select stringcol from tablename)
    fetchedstring = cur.fetchone()
    # some code that might take 10 seconds to run, or 20 seconds to run. requires knowing information            #fetchedstring so I cannot put it above the fetch.
    if person == 'jack':
        newstring = fetchedstring.replace(1, "blue")
    if person == 'joe':
        newstring = fetchedstring.replace(2, "green")
    cur.execute(update tablename set stringcol = newstring)
    conn.commit()

所以杰克想把那个字符串中的“1”变成“蓝色”,而乔想把那个字符串中的“2”变成“绿色”。在大多数情况下(以及我想要的行为),一个接一个地调用会导致字符串“blue:yes_green:no_3:no_”。但是我担心如果它几乎同时被调用会发生什么。这是允许的,因为起初他们只是读取字符串的值。对于 jack,字符串显示为“1:yes_2:no_3:no_”,并且在将“blue:yes_2:no_3:no_”写入数据库之前,在方法中将字符串更改为“blue:yes_2:no_3:no_”。对于 joe,当读取字符串时它也是“1:yes_2:no_3:no_”,并在将该值写入数据库之前将方法中的字符串更改为“1:yes_green:no_3:no_”,从而丢失更改乔做了。有什么办法可以防止这种情况发生吗?我相信有很多,但我不确定哪一个是最好的选择/最标准的方法。如果我能让问题更清楚,请告诉我,谢谢你的帮助。

我阅读了有关事务隔离的内容,但仍然感到困惑和担忧。

postgresql psycopg2
1个回答
0
投票

设计是有问题的,因为它需要长时间保持交易开放。这会导致严重的缩放问题。尽管存在设计问题,但以下解决了所述问题:

SELECT stringcol FROM tablename FOR UPDATE

如果没有

WHERE
子句来限制受影响的行,这将锁定表中的每一行并防止在事务期间进行更新。

有关其他信息和注意事项,请参阅 PostgreSQL 文档中的锁定条款

© www.soinside.com 2019 - 2024. All rights reserved.