Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL:Transaktionen vs. Sperren von Tabellen

Das Sperren von Tabellen verhindert, dass andere DB-Benutzer die von Ihnen gesperrten Zeilen/Tabellen beeinflussen. Aber Sperren an und für sich stellen NICHT sicher, dass Ihre Logik in einem konsistenten Zustand herauskommt.

Denken Sie an ein Bankensystem. Wenn Sie eine Rechnung online bezahlen, sind mindestens zwei Konten von der Transaktion betroffen:Ihr Konto, von dem das Geld abgebucht wird. Und das Konto des Empfängers, auf das das Geld überwiesen wird. Und das Konto der Bank, auf das sie gerne alle für die Transaktion erhobenen Servicegebühren einzahlen. Angesichts der Tatsache (wie heutzutage jeder weiß), dass Banken außerordentlich dumm sind, nehmen wir an, ihr System funktioniert so:

$balance = "GET BALANCE FROM your ACCOUNT";
if ($balance < $amount_being_paid) {
    charge_huge_overdraft_fees();
}
$balance = $balance - $amount_being paid;
UPDATE your ACCOUNT SET BALANCE = $balance;

$balance = "GET BALANCE FROM receiver ACCOUNT"
charge_insane_transaction_fee();
$balance = $balance + $amount_being_paid
UPDATE receiver ACCOUNT SET BALANCE = $balance

Jetzt, da es keine Sperren und keine Transaktionen gibt, ist dieses System anfällig für verschiedene Rennbedingungen, von denen die größte darin besteht, dass mehrere Zahlungen auf Ihrem Konto oder auf dem Konto des Empfängers parallel ausgeführt werden. Während Ihr Code Ihr Guthaben abgerufen hat und die huge_overdraft_fees() und so weiter ausführt, ist es durchaus möglich, dass eine andere Zahlung den gleichen Codetyp parallel ausführt. Sie werden Ihr Guthaben abrufen (z. B. 100 $), ihre Transaktionen durchführen (die 20 $ herausnehmen, die Sie bezahlen, und die 30 $, mit denen sie Sie verarschen), und jetzt haben beide Codepfade zwei verschiedene Salden:80 $ und $70. Je nachdem, welches zuletzt endet, erhalten Sie am Ende eines dieser beiden Guthaben auf Ihrem Konto, anstatt der 50 $, die Sie hätten haben sollen (100 $ - 20 $ - 30 $). In diesem Fall „Bankfehler zu Ihren Gunsten“.

Nehmen wir an, Sie verwenden Sperren. Ihre Rechnungszahlung (20 $) kommt zuerst in die Röhre, also gewinnt sie und sperrt Ihren Kontodatensatz. Jetzt haben Sie die exklusive Nutzung und können die 20 $ vom Guthaben abziehen und das neue Guthaben in Ruhe zurückschreiben ... und Ihr Konto endet wie erwartet bei 80 $. Aber ... uhoh ... Sie versuchen, das Konto des Empfängers zu aktualisieren, und es ist gesperrt und länger gesperrt, als der Code es zulässt, wodurch Ihre Transaktion zeitlich überschritten wird ... Wir haben es mit dummen Banken zu tun, also anstatt einen richtigen Fehler zu haben Behandlung, zieht der Code einfach einen exit() , und Ihre 20 $ verschwinden in einem Hauch von Elektronen. Jetzt sind Ihnen 20 $ ausgegangen, und Sie schulden dem Empfänger immer noch 20 $, und Ihr Telefon wird beschlagnahmt.

Also ... geben Sie Transaktionen ein. Sie starten eine Transaktion, belasten Ihr Konto mit 20 $, Sie versuchen, dem Empfänger 20 $ gutzuschreiben ... und wieder explodiert etwas. Aber dieses Mal statt exit() , kann der Code einfach rollback ausführen , und puff, Ihre 20 $ werden Ihrem Konto auf magische Weise wieder gutgeschrieben.

Am Ende läuft es darauf hinaus:

Sperren halten andere davon ab, Datenbankeinträge zu stören, mit denen Sie es zu tun haben. Transaktionen verhindern, dass "spätere" Fehler "frühere" Dinge, die Sie getan haben, stören. Beides allein kann nicht garantieren, dass es am Ende gut ausgeht. Aber zusammen tun sie es.

in der morgigen Lektion:The Joy of Deadlocks.