根据其文档,每当提交任何其他事务时,Postgres 都会重新评估事务中的所有 WHERE 子句,以检查更新的行是否仍然匹配搜索条件:
UPDATE、DELETE、SELECT FOR UPDATE 和 SELECT FOR SHARE 命令在搜索目标行方面与 SELECT 的行为相同:它们只会查找截至命令开始时间已提交的目标行。然而,这样的目标行在被发现时可能已经被另一个并发事务更新(或删除或锁定)。在这种情况下,潜在的更新程序将等待第一个更新事务提交或回滚(如果仍在进行中)。
如果第一个更新程序回滚,则其效果被否定,第二个更新程序可以继续更新最初找到的行。如果第一个更新程序提交,则第二个更新程序将忽略第一个更新程序删除的行,否则它将尝试将其操作应用于该行的更新版本。
重新评估命令的搜索条件(WHERE 子句),以查看该行的更新版本是否仍然与搜索条件匹配。如果是这样,第二个更新器将使用该行的更新版本继续其操作。
WAL模式下的SQLite怎么样?它的行为方式是否与 Postgres 相同,并且在另一个更新程序首先提交时重新评估 WHERE 子句?我在 SQLite 文档中找不到任何关于此的信息。
即使使用 WAL 模式,在 SQLite 中,整个数据库文件一次只能有一个写入者。
如果读事务尝试升级到写事务,并且数据库自该事务以来已被更改,则操作将失败并出现“数据库已锁定”错误。