sql >> Database teknologi >  >> RDS >> Mysql

MySQL:Transaktioner vs låsetabeller

Låsning af tabeller forhindrer andre DB-brugere i at påvirke de rækker/tabeller, du har låst. Men låse vil i sig selv IKKE sikre, at din logik kommer ud i en konsistent tilstand.

Tænk på et banksystem. Når du betaler en regning online, er der mindst to konti, der er påvirket af transaktionen:Din konto, hvorfra pengene tages. Og modtagerens konto, som pengene overføres til. Og bankens konto, som de gladeligt indsætter alle de servicegebyrer, der opkræves for transaktionen. I betragtning af (som alle ved i dag) at banker er ekstraordinært dumme, lad os sige, at deres system fungerer sådan her:

$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

Nu, uden låse og ingen transaktioner, er dette system sårbart over for forskellige raceforhold, hvoraf den største er flere betalinger, der udføres på din konto eller modtagerens konto parallelt. Mens din kode har din saldo hentet og laver de enorme_overtræksgebyrer() og hvad dertil, er det fuldt ud muligt, at en anden betaling vil køre den samme type kode parallelt. De henter din saldo (f.eks. $100), udfører deres transaktioner (tager de $20 ud, du betaler, og de $30, de sviner dig til), og nu har begge kodestier to forskellige saldi:$80 og 70 USD. Afhængigt af hvilke der slutter sidst, ender du med en af ​​disse to saldi på din konto, i stedet for de $50, du skulle have endt med ($100 - $20 - $30). I dette tilfælde "bankfejl til din fordel".

Lad os nu sige, at du bruger låse. Din regning ($20) rammer først røret, så den vinder og låser din kontopost. Nu har du eksklusiv brug og kan trække $20 fra saldoen og skrive den nye saldo tilbage i ro og mag... og din konto ender som forventet på $80. Men... uhoh... Du prøver at opdatere modtagerens konto, og den er låst og låst længere end koden tillader, og timeout din transaktion... Vi har at gøre med dumme banker, så i stedet for at have en ordentlig fejl håndtering, trækker koden bare en exit() , og dine $20 forsvinder til et pust af elektroner. Nu er du ude med $20, og du skylder stadig $20 til modtageren, og din telefon bliver overtaget.

Så... indtast transaktioner. Du starter en transaktion, du debiterer din konto $20, du forsøger at kreditere modtageren med $20... og noget blæser op igen. Men denne gang i stedet for exit() , koden kan bare gøre rollback , og puf, dine $20 føjes på magisk vis tilbage til din konto.

I sidste ende går det ud på dette:

Låse forhindrer andre i at blande sig i databaseregistreringer, du har at gøre med. Transaktioner forhindrer eventuelle "senere" fejl i at forstyrre "tidligere" ting, du har gjort. Ingen af ​​dem alene kan garantere, at tingene lykkes i sidste ende. Men sammen gør de det.

i morgendagens lektion:The Joy of Deadlocks.



  1. SQL dataopdagelse og klassificering

  2. Postgres sql indsæt forespørgselssyntaksfejl fra phpPgAdmin

  3. Oracle SQL pivotforespørgsel

  4. Sådan forbedres ydeevnen for SQLite-databasen til Android