복붙노트

[SQL] MySQL의 : 잠금 테이블 대 거래

SQL

MySQL의 : 잠금 테이블 대 거래

나는 조금 데이터베이스 무결성을 보장하기 위해 테이블을 잠금 대 거래와 혼동하고 확실히 SELECT 및 UPDATE 동기화 및 그것과 다른 연결를 방해에 남아 있도록 해요. 나는 필요 :

SELECT * FROM table WHERE (...) LIMIT 1

if (condition passes) {
   // Update row I got from the select 
   UPDATE table SET column = "value" WHERE (...)

   ... other logic (including INSERT some data) ...
}

나는 다른 쿼리를 방해하지 않고 행을 업데이트하는 연결 완료되기 전에 '이전 값을'읽기 같은 SELECT를 (수행 할 수 있도록해야합니다.

난 그냥 확인 만 1 연결이 한 번에 이렇게되었는지 확인에 LOCK 테이블 테이블에 기본 수있어, 내가 다있을 때 잠금을 해제,하지만 과잉처럼 보인다. 트랜잭션에서 같은 일을 (다른 연결 시도 동일한 프로세스 다른 여전히 처리하는 동안을 보장하지)를 수행하는 것이겠습니까 포장? 아니면 SELECT는 ... UPDATE 또는 SELECT ... FOR LOCK IN SHARE MODE는 더 좋을 것이다?

해결법

  1. ==============================

    1.테이블을 잠그면 잠긴 한 행 / 테이블에 영향을 미치는 다른 DB 사용자를 방지 할 수 있습니다. 그러나 잠금은, 그 자체로 그리고, 당신의 논리가 일관성있는 상태에 나오는 것을 보장되지 않습니다.

    테이블을 잠그면 잠긴 한 행 / 테이블에 영향을 미치는 다른 DB 사용자를 방지 할 수 있습니다. 그러나 잠금은, 그 자체로 그리고, 당신의 논리가 일관성있는 상태에 나오는 것을 보장되지 않습니다.

    금융 시스템의 생각. 계정, 돈이 촬영되는 : 온라인 청구서를 지불 할 때, 트랜잭션에 의해 영향을받는 두 개 이상의 계정이있다. 그리고 수신기의 계정이되는 돈이 전송됩니다. 그리고 은행의 계좌가되는 그들은 행복하게 거래에 부과하는 모든 서비스 수수료를 입금합니다. 은행은 매우 바보 같은 것을 (모두가이 일을 알고로)을 감안할 때,의는 자신의 시스템이 다음과 같이 작동 가정 해 봅시다 :

    $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
    

    이제, 아니 잠금없이 트랜잭션이 시스템은 다양한 경쟁 조건에 취약, 가장 큰하는 여러 계정에서 수행되는 지불, 또는 병렬로 수신자의 계정입니다. 코드가 잔고가 검색 한과 huge_overdraft_fees ()와 이것 저것을하고 있지만, 그것은 어떤 다른 지불 병렬 코드의 동일한 유형을 실행됩니다 전적으로 가능하다. $ 80 : 그들은 당신의 균형 (예를 들어, $, 100), 자신의 거래는, 지금은 모두 코드 경로가 서로 다른 두 가지의 균형이 (당신이 지불하고있는 $ 20와 $ (30) 그들이 당신을 통해 나사하고 꺼내) 않습니다를 검색 할 수 있습니다 $ (70). (- $ 20 - $ 30-100 $) 어떤 것들 완료 마지막에 따라, 대신 당신이 결국해야 $ 50의 계정에서 두 잔액 중 하나가 될 겁니다. 이 경우, "당신의 호의에있는 은행 오류".

    자, 이제 당신이 잠금을 사용하는 가정 해 봅시다. 이 승리하고 계정 기록을 고정 귀하의 청구서 지불 ($ 20), 첫째 파이프를 안타. 지금 당신은 독점적으로 사용할 수있어, 그리고 균형에서 $ 20 공제, 평화의 새로운 균형을 다시 쓸 수 ... 예상대로 계정은 $ 80 끝납니다. 하지만 ... uhoh ... 당신은 수신기의 계정을 업데이트 가려고하고, 잠겨, 긴 잠겨 코드는 트랜잭션을 시간 초과 ... 우린 바보 은행과 거래, 그래서 대신 가진 적절한 오류를 허용하는 것보다 처리 코드는 출구 () 및 전자의 퍼프로 당신의 $ (20) 사라지다를 가져옵니다. 지금 당신은 $ 20 밖으로있어, 당신은 여전히 ​​수신기에 $ 20 빚, 당신의 전화가 다시 소유 가져옵니다.

    그래서 ... 거래를 입력합니다. 당신은 트랜잭션을 시작, 당신은 당신이 $ 20 수신기를 신용하려고 계정 $ 20 직불 ... 뭔가가 다시 불면. 그러나 이번에는, 대신에 종료 ()의 코드는 단지 롤백 수행하고 휙 수 있습니다, 당신의 $ 20 마술 계정에 다시 추가됩니다.

    결국,이 귀결 :

    잠금 당신이 상대하고있는 데이터베이스 레코드 방해 다른 사람을 유지한다. 거래는 당신이 한 "이전"일을 방해하는 어떤 "나중에"오류를 유지한다. 일이 결국 확인을 작동하는지 나도 혼자 캔 보증. 그러나 함께, 그들은 않습니다.

    교착 상태의 기쁨 : 내일의 교훈이다.

  2. ==============================

    2.당신이 말한대로 일반적으로 제공하므로 그들이 거래에인지 아닌지 상관없이, 테이블을 잠글 것, 트랜잭션 내부 SELECT ... FOR UPDATE 또는 SELECT ... LOCK IN SHARE MODE를 원한다. 어떤 당신이 다른 트랜잭션이 트랜잭션이 진행되는 동안 해당 행을 읽을 수 있도록할지 여부에 달려 하나를 선택.

    당신이 말한대로 일반적으로 제공하므로 그들이 거래에인지 아닌지 상관없이, 테이블을 잠글 것, 트랜잭션 내부 SELECT ... FOR UPDATE 또는 SELECT ... LOCK IN SHARE MODE를 원한다. 어떤 당신이 다른 트랜잭션이 트랜잭션이 진행되는 동안 해당 행을 읽을 수 있도록할지 여부에 달려 하나를 선택.

    http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

    다른 트랜잭션이 여전히 함께 와서 해당 행을 수정할 수있는 일관된 스냅 샷 START 트랜잭션, 당신을 위해 트릭을 할 수 없습니다. 이것은 바로 아래 링크의 상단에 언급되어있다.

    http://dev.mysql.com/doc/refman/5.0/en/innodb-consistent-read.html

  3. ==============================

    3.트랜잭션 개념과 잠금 장치는 다르다. 그러나 거래는 ACID 원칙을 따르도록하기 위해 잠금을 사용했다. 당신이 읽기 / 쓰기 동안 같은 시점에서 읽기 / 쓰기 다른 사람을 방지하기 위해 테이블을하려는 경우, 당신은이 작업을 수행하기 위해 잠금이 필요합니다. 당신이 확실 데이터 무결성 및 일관성을 확인하려면, 당신은보다 효율적으로 사용하는 거래를했다. 나는 자물쇠와의 거래에 격리 수준의 혼합 개념을 생각합니다. SERIALIZE 원하는 수준이어야한다, 트랜잭션의 격리 수준을 검색하십시오.

    트랜잭션 개념과 잠금 장치는 다르다. 그러나 거래는 ACID 원칙을 따르도록하기 위해 잠금을 사용했다. 당신이 읽기 / 쓰기 동안 같은 시점에서 읽기 / 쓰기 다른 사람을 방지하기 위해 테이블을하려는 경우, 당신은이 작업을 수행하기 위해 잠금이 필요합니다. 당신이 확실 데이터 무결성 및 일관성을 확인하려면, 당신은보다 효율적으로 사용하는 거래를했다. 나는 자물쇠와의 거래에 격리 수준의 혼합 개념을 생각합니다. SERIALIZE 원하는 수준이어야한다, 트랜잭션의 격리 수준을 검색하십시오.

  4. ==============================

    4.IF NOT 존재 시도 ... 그리고 여러 스레드가 같은 테이블을 갱신 한 경쟁 조건이 발생하는 INSERT를 수행 할 때 나는 비슷한 문제가 있었다.

    IF NOT 존재 시도 ... 그리고 여러 스레드가 같은 테이블을 갱신 한 경쟁 조건이 발생하는 INSERT를 수행 할 때 나는 비슷한 문제가 있었다.

    작성하는 방법을 삽입하는 경우가 NOT 표준 SQL에서 쿼리를 EXISTS : 여기 문제에 대한 해결책을 발견

    내가 직접 질문을하지만, 하나의 문이 매우 유용 등의 확인 및 삽입을 수행하는 동일한 원리에 응답하지 않습니다이 실현; 당신은 당신의 업데이트를 수행하기 위해 수정할 수 있어야합니다.

  5. ==============================

    5.당신은 잠금 및 거래와 혼동된다. 그들은 RMDB에서 다른 두 가지입니다. 트랜잭션이 데이터 분리에 초점을 맞추고있는 동안 잠금 동시 작업을 방지 할 수 있습니다. 정화 및 일부 우아한 솔루션이 위대한 기사를 확인하세요.

    당신은 잠금 및 거래와 혼동된다. 그들은 RMDB에서 다른 두 가지입니다. 트랜잭션이 데이터 분리에 초점을 맞추고있는 동안 잠금 동시 작업을 방지 할 수 있습니다. 정화 및 일부 우아한 솔루션이 위대한 기사를 확인하세요.

  6. ==============================

    6.나는를 사용하십시오

    나는를 사용하십시오

    START TRANSACTION WITH CONSISTENT SNAPSHOT;
    

    로 시작하고,하기

    COMMIT;
    

    로 종료합니다.

    당신이 사이에서 할 뭐든지 (이노 인) 스토리지 엔진을 지원하는 거래를하는 경우 데이터베이스의 다른 사용자로부터 격리됩니다.

  7. from https://stackoverflow.com/questions/4226766/mysql-transactions-vs-locking-tables by cc-by-sa and MIT license