Mengunci tabel mencegah pengguna DB lain mempengaruhi baris / tabel yang telah Anda kunci. Tapi kunci, di dalam dan dari dirinya sendiri, TIDAK akan memastikan bahwa logika Anda keluar dalam keadaan yang konsisten.
Pikirkan sistem perbankan. Saat Anda membayar tagihan secara online, setidaknya ada dua akun yang terpengaruh oleh transaksi tersebut: Akun Anda, tempat uang diambil. Dan akun penerima, tempat uang ditransfer. Dan rekening bank, tempat mereka akan dengan senang hati menyetorkan semua biaya layanan yang dibebankan pada transaksi tersebut. Mengingat (seperti yang diketahui semua orang akhir-akhir ini) bahwa bank sangat bodoh, katakanlah sistem mereka bekerja seperti ini:
$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
Sekarang, tanpa kunci dan tanpa transaksi, sistem ini rentan terhadap berbagai kondisi balapan, yang terbesar adalah beberapa pembayaran yang dilakukan di akun Anda, atau akun penerima secara paralel. Sementara kode Anda telah mengambil saldo Anda dan melakukan huge_overdraft_fees () dan yang lainnya, sangat mungkin bahwa beberapa pembayaran lain akan menjalankan jenis kode yang sama secara paralel. Mereka akan mengambil saldo Anda (katakanlah, $ 100), melakukan transaksi mereka (ambil $ 20 yang Anda bayarkan, dan $ 30 yang mereka gunakan untuk mengacaukan Anda), dan sekarang kedua jalur kode memiliki dua saldo berbeda: $ 80 dan $ 70. Bergantung pada saldo mana yang terakhir kali berakhir, Anda akan mendapatkan salah satu dari dua saldo tersebut di akun Anda, bukan $ 50 yang seharusnya Anda dapatkan ($ 100 - $ 20 - $ 30). Dalam kasus ini, "kesalahan bank dalam keuntungan Anda"
Sekarang, katakanlah Anda menggunakan kunci. Pembayaran tagihan Anda ($ 20) menyentuh pipa terlebih dahulu, sehingga menang dan mengunci catatan akun Anda. Sekarang Anda memiliki penggunaan eksklusif, dan dapat mengurangi $ 20 dari saldo, dan menulis kembali saldo baru dengan damai ... dan akun Anda berakhir dengan $ 80 seperti yang diharapkan. Tapi ... uhoh ... Anda mencoba memperbarui akun penerima, dan akun itu terkunci, dan dikunci lebih lama dari yang diizinkan oleh kode, waktu transaksi Anda habis ... Kami berurusan dengan bank-bank bodoh, jadi alih-alih mengalami kesalahan yang tepat penanganan, kode hanya menarik exit()
, dan $ 20 Anda lenyap menjadi embusan elektron. Sekarang Anda kehabisan $ 20, dan Anda masih berhutang $ 20 ke receiver, dan telepon Anda diambil alih.
Jadi ... masukkan transaksi. Anda memulai transaksi, Anda mendebit akun Anda $ 20, Anda mencoba mengkredit penerima dengan $ 20 ... dan sesuatu meledak lagi. Tapi kali ini, alih-alih exit()
, kodenya bisa begitu saja rollback
, dan poof, $ 20 Anda secara ajaib ditambahkan kembali ke akun Anda.
Pada akhirnya, intinya adalah:
Kunci mencegah orang lain mengganggu catatan database apa pun yang Anda tangani. Transaksi mencegah kesalahan "nanti" mengganggu hal "sebelumnya" yang telah Anda lakukan. Tidak satu pun yang dapat menjamin bahwa semuanya berjalan dengan baik pada akhirnya. Tapi bersama-sama, mereka melakukannya.
dalam pelajaran besok: The Joy of Deadlocks.