Frage

I SQLAlchemy als ORM innerhalb einer Anwendung verwende ich schon seit einiger Zeit mit dem Aufbau.

Bisher es war ziemlich schmerzlos ORM zu implementieren und zu verwenden, jedoch eine aktuelle Funktion erfordert arbeite ich an eine persistente & verteilte Warteschlange (Liste & Arbeiter) Stil-Implementierung, die ich in MySQL und Python gebaut haben .

Es ist alles ganz gut geklappt, bis ich es in einer skalierten Umgebung getestet. Ich habe InnoDB Sperren auf Zeilenebene verwendet, um jede Zeile, um sicherzustellen, nur einmal gelesen wird, während die Zeile gesperrt ist, aktualisiere ich einen ‚ in_use ‘ Wert, um sicherzustellen, dass andere greifen nicht am Eingang .

Da MySQL nicht bieten eine „NOWAIT“ Verfahren wie Postgre oder Oracle nicht, ich habe in Verriegelungs Probleme laufen, wo Worker-Threads hängen und warten auf die gesperrte Zeile zur Verfügung zu stehen.

In einem Versuch, diese Beschränkung zu überwinden, habe ich versucht, alle erforderlichen Verarbeitung in einer einzigen Anweisung zu setzen, und es durch die ORM laufen execute() Methode, obwohl SQLAlchemy weigert sich die Rückkehr Abfrageergebnis.

Hier ist ein Beispiel.

My SQL-Anweisung lautet:

SELECT id INTO @update_id FROM myTable WHERE in_use=0 ORDER BY id LIMIT 1 FOR UPDATE;
UPDATE myTable SET in_use=1 WHERE id=@update_id;
SELECT * FROM myTable WHERE id=@update_id;

Und ich diesen Code ausführen in der Konsole:

engine = create_engine('mysql://<user details>@<server details>/myDatabase', pool_recycle=90, echo=True)
result = engine.execute(sqlStatement)
result.fetchall()

Nur dieses Ergebnis erhalten

[]

Ich bin sicher, dass die Anweisung ausgeführt wird, da ich das Update wirksam in der Datenbank sehen, und wenn ich durch den mysql-Terminal oder andere Tools ausführen, bekomme ich die modifizierte Zeile zurückgegeben. Es scheint nur SQLAlchemy zu sein, dass nicht die zurückgegebene Zeile bestätigen will.

Gibt es etwas Bestimmtes, die sicherstellen, getan werden muss, um, dass die ORM die Antwort aufgreift?

Prost

War es hilfreich?

Lösung

Sie haben 3-Abfragen ausgeführt und MySQLdb erstellt ein Ergebnis für jeden Satz. Sie müssen zuerst Ergebnis holen, dann cursor.nextset() rufen, holen zweite und so weiter.

Diese beantworten Ihre Frage, aber nicht für Sie nützlich sein, weil es Sperrung Problem nicht lösen wird. Sie müssen verstehen, wie FOR UPDATE funktioniert zuerst: Sie sperrt zurückgegebenen Zeilen bis zum Ende der Transaktion. lange Sperre warten Um zu vermeiden, müssen Sie es so kurz wie möglich machen: SELECT ... FOR UPDATE, UPDATE SET in_use=1 ..., COMMIT. Sie brauchen eigentlich nicht, sie in einzelne SQL-Anweisung zu setzen, 3 execute() Anrufe zu OK sein wird. Aber Sie haben vor langer Berechnung zu begehen haben, andernfalls Sperre zu lange gehalten werden und die Aktualisierung in_use (offline Sperre) ist bedeutungslos. Und sicher, Sie können das gleiche tun mit ORM zu.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top