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