Таблица блокировки базы данных Laravel в параллельном запросе
Я хочу запретить обновлять мою базу данных, если внезапно несколько запросов отправляются в мою базу данных и обновляются одновременно.
Я создаю пользовательскую таблицу пользователей Laravel в качестве примера и использую JMeter для симуляции двух пользователей, отправляющих параллельный запрос на изменение одной и той же строки данных.
Например, сценарий
Мой банковский счет имеет 1000 долларов. В то же время, два запроса на перевод денег мистеру А и мистеру Б. отправляются с моего счета.
Мой счет для баланса - 1000, Запрос 1 - Отправьте 700 долларов мистеру А, а Запрос 2 - Отправьте 700 долларов мистеру Б. Если я не заблокировал стол, система будет обработана. У меня достаточно средств для отправки денег.
Моя цель состоит в том, что когда дело доходит до одновременного запроса, второй (FIFO, даже если веб-сервер параллелизма по-прежнему будет обрабатывать его и обрабатывать один из них как второй), выдаст исключение / или покажет ошибку возврата для запроса, который он использует,
ниже приведен мой код для теста, и я использую JMeter для его запуска. Тем не менее, тест показывает, что оба запроса обновляются. Следовательно, последний запрос перезапишет первый запрос.
Ниже я ожидаю, что Laravel выдаст исключение или ошибку для блокировки базы данных, но она все еще продолжается.
Route::get('/db-a', function() {
\DB::beginTransaction();
//lock the table
$rs = \DB::table('users')->where('id', '1')->lockForUpdate()->first();
$sql = "update users set remember_token='this is a' where id=1";
\DB::update(DB::raw($sql));
//purposely put the sleep to see can the table / row be locked
sleep(3);
\DB::commit();
$rs = DB::table('users')->where('id', '1')->first();
echo($rs->remember_token);
return;
});
Route::get('/db-b', function () {
\DB::beginTransaction();
//lock the table
$rs = \DB::table('users')->where('id', '1')->lockForUpdate()->first();
$sql = "update users set remember_token='this is b' where id=1";
\DB::update(DB::raw($sql));
//purposely put the sleep to see can the table / row be locked
sleep(3);
\DB::commit();
$rs = DB::table('users')->where('id', '1')->first();
echo($rs->remember_token);
return;
});
Я делаю другую версию для ручного перехвата исключения, но тоже не работает
Route::get('db-callback-a', function() {
try {
app('db')->transaction(function () {
$record = \DB::table('users')->where('id', 1)->lockForUpdate()->first();
$sql = "update users set remember_token='this is callback a' where id=1";
\DB::update(DB::raw($sql));
sleep(3);
});
}
catch (\Exception $e) {
// display an error to user
echo('Database Row in Use, update later');
}
});
Route::get('db-callback-b', function () {
try {
app('db')->transaction(function () {
$record = \DB::table('users')->where('id', 1)->lockForUpdate()->first();
$sql = "update users set remember_token='this is callback b' where id=1";
\DB::update(DB::raw($sql));
sleep(3);
});
} catch (\Exception $e) {
// display an error to user
echo ('Database Row in Use, update later');
}
});