为什么 MySQL InnoDB 可以处理并发更新而 PostgreSQL 不能?

SDR*_*yes 0 mysql postgresql deadlock isolation-level

假设您有一个具有以下定义的表:

CREATE TABLE public.positions
(
   id serial,
   latitude numeric(18,12),
   longitude numeric(18,12),
   updated_at timestamp without time zone
)
Run Code Online (Sandbox Code Playgroud)

你在这样的表中有 50,000 行。现在出于测试目的,您将运行如下更新:

update positions
set  updated_at = now()
where latitude between 234.12 and 235.00;
Run Code Online (Sandbox Code Playgroud)

该语句将更新 50,000 行中的 1,000 行(在此特定数据集中)

如果您在 30 个不同的线程中运行这样的查询,MySQL innodb 将成功,而 postgres 将因大量死锁而失败。

为什么?

Lau*_*lbe 5

我会说,普通的老运气。

如果 30 个线程继续并想要更新相同的 1000 行,它们可以以相同的顺序访问这些行(在这种情况下它们将相互锁定并按顺序执行)或以不同的顺序访问这些行(在这种情况下它们将死锁)。

InnoDB 和 PostgreSQL 也是如此。

要分析为什么在您的情况下事情会有所不同,您应该从比较执行计划开始。也许你会知道为什么 PostgreSQL 不会以相同的顺序访问所有行。

如果缺少这些信息,我猜您会遇到8.3 版中引入的一项功能,功能可以加速并发顺序扫描:

  • 并发大型顺序扫描现在可以共享磁盘读取(Jeff Davis)

    这是通过在表的中间开始新的顺序扫描(另一个顺序扫描已经在进行中)并从头开始到结束来完成的。这可能会影响未指定的查询中返回行的顺序ORDER BYsynchronize_seqscans如有必要,配置参数可用于禁用此功能。

检查您的 PostgreSQL 执行计划是否使用顺序扫描并查看更改是否synchronize_seqscans避免了死锁。