2016-10-09 3 views
0

wir uns vor, Sie eine Tabelle mit dieser Definition haben:Warum MySQL InnoDB kann gleichzeitige Updates und PostgreSQL kann nicht?

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

Und Sie haben 50.000 Zeilen in einer solchen Tabelle. jetzt zu Testzwecken erhalten Sie ein Update wie folgt ausführen:

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

die Anweisung 1000 Zeilen aus der 50.000 aktualisieren (in diesem speziellen Datensatz)

wenn Sie eine solche Abfrage in 30 verschiedenen Threads, MySQL innodb laufen wird gelingen und postgres wird mit vielen Deadlocks scheitern.

warum?

Antwort

3

Plain altes Glück, würde ich sagen.

Wenn dreißig Threads vorausgehen und die gleichen 1000 Zeilen aktualisieren möchten, können sie entweder auf diese Zeilen in der gleichen Reihenfolge zugreifen (in diesem Fall werden sie sich gegenseitig ausschließen und sequenziell ausführen) oder in anderen Ordnungen (in denen Fall werden sie festgefahren).

Das ist das gleiche für InnoDB und PostgreSQL.

Um zu analysieren, warum die Dinge in Ihrem Fall anders laufen, sollten Sie mit dem Vergleich der Ausführungspläne beginnen. Vielleicht bekommen Sie dann einen Hinweis, warum PostgreSQL nicht auf alle Zeilen in der gleichen Reihenfolge zugreift.

diese Information fehlt Ich würde vermuten, dass Sie ein feature introduced in version 8.3 auftreten, die gleichzeitige sequentielle Scans beschleunigt:

  • Concurrent großer sequenzieller Scans jetzt kann Disk teilen liest (Jeff Davis)

    Dies wird erreicht, indem der neue sequenzielle Scan in der Mitte der Tabelle gestartet wird (wo bereits ein anderer sequenzieller Scan läuft) und um den Anfang bis zum Ende gewickelt wird. Dies kann sich auf die Reihenfolge der zurückgegebenen Zeilen in einer Abfrage auswirken, die ORDER BY nicht angibt. Mit dem Konfigurationsparameter synchronize_seqscans kann dieser bei Bedarf deaktiviert werden.

Überprüfen Sie, ob Ihre PostgreSQL Ausführungsplan verwendet sequenzielle Scans und sehen, ob synchronize_seqscans Veränderung der Deadlock vermeidet.

+0

Sie haben Recht. Sie können dies in Postgres lösen mit: UPDATE .... WHERE ID in (SELECT ... FROM ... WHERE ... nach ID für UPDATE). – SDReyes

+0

Ich denke, die * richtige * Lösung wäre * nicht * 30 Threads die gleichen Zeilen zu aktualisieren. –

+0

es sei denn, wir betonen die DB. was wir sind, denn das ist Teil einer Benchmark! xD – SDReyes