2010-03-18 1 views
10

에서 교착 상태를 피하기 위해 나는이 다음 쿼리 (모든 테이블이 InnoDB에있는) 내가 스레드를 실행할 때 오른쪽 분명하기 때문에 내부 선택의, 교착 상태가 발생 방법 MySQL의

INSERT INTO busy_machines(machine) 
       SELECT machine FROM all_machines 
       WHERE machine NOT IN (SELECT machine FROM busy_machines) 
       and machine_name!='Main' 
       LIMIT 1 

?

내가 오류는 다음과 같습니다

(1213, 'Deadlock found when trying to get lock; try restarting transaction') 

가 어떻게 교착 상태를 피할 수있다? 쿼리가 작동하도록 변경하는 방법이 있습니까? 아니면 다른 것을해야합니까?

물론이 오류는 여러 번 실행하고 여러 스레드에서 실행 한 후에 만 ​​발생합니다.

+0

당신은 교착 상태 또는 잠금 경합을 경험하고 있습니까? – Quassnoi

+0

@Quassnoi : 질문에 정보를 추가했습니다. (1213, '잠금을 시도 할 때 교착 상태가 발견되어 트랜잭션을 다시 시작하십시오') – olamundo

+0

'show innodb status'는 마지막 교착 상태의 원인을 간략하게 설명합니다. – jonny

답변

5

"NOT IN"을 외부 조인으로 바꾸면 성능이 향상 될 것입니다.

단일 쿼리에서 동일한 테이블을 삽입하고 선택하지 않으려면이를 두 개의 쿼리로 분리 할 수도 있습니다. 이 같은

뭔가 :

  SELECT a.machine 
      into @machine 
      FROM all_machines a 
      LEFT OUTER JOIN busy_machines b on b.machine = a.machine 
      WHERE a.machine_name!='Main' 
      and b.machine IS NULL 
      LIMIT 1; 

      INSERT INTO busy_machines(machine) 
      VALUES (@machine); 
+0

MySQL 5.0 이상을 사용하는 경우 훌륭한 솔루션입니다. 그렇지 않으면 사용자 변수를 사용할 수 없습니다. 이렇게하면 교착 상태 문제도 피해야합니다. –

+0

내 쿼리가 내 쿼리와 어떻게 비슷한지 잘 모르겠다. 바깥 쪽 조인은 바쁜 컴퓨터에있는 컴퓨터도 반환하고 – olamundo

+0

@noam이 아닌 컴퓨터뿐만 아니라 "and b.machine IS where 절에 NULL이 있으면 busy_machines에있는 시스템이 제외됩니다. NOT IN과 동일한 데이터를 반환하지만 훨씬 효율적으로 처리합니다. –

11

필자는 select가 잠금을 획득하지 않으며 교착 상태의 원인이되어서는 안됩니다.

행을 삽입/업데이트/삭제할 때마다 잠금이 획득됩니다. 교 x 상태를 f 지하려면 동시 트랜잭션이 교 x 상태가 될 수있는 순서로 행을 갱신하지 않도록해야합니다. 일반적으로 교착 상태를 피하기 위해 을 사용해야합니다. 다른 트랜잭션 (예 : 항상 테이블 A가 먼저, 다음 테이블 B)에서도 항상 동일한 순서로 잠금을 획득해야합니다 ().

그러나 한 트랜잭션 내에서 하나의 테이블에만 삽입하면이 조건이 충족되며 일반적으로 교착 상태가 발생하지 않습니다. 거래에서 뭔가하고 있습니까?

그러나 인덱스가 누락 된 인 경우 교착 상태가 발생할 수 있습니다.. 삽입/업데이트/삭제의 행이있을 때 데이터베이스는 관계형 제약 조건을 확인해야합니다. 즉 관계가 일관성이 있는지 확인해야합니다. 그렇게하기 위해 데이터베이스는 관련 테이블의 외래 키를 점검해야합니다. 이 수정 된 행보다 다른 잠금을 획득하게 될 수 있습니다. 외래 키 (물론 기본 키)에 항상 인덱스가 있어야합니다. 그렇지 않으면 행 잠금 대신 테이블 잠금이 발생할 수 있습니다. 테이블 잠금이 발생하면 잠금 경합이 높아지고 교착 상태가 발생할 확률이 높아집니다.

정확하게 무엇이 발생하는지 확실하지 않지만 도움이 될 수 있습니다.

+0

-1; MySQL은 두개의 컬럼 사이에 외래 키를 생성 할 수 있도록하지 않는다. 외래 키의 인덱스가 누락 되어도 아무 것도 설명 할 수 없다. –