Блокировка таблицы не позволяет другим пользователям БД от воздействия на строки/таблицы вы заблокированы. Но блокировки сами по себе НЕ гарантируют, что ваша логика выйдет в согласованном состоянии.
Подумайте о банковской системе.Когда вы оплачиваете онлайн-счет, на транзакцию влияет как минимум две аккаунта: ваша учетная запись, из которой берутся деньги. И счет получателя, в который перечисляются деньги. И счет банка, в который они с радостью будут перечислять все комиссионные, взимаемые с транзакции. Принимая во внимание (как всем известно, в эти дни), что банки чрезвычайно глупо, скажем, их система работает следующим образом:
$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
Теперь, без замков и без каких-либо операций, эта система является уязвимой к различным условиям гонки, самый большой из который представляет собой несколько платежей, выполняемых в вашей учетной записи, или учетную запись получателя параллельно. В то время как ваш код имеет ваш баланс, полученный и делающий огромный_overdraft_fees() и еще много чего, вполне возможно, что некоторые другие платежи будут работать с одним и тем же типом кода параллельно. Они будут получать ваш баланс (скажем, 100 долларов США), совершают свои транзакции (вынимают 20 долларов США, которые вы платите, и 30 долларов, за которые вы их заманиваете), и теперь оба пути кода имеют два разных баланса: 80 долларов США и $ 70. В зависимости от того, какие из них заканчиваются последним, вы получите один из двух балансов в своей учетной записи, вместо 50 долларов США, которые вы должны были получить (от $ 100 до $ 20 - $ 30). В этом случае «банковская ошибка в вашу пользу».
Теперь предположим, что вы используете блокировки. Сначала вы получаете платеж по счету (20 долларов США), поэтому он выигрывает и блокирует вашу учетную запись. Теперь у вас есть эксклюзивное использование, и вы можете вычесть 20 долларов из баланса, и снова записать новый баланс ... и ваша учетная запись заканчивается на 80 долларов, как ожидается. Но ... ухо ... Вы пытаетесь обновить учетную запись получателя, и она заблокирована и заблокирована дольше, чем позволяет код, тайминг вашей транзакции ... Мы имеем дело с глупыми банками, поэтому вместо правильной ошибки обработка, код просто тянет exit()
, а ваши 20 долларов исчезают в клубок электронов. Теперь у вас 20 долларов, и вы все равно должны 20 долларов за приемник, и ваш телефон получает обратно.
Итак ... введите транзакции. Вы начинаете транзакцию, вы дебетеваете свою учетную запись на 20 долларов США, вы пытаетесь кредитовать получателя с помощью 20 долларов ... и что-то снова взрывается. Но на этот раз, вместо exit()
, код может просто сделать rollback
, а пуф, ваши $ 20 волшебным образом добавлены обратно в вашу учетную запись.
В конце концов, сводится к следующему:
Замки держать кого-либо еще от вмешательства каких-либо записей в базе данных вы имеете дело с. Транзакции содержат любые «более поздние» ошибки от вмешательства в «ранние» вещи, которые вы сделали. Ни один из них не может гарантировать, что в итоге все будет хорошо. Но вместе они делают.
в уроке завтрашнего дня: Радость тупиков.
Я тоже все еще смущен. Скажем, у учетной записи приемника было 100 долларов, чтобы начать, и мы добавляем платеж в размере 20 долларов США из нашей учетной записи. Мое понимание транзакций заключается в том, что при их запуске любая операция в транзакции видит базу данных в состоянии, которое было в начале транзакции. т.е.: пока мы его не изменим, учетная запись получателя составляет 100 долларов США. Итак ... когда мы добавляем $ 20, мы фактически устанавливаем баланс в 120 долларов. Но что произойдет, если во время нашей транзакции кто-то спустил учетную запись приемника до 0 долларов? Это как-то предотвращено? Они волшебным образом получают 120 долларов снова? Именно поэтому нужны замки? – Russ
Да, вот где затворы вступают в игру. Правильная система блокирует запись записи, чтобы никто другой не мог обновить запись во время выполнения транзакции. Параноидальная система поставила бы безусловную блокировку записи, чтобы никто не мог прочитать «устаревший» баланс. –
В основном посмотрите на транзакции как на защиту вещей внутри вашего кода. Блокирует безопасные вещи через «параллельные» кодовые пути. До тупиков ... –