2010-08-17 8 views
5

Auf der Suche nach einem Best-Practice-Tipp:Wählen Sie Sperren in Rails mit MySQL

Angenommen, ich habe ein Konto-Objekt mit Limit-Attribut. Jeden Tag können n Zahlungen mit der Summe ihrer Beträge bis zum Konto-Limit sein. Beim Erstellen einer neuen Zahlung wird überprüft, ob der Betrag und die Beträge anderer Zahlungen des Tages immer noch innerhalb des Kontolimits liegen, und entweder wird der Datensatz gespeichert oder es wird ein Fehler angezeigt. Jetzt

, nehmen wir an, ich habe Konto mit Limit $ 100, und gleichzeitig zwei Zahlungen von $ 99 erstellt werden. Jeder würde eine Auswahl treffen, sehen, dass nichts da ist, und fortfahren, sich selbst zu speichern, was dazu führt, dass insgesamt 198 $ gespeichert werden.

Was würden Sie dagegen tun? Ich habe darüber nachgedacht, zu Beginn der Transaktion eine Schreibsperre auf die Zahlungstabelle zu setzen, aber das scheint ziemlich umständlich, da ich nur wirklich darauf bedacht bin, Zahlungen, die zu einem bestimmten Konto gehören, nicht von anderen Transaktionen lesen zu lassen. Gibt es andere Möglichkeiten, diese Situation besser zu bewältigen?

Antwort

3

ich eine Schreibsperre auf die Zahlungen Tabelle zu Beginn der Transaktion Ausstellung habe darüber nachgedacht, aber das beendigen scheint

eheavy-handed

Vorausgesetzt, Sie sprechen bereits über Transaktionen, nehme ich an, dass Sie nicht verwenden MyISAM, aber stattdessen InnoDB oder eine andere Engine, die bereits Transaktionen unterstützt.

für Lese Sperren oder auf Transaktionen schreiben Unteilbarkeit von Operationen zu erhalten, ist nicht etwas, das manuell getan werden soll. Es ist die Aufgabe der Isolationsstufe Ihrer Transaktion, dies zu tun. Dadurch wird auch die Atomizität der Operationen zwischen dem Öffnen der Transaktion und dem Sperren Ihrer Tabelle oder Datensätze erhalten, so dass in der Zwischenzeit keine Lesevorgänge ausgeführt werden.

Für den Anwendungsfall beschreiben Sie, was Sie wollen, sind Geschäfte mit der ‚SERIALIZABLE‘ Isolationsstufe, die für Lesesperre wird und schreibt. Außerdem werden automatisch nur die Datensätze gesperrt, von denen Sie gelesen haben (auch wenn Sie nach Bereichen suchen), sodass die verbleibenden Datensätze für die Bearbeitung frei bleiben.

Durch die ‚SERIALIZABLE‘ Isolationsstufe, sobald Sie die Informationen aus der Tabelle zu lesen, alle Versuche, zu aktualisieren oder die Datensätze gelesen werden müssen warten, bis die Transaktion abgeschlossen ist. Stellen Sie außerdem sicher, dass Sie gelesen haben, bevor Sie mit derselben Transaktion aktualisieren, sodass Sie sicher sind, dass Sie mit dem richtigen Wert arbeiten.

Sie können mehr über Isolationsstufen hier lesen: http://en.wikipedia.org/wiki/Isolation_(database_systems) http://www.databasejournal.com/features/mysql/article.php/3393161/MySQL-Transactions-Part-II---Transaction-Isolation-Levels.htm

Sie können lernen, wie man Setup die Isolationsstufe Ihrer Transaktionen hier: http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html

+0

„, sobald Sie die Informationen aus der Tabelle gelesen , alle Versuche, diese Datensätze zu aktualisieren oder zu lesen, müssen auf diese Transaktion warten. "- Was ist, wenn die Auswahl keine Datensätze enthält? oder im Fall des Fragestellers fragt er nach dem Gesamtwert existierender Datensätze, bevor er neue hinzufügt. wie weiß mysql was zu sperren? –