PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Haben in PostgreSQL mehrere UPDATEs für verschiedene Zeilen in derselben Tabelle widersprüchliche Sperren?

UPDATE sperrt die Zeile, sodass Sie sie nicht zuerst sperren müssen. Wenn Sie versuchen, UPDATE überlappende Sätze von Zeilen gleichzeitig, das zweite UPDATE wartet darauf, dass die erste Transaktion festgeschrieben oder rückgängig gemacht wird.

Das große Problem bei Ihrem Ansatz - abgesehen davon, dass UPDATE hat kein LIMIT Klausel - ist, dass mehrere Arbeiter alle versuchen werden, die gleichen Zeilen zu greifen. Folgendes passiert:

  • worker1:Filtert die Tabelle, um 200 Zeilen zu finden, und sperrt sie
  • worker1:beginnt mit dem Aktualisieren von Zeilen
  • worker2:filtert die Tabelle, um 200 Zeilen zu finden
  • worker2:versucht, Zeilen zu aktualisieren, hat aber dieselben Zeilen wie worker1 ausgewählt, sodass es die Sperre von worker1 blockiert
  • worker1:Beendet die Zeilenaktualisierung
  • Arbeiter2:Prüft nach Freigabe der Sperre erneut die WHERE-Bedingung und stellt fest, dass keine der Zeilen mehr übereinstimmt, da Arbeitskraft1 sie aktualisiert hat. Aktualisiert null Zeilen.

... und wiederhole!

Sie müssen entweder:

  • Haben Sie eine zentrale Warteschlange Verteilen von Zeilen auf eine ordnungsgemäße parallelitätssichere Weise; oder
  • Weisen Sie Arbeitern sich nicht überschneidende ID-Bereiche zu, an denen sie arbeiten können

Wie bei LIMIT - Sie könnten WHERE id IN (SELECT t.id FROM thetable t LIMIT 200 ORDER BY id) verwenden - aber Sie hätten das gleiche Problem, wenn beide Worker denselben Satz von Zeilen zum Aktualisieren auswählen würden.