[라라벨] DB 동시 쓰기 요청시 중복 레코드 생성 방지 (중복 방지)
- 동시 요청으로 데이터베이스 insert 발생시 중복 데이터 생성 방지 방법
- php laravel simultaneous requests avoid duplicate record lock without unique
- php에서 비동기 다중 요청시 공유 자원 제어
//-------------------------------------
* cache lock 사용
Atomic Lock
https://laravel.com/docs/8.x/cache#managing-locks
https://laravel.com/api/8.x/Illuminate/Cache/Lock.html
\Cache::lock('foo', 10)->block(5, function () use($row)) {
self::firstOrCreate($row);// DB 작업
});
//-------------------------------------
* table lock 사용
- 중복 방지 가능
- 주의! 여러쿼리가 동시에 시도되었을때 첫번째 쿼리로 등록되지 않는 경우도 있음
- \DB::unprepared() 사용해서 명령 실행, \DB::raw(), \DB::statement()는 안됨
\DB::unprepared('LOCK TABLES tbl_users WRITE');
if (self::where($row0)->first() == null) {
$ret1 = self::create($row);
}
\DB::unprepared('UNLOCK TABLES');
//-------------------------------------
* php lock 사용
php-lock /lock
https://github.com/php-lock/lock
- flock(), ext-redis, ext-pdo_mysql 등을 이용해 락을 구현
//-----------------------------------------------------------------------------
// 참고만
//-------------------------------------
* 라라벨 sharedLock , lockForUpdate 사용
- 이미 있는 레코드에 락이 걸림
https://laravel.com/docs/8.x/queries#pessimistic-locking
- 트랜잭션 안에서 사용해야 함
$this->database->transaction(function () use ($id) {
if ($this->database->table($this->table)->lockForUpdate()->find($id)) {
$this->database->table($this->table)->where('id', $id)->delete();
}
});
- SharedLock:
DB::table('users')->where('votes', '>', 100)->sharedLock()->get();
선택된 row 가 트랜젝션이 커밋되기 전까지 수정되는 것을 방지
- LockForUpdate:
DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();
row 가 수정되는 것 또는 다른 공유 lock 에 의해서 선택되는 것을 방지
//-------------------------------------
* 트랜잭션
- 안됨 - 중복 방지에 소용없음
- DB 작업중 에러발생시 복원하는 기능
\DB::beginTransaction();
//-------------------------------------
// 참고
krakjoe /apcu
https://github.com/krakjoe/apcu - 867
https://www.php.net/apcu
https://pecl.php.net/package/APCu
APCu - APC User Cache
in-memory key-value store for PHP
//-------------------------------------
APC
https://pecl.php.net/package/APC
Alternative PHP Cache
PHP 7 에서 opcache가 내장 되면서 삭제됨