表中的一个条目有一个列,其类型是一个字符串,我用它来存储另一个表中某些行的主键 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_”,从而丢失更改乔做了。有什么办法可以防止这种情况发生吗?我相信有很多,但我不确定哪一个是最好的选择/最标准的方法。如果我能让问题更清楚,请告诉我,谢谢你的帮助。
我阅读了有关事务隔离的内容,但仍然感到困惑和担忧。
设计是有问题的,因为它需要长时间保持交易开放。这会导致严重的缩放问题。尽管存在设计问题,但以下解决了所述问题:
SELECT stringcol FROM tablename FOR UPDATE
如果没有
WHERE
子句来限制受影响的行,这将锁定表中的每一行并防止在事务期间进行更新。
有关其他信息和注意事项,请参阅 PostgreSQL 文档中的锁定条款。