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