sql >> Databáze >  >> RDS >> Mysql

MySQL:Transakce vs zamykání tabulek

Uzamčení tabulek zabrání ostatním uživatelům DB ovlivnit řádky/tabulky, které jste zamkli. Ale zámky, samy o sobě, NEZAJIŠŤUJÍ, že vaše logika vyjde v konzistentním stavu.

Představte si bankovní systém. Když platíte účet online, transakce se týká nejméně dvou účtů:Váš účet, ze kterého se odebírají peníze. A účet příjemce, na který jsou peníze převedeny. A bankovní účet, na který vám rádi vloží všechny poplatky za služby účtované při transakci. Vzhledem k tomu (jak dnes každý ví), že banky jsou mimořádně hloupé, řekněme, že jejich systém funguje takto:

$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

Nyní, bez zámků a bez transakcí, je tento systém zranitelný vůči různým rasovým podmínkám, z nichž největší je několik plateb prováděných paralelně na vašem účtu nebo na účtu příjemce. Zatímco váš kód má načten váš zůstatek a provádí huge_overdraft_fees() a cokoli jiného, ​​je zcela možné, že stejný typ kódu bude souběžně probíhat i nějaká jiná platba. Získají váš zůstatek (řekněme 100 USD), provedou své transakce (vytáhnou 20 USD, které platíte, a 30 USD, kterými vás šrotují), a nyní mají obě cesty kódu dva různé zůstatky:80 USD a 70 dolarů. V závislosti na tom, který z nich skončí jako poslední, skončíte s některým z těchto dvou zůstatků na vašem účtu namísto 50 USD, které byste měli skončit (100 USD – 20 USD – 30 USD). V tomto případě „chyba banky ve váš prospěch“.

Nyní řekněme, že používáte zámky. Vaše platba účtu (20 $) dopadne jako první, takže vyhraje a uzamkne váš účet. Nyní máte výhradní použití a můžete odečíst 20 USD ze zůstatku a v klidu zapsat nový zůstatek zpět... a váš účet skončí s 80 USD, jak se očekává. Ale... uhoh... Pokusíte se aktualizovat účet příjemce a ten je zamknutý a zamčený déle, než kód dovoluje, čímž vypršel časový limit vaší transakce... Máme co do činění s hloupými bankami, takže místo řádné chyby kód pouze vyvolá exit() a vašich 20 dolarů zmizí v obláčky elektronů. Nyní jste mimo 20 USD a stále dlužíte 20 USD přijímači a váš telefon bude odebrán.

Takže... zadejte transakce. Zahájíte transakci, odečtete ze svého účtu 20 $, pokusíte se připsat 20 $ příjemci... a zase něco praskne. Ale tentokrát místo exit() , kód může provést pouze rollback a fuj, vašich 20 $ se magicky přidá zpět na váš účet.

Nakonec se to scvrkne na toto:

Zámky brání komukoli jinému zasahovat do jakýchkoli záznamů databáze, se kterými máte co do činění. Transakce zabraňují tomu, aby jakékoli „pozdější“ chyby narušovaly „dřívější“ věci, které jste udělali. Ani jeden nemůže zaručit, že vše nakonec dopadne dobře. Ale dohromady ano.

v zítřejší lekci:The Joy of Deadlocks.



  1. Jak opravit databázi MySQL v cPanel

  2. Najděte rozdíl mezi časovými razítky v sekundách v PostgreSQL

  3. Mohl by někdo vysvětlit, co příkaz MERGE skutečně dělá v Oracle?

  4. Jak provádět průběžné upgrady pro MySQL