2016-10-09 31 views
0

让我们想象一下,你有一个表,这个定义:为什么MySQL InnoDB可以处理并发更新,而PostgreSQL不能?

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

而且你有这样的表50,000行。现在用于测试目的你会遇到这样的更新:

update positions 
set updated_at = now() 
where latitude between 234.12 and 235.00; 

,如果你在30级不同的线程运行这样的查询语句将更新从50,000 1,000行(在这个特定的数据集)

,MySQL的InnoDB的将成功,postgres将失败,并造成大量死锁。

为什么?

回答

3

简单的老运气,我会说。

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

这对InnoDB和PostgreSQL的相同。

要分析为什么事情工作了你的情况不同,你应该通过比较执行计划开始。也许你会明白为什么PostgreSQL不能以相同的顺序访问所有的行。

缺乏这些信息,我猜您遇到feature introduced in version 8.3可以加速并行顺序扫描:

  • 并发大顺序扫描现在可以共享磁盘读取(杰夫·戴维斯)

    这是通过在表格中间开始新的顺序扫描(其中已经有另一个顺序扫描正在进行中)并将其包裹到头到尾来完成的。这可能会影响未指定ORDER BY的查询中返回的行的顺序。如有必要,可以使用synchronize_seqscans配置参数禁用此功能。

检查你的PostgreSQL执行计划使用顺序扫描,看看是否改变synchronize_seqscans避免死锁。

+0

你是对的。你可以通过使用下面的代码解决这个问题:UPDATE .... WHERE id(SELECT ... FROM ... WHERE ... order by id FOR UPDATE)。 – SDReyes

+0

我认为* right *解决方案将*不*有30个线程更新相同的行。 –

+0

除非,我们强调数据库。我们是我们,因为这是基准的一部分! xD – SDReyes

相关问题