2014-09-24 4 views
1

이것이 격리 문제인지 그리고 어떻게 해결할 수 있는지 알아 내려고합니다. 두 개의 동시 연결이있는 데이터베이스가 있다고 가정합니다.동시 연결에서 InnoDB 트랜잭션 격리 수준

0. BEGIN transaction TX1 
1. TX1 performs SELECT VALUE 10 
2. TX1 performs INSERT VALUE 10 since it does not exist 
3. TX1 performs SELECT VALUE 20 
4. TX1 performs INSERT VALUE 20 since it does not exist 
5. BEGIN transaction TX2 in a different session, using a different connection 
6. TX2 performs SELECT VALUE 10 
7. TX2 performs INSERT VALUE 10 since TX1 hasn't committed yet 
8. COMMIT TX2 
9. COMMIT TX1 

현재 격리 수준은 반복적으로 읽을 수 있습니다. 다른 격리 수준으로 변경하여이 문제를 해결할 수 있습니까? 그렇다면 어떤 것입니까? 커밋되지 않은 읽기?

+1

고유 한 값입니까? select 쿼리에서 얻은 결과를 잠 그려면'select VALUE FROM TABLE * FOR UPDATE *'를 시도하십시오. https://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html을보십시오. – MrTux

+0

왜 2 개의 연결을 사용하고 있습니까? 그들은 별도의 서버 (마스터/슬레이브)에 연결되어 있습니까? – Jaydee

+0

@MrTux 예, 값은 고유 한 키입니다. 고맙습니다. –

답변

2

나는 더 긴 설명으로 내 의견을 공식화하려고합니다. 전제 조건 : InnoDB와 VALUE는 고유 한 키 또는 기본 키를 가지고있다.

OPS 예부터는

0. BEGIN transaction TX1 
1. TX1 performs SELECT VALUE 10 
2. TX1 performs INSERT VALUE 10 since it does not exist 
3. TX1 performs SELECT VALUE 20 
4. TX1 performs INSERT VALUE 20 since it does not exist 
5. BEGIN transaction TX2 in a different session, using a different connection 
6. TX2 performs SELECT VALUE 10 
7. TX2 performs INSERT VALUE 10 since TX1 hasn't committed yet 
    TX2 will block here until TX1 finishes, if TX1 rolls back this step succeedes, 
    if TX1 commits, you get an error here. 

이 상황이 SELECT 쿼리에 대한 FOR UPDATE 접미사를 사용 방지하기위한 방법은 다음과 같습니다 당신이 TX2는 실패하고 항상 사용 피할 수 FOR UPDATE 키워드를 사용하여

0. BEGIN transaction TX1 
1. TX1 performs SELECT VALUE 10 FOR UPDATE 
2. TX1 performs INSERT VALUE 10 since it does not exist 
3. TX1 performs SELECT VALUE 20 FOR UPDATE 
4. TX1 performs INSERT VALUE 20 since it does not exist 
5. BEGIN transaction TX2 in a different session, using a different connection 
6. TX2 performs SELECT VALUE 10 FOR UPDATE 
    based on the `FOR UPDATE` condition, TX2 will block here until TX1 finishes. 
    If TX1 commits, the result will be the row TX1 committed, if TX1 rolls back, 
    this query returns an empty result. 

가장 최근의 데이터 - 행 잠금이 작성됩니다 (따라서주의해서 사용하십시오). 그러나 교착 상태에 유의하십시오 (Database Deadlock in SELECT FOR UPDATE, 항상 동일한 순서로 "잠금").

+0

다중 연결을 열었을 때 선택/삽입 프로세스가 상당히 느려지더라도 (~ 20 개의 클라이언트 연결로 시도) 문제를 해결합니다. 이것에 대한 대안? 감사. –