sql >> Databasteknik >  >> RDS >> Mysql

MySQL:Transaktioner vs låsningstabeller

Låsning av tabeller förhindrar andra DB-användare från att påverka de rader/tabeller du har låst. Men lås, i och för sig, kommer INTE att säkerställa att din logik kommer ut i ett konsekvent tillstånd.

Tänk på ett banksystem. När du betalar en räkning online finns det minst två konton som påverkas av transaktionen:Ditt konto, från vilket pengarna tas. Och mottagarens konto, till vilket pengarna överförs. Och bankens konto, som de gärna sätter in alla serviceavgifter som tas ut för transaktionen. Med tanke på (som alla vet nuförtiden) att banker är utomordentligt dumma, låt oss säga att deras system fungerar så här:

$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, utan lås och inga transaktioner, är detta system sårbart för olika tävlingsförhållanden, varav den största är att flera betalningar görs på ditt konto eller mottagarens konto parallellt. Medan din kod har ditt saldo hämtat och gör enorma_overdraft_fees() och vad som helst, är det fullt möjligt att någon annan betalning kommer att köra samma typ av kod parallellt. De kommer att hämta ditt saldo (säg 100 USD), göra sina transaktioner (ta ut de 20 USD du betalar och de 30 USD som de tjatar på dig), och nu har båda kodvägarna två olika saldon:80 USD och 70 USD. Beroende på vilka som slutar sist, kommer du att få något av dessa två saldon på ditt konto, istället för de $50 du borde ha slutat med ($100 - $20 - $30). I det här fallet, "bankfel till din fördel".

Låt oss nu säga att du använder lås. Din fakturabetalning ($20) träffar pipan först, så den vinner och låser ditt kontoregister. Nu har du exklusiv användning och kan dra av $20 från saldot och skriva tillbaka det nya saldot i lugn och ro... och ditt konto slutar med $80 som förväntat. Men... öhh... Du försöker uppdatera mottagarens konto, och det är låst och låst längre än koden tillåter, timeout för din transaktion... Vi har att göra med dumma banker, så istället för att ha ordentligt fel hantering, drar koden bara en exit() , och dina 20 dollar försvinner till en bloss av elektroner. Nu är du ute med 20 USD, och du är fortfarande skyldig 20 USD till mottagaren, och din telefon blir återtagen.

Så... skriv in transaktioner. Du startar en transaktion, du debiterar ditt konto $20, du försöker kreditera mottagaren med $20... och något blåser upp igen. Men den här gången istället för exit() , koden kan bara göra rollback , och poff, dina $20 läggs magiskt tillbaka till ditt konto.

I slutändan kokar det ner till detta:

Lås hindrar någon annan från att störa databasposter du har att göra med. Transaktioner hindrar eventuella "senare" fel från att störa "tidigare" saker du har gjort. Ingendera ensam kan garantera att saker och ting löser sig i slutändan. Men tillsammans gör de det.

i morgondagens lektion:The Joy of Deadlocks.



  1. Hur pratar Access med ODBC-datakällor? Del 3

  2. Hur får jag den aktuella tidszonen för MySQL?

  3. Hur man installerar och konfigurerar ClickHouse på Ubuntu 20.04

  4. Använda aggregerade funktioner (SUM, AVG, MAX, MIN, COUNT, DISTINCT) i MySQL