有一个可能很大的更新语句,用于更改表上的布尔标志和时间戳列。
此操作可能会更新表中可能有几百万行的几千行。
更新操作不应该锁定表,如果可能同时运行的其他查询获得过时数据,我愿意完全没问题。
目标是以不会影响其他读取操作的方式执行更新语句(如果可能,甚至更新)。
在这种情况下,如果在处理update语句时读取操作获取布尔标志和时间戳列的值不正确,则可以正常工作。
对于我可以使用的更新语句,postgresql是否有任何查询优化?鉴于上述宽松的要求?
答案 0 :(得分:0)
正如@a_horse_with_no_name所述,UPDATE
(或INSERT
或DELETE
)不会阻止PostgreSQL中的并发SELECT
,除非那些SELECT
s使用FOR UPDATE
或FOR SHARE
进行显式行锁定。
因此,在更新运行时,您可以从表中继续SELECT
。 SELECT
只会看到旧值。
影响已经UPDATE
d行的任何DELETE
或UPDATE
将在行锁上阻止,直到前一个{{1}完成。但是,这里有更新排序的皱纹。
如果你的大更新是按顺序扫描表,按顺序更新每一行,然后再做一个小的UPDATE
以其他顺序扫描表以选择要更新的行,你可以登陆陷入僵局。大更新可能已锁定id = 1000的行,并尝试锁定id = 1001的行。但是你的新版小更新已经锁定了id = 1001并试图获得id = 1000的锁定。他们都不能得到他们想要的锁,所以他们被困住了。 PostgreSQL检测到这一点,并使用死锁检测错误中止其中一个语句。 无保证哪个语句将被中止。
为了缓解这种情况,我建议尽可能将您的大UPDATE
分成一系列小UPDATE
,每个UPDATE
超过一系列值。这也将减少数据库必须在表中分配的额外工作空间量,以存储新版本的行,直到更新完成,并且可以清除旧版本。
我希望MySQL + InnoDB的行为类似。当你执行UPDATE
时,MySQL + MyISAM将锁定表格,但你不应该使用MyISAM。