Created
November 22, 2018 15:53
-
-
Save Denkong/7b45f70188e8ed4483ca8e22fe569f2f to your computer and use it in GitHub Desktop.
SQL - блокировки, транзакции
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
===SQL==== | |
Транзакция — это операция, состоящая из одного или нескольких запросов к базе данных. | |
Суть транзакций — обеспечить корректное выполнение всех запросов в рамках одной транзакции, | |
а так-же обеспечить механизм изоляции транзакций друг от друга для решения проблемы совместного доступа к данным. | |
set autocommit=0; //отключаем autocommit | |
Start transaction; (также, можно написать BEGIN; ) | |
Select * from table where ... FOR UPDATE; // блокирует записаь, снимается после commit | |
…какие-то действий с БД (insert, update,delete…) | |
commit; //Фиксация действий, запись их в физическую БД | |
====LARAVEL=== | |
В конструкторе запросов есть несколько функций, которые помогают делать «пессимистическую блокировку» (pessimistic locking) | |
для ваших операторов SELECT. Для запуска оператора SELECT с «разделяемой блокировкой» вы можете использовать в запросе метод sharedLock(). | |
Разделяемая блокировка предотвращает изменение выбранных строк до конца транзакции: | |
DB::table('users')->where('votes', '>', 100)->sharedLock()->get(); | |
Или вы можете использовать метод lockForUpdate(). | |
Блокировка «для изменения» предотвращает изменение строк и их выбор другими разделяемыми блокировками: | |
DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get(); | |
===ПРИМЕР LARAVEL ==== | |
DB::transaction(function () { | |
$balance = DB::table('test')->where('id', '=', 2)->lockForUpdate()->value('number'); | |
sleep(20); | |
$test = DB::table('test')->where([['id',1],])->update(['number'=>$balance-10000]); | |
}); | |
===ПРИМЕР С МЕТКОЙ В БД==== | |
$balance = DB::table('test')->where('id',1)->value('number'); | |
$edit = DB::table('test')->where('id',1)->value('edit'); | |
if ($edit != 1){ | |
DB::table('test')->where('id',1)->update(['edit'=>1]); | |
$data=[ | |
'name'=>$req->name, | |
'number'=>$balance-$req->number | |
]; | |
try { | |
$test = DB::table('test')->where([['id',1],['number',$balance]])->lockForUpdate()->update($data); | |
DB::table('test')->where('id',1)->update(['edit'=>-1]); | |
dd($test); | |
return redirect()->back(); | |
} | |
catch (\Exception $e) { | |
return ("Ошибка обновления в БД. Возможно, данная пара ИМЕНИ/ПРЕФИКСА уже существует"); | |
} | |
} else { | |
return 'Ошибка'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment