2016-01-20 7 views
7

Ich habe eine sehr große Redshift-Datenbank, die Milliarden von Zeilen von HTTP-Anforderungsdaten enthält.Redshift: Serializable Isolationsverletzung auf Tabelle

Ich habe eine Tabelle requests genannt, die einige wichtige Felder hat:

  • ip_address
  • city
  • state
  • country

ich ein Python-Prozess läuft einmal pro Tag, der alle d ergreift Es handelt sich um Zeilen, die noch nicht geokodiert wurden (keine Informationen zu Stadt, Staat und Land enthalten) und versucht dann, jede IP-Adresse über die Google Geocoding-API zu geocodieren.

Dieser Prozess (Pseudo-Code) sieht wie folgt aus:

for ip_address in ips_to_geocode: 
    country, state, city = geocode_ip_address(ip_address) 
    execute_transaction(''' 
     UPDATE requests 
     SET ip_country = %s, ip_state = %s, ip_city = %s 
     WHERE ip_address = %s 
    ''') 

Wenn dieser Code ausgeführt wird, habe ich oft Fehler wie die folgenden:

psycopg2.InternalError: 1023 
DETAIL: Serializable isolation violation on table - 108263, transactions forming the cycle are: 647671, 647682 (pid:23880) 
diese

Ich gehe davon aus, weil ich andere haben Prozesse protokolliert ständig HTTP-Anfragen in meine Tabelle, so dass ich beim Versuch, meine UPDATE-Anweisung auszuführen, nicht alle Zeilen mit der IP-Adresse auswählen kann, die ich aktualisieren möchte.

Meine Frage ist: Was kann ich tun, um diese Datensätze auf eine vernünftige Art und Weise zu aktualisieren, die aufhören wird, regelmäßig zu versagen?

Antwort

3

Ihr Code verletzt die serialisierbare Isolationsstufe von Redshift. Sie müssen sicherstellen, dass Ihr Code nicht versucht, mehrere Transaktionen in derselben Tabelle zu öffnen, bevor alle offenen Transaktionen geschlossen werden.

Sie können dies erreichen, indem Sie die Tabelle in jeder Transaktion sperren, sodass keine andere Transaktion auf die Tabelle für Aktualisierungen zugreifen kann, bis die geöffnete Transaktion geschlossen wird. Sie sind sich nicht sicher, wie Ihr Code aufgebaut ist (synchron oder asynchron), aber dies erhöht die Laufzeit, da jede Sperre andere dazu zwingt, zu warten, bis die Transaktion beendet ist. Siehe

: http://docs.aws.amazon.com/redshift/latest/dg/r_LOCK.html

0

Entweder Sie starten eine neue Sitzung, wenn Sie auf dem gleichen Tisch zweite Update oder Sie haben zu ‚begehen‘, wenn Sie Transaktion abgeschlossen ist.

Sie können set autocommit = on schreiben, bevor Sie mit der Aktualisierung beginnen.

0

hätten das gleiche Problem auf meinem Code, und das ist, wie ich es fest:

erster

Erste Sachen, es ist gut, dass dieser Fehlercode zu wissen, bedeutet, dass Sie gleichzeitige Operationen in Rotverschiebung zu tun versuchen. Wenn Sie eine zweite Abfrage an eine Tabelle vornehmen, bevor die erste Abfrage, die Sie gerade ausgeführt haben, durchgeführt wurde, ist beispielsweise ein Fall, in dem Sie diese Art von Fehler erhalten würden (das war mein Fall).

Gute Neuigkeiten: Es gibt eine einfache Möglichkeit, Rotverschiebungsoperationen zu serialisieren! Sie müssen nur den LOCK-Befehl verwenden. Hier ist die Amazon Dokumentation für die redshift LOCK command. Es funktioniert im Grunde die nächste Operation warten, bis die vorherige geschlossen ist. Beachten Sie, dass Ihr Skript mit diesem Befehl natürlich ein wenig langsamer wird.

Am Ende war die praktische Lösung für mich: Ich habe den LOCK-Befehl vor den Abfragenachrichten eingefügt (in der gleichen Zeichenfolge, getrennt durch ein ';'). Etwas wie folgt aus:

LOCK table_name; SELECT * from ...

Und Sie sollten gut zu gehen! Ich hoffe es hilft dir.