Code/PHP

[라라벨] DB 동시 쓰기 요청시 중복 레코드 생성 방지 (중복 방지)

codens 2021. 6. 30. 15:22


    - 동시 요청으로 데이터베이스 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가 내장 되면서 삭제됨

반응형