2011-05-11 3 views
0

나는 종종 그 자체를 보여주는 이노 교착 상태 주위에 내 머리를 정리하려고 해요 :InnoDB CREATE ... SELECT가 독점적 인 락을 사용하는 이유는 무엇입니까?

------------------------ 
LATEST DETECTED DEADLOCK 
------------------------ 
110511 10:45:59 
*** (1) TRANSACTION: 
TRANSACTION 0 959459752, ACTIVE 0 sec, process no 24148, OS thread id 2958613424 starting index read 
mysql tables in use 16, locked 16 
LOCK WAIT 2 lock struct(s), heap size 320 
MySQL thread id 13029007, query id 85826239 localhost andrew updating 
DELETE FROM `clients_permission_assignments` WHERE permission_assignment_id = 3761 AND client_id IN (52621) 
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 1490959 n bits 864 index `unique_index` of table `test/clients_permission_assignments` trx id 0 959459752 lock_mode X waiting 
Record lock, heap no 202 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 8000cd8d; asc  ;; 1: len 4; hex 80000eb1; asc  ;; 2: len 6; hex 0000006b7d5c; asc k}\;; 

*** (2) TRANSACTION: 
TRANSACTION 0 959459751, ACTIVE 0 sec, process no 24148, OS thread id 1996331952 fetching rows, thread declared inside InnoDB 354 
mysql tables in use 16, locked 16 
20 lock struct(s), heap size 2496, undo log entries 1 
MySQL thread id 13019094, query id 85826237 localhost andrew Copying to tmp table 
CREATE TEMPORARY TABLE tmp_tests_people_cleanup_table (SELECT unit_code FROM (
       SELECT u.unit_code, COUNT(u.unit_code) AS cnt FROM staging.client_test_utilization u 
       LEFT JOIN permission_assignments pa ON pa.person_id = 
        (SELECT person_id FROM permission_assignments pa WHERE pa.id = OLD.permission_assignment_id) 
       LEFT JOIN permissions p ON pa.permission_id = p.id 
       LEFT JOIN clients_permission_assignments cpa ON cpa.permission_assignment_id = pa.id 
       LEFT JOIN clients c ON c.id = cpa.client_id 
       LEFT JOIN staging.client_test_utilization u2 ON CONCAT('C',u2.client_number) = c.number 
        AND u2.unit_code = u.unit_code 
       WHERE p.label = 'Receive Test Updates' 
        AND CONCAT('C',u.client_number) = (SELECT number from clients WHERE id = OLD.client_id) 
        AND u2.id IS NULL GROUP BY u.unit_code 
     ) tbl 
      WHERE cnt = (SELECT COUNT(*) FROM permission_assignments pa 
         LEFT JOIN permissions p ON pa.permission_id = p.id 
         LEFT JOIN clients_permission_assignments cpa ON cpa.permission_assignment_id = pa.id 
         WHERE p.label = 'Receive Test Updates' AND pa.person_id = 
          (SELECT person_id FROM permission_assignments pa WHERE pa.id = OLD.permission_assignment_id)) 
       OR (SELECT COUNT(*) FROM permission_assignments pa 
         LEFT JOIN permissions p ON pa.permission_id = p.id 
         LEFT JOIN clients_permission_assignments cpa ON cpa.permission_assignment_id = pa.id 
         WHERE p.label = 'Receive Test Updates' AND pa.person_id = 
          (SELECT person_id FROM permission_assignments pa WHERE pa.id = OLD.permission_assignment_id)) = 0) 
*** (2) HOLDS THE LOCK(S): 
RECORD LOCKS space id 0 page no 1490959 n bits 864 index `unique_index` of table `test/clients_permission_assignments` trx id 0 959459751 lock_mode X locks rec but not gap 
Record lock, heap no 202 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 8000cd8d; asc  ;; 1: len 4; hex 80000eb1; asc  ;; 2: len 6; hex 0000006b7d5c; asc k}\;; 

*** (2) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 1490959 n bits 864 index `unique_index` of table `test/clients_permission_assignments` trx id 0 959459751 lock mode S waiting 
Record lock, heap no 202 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 8000cd8d; asc  ;; 1: len 4; hex 80000eb1; asc  ;; 2: len 6; hex 0000006b7d5c; asc k}\;; 

*** WE ROLL BACK TRANSACTION (1) 

내가 시간에 알지 못했다하지만 INSERT 것 같아 ... SELECT, CREATE ... SELECT SELECT 쿼리의 모든 테이블을 잠급니다. 보시다시피 조인과 하위 쿼리가있는 테이블이 많이 있습니다. 나는 자물쇠가 공유 (S) 자물쇠 일 것이라고 생각했지만 위의 데이터에서 자물쇠 (X) 자물쇠를 보유하고있는 것으로 보인다. 나는 왜 그런지 이해하지 못한다.

아마도 누군가가 CREATE ... SELECT 쿼리에 독점 (X) 잠금이있는 이유를 알면이 교착 상태를 해결할 수 있습니다. 또는 교착 상태에 대한 도움을받을 수 있습니다.

감사합니다.

+0

어떤 격리 수준을 사용하고 있습니까? –

+0

MySQL의 기본값 (REPEATABLE READ) 인 것 같습니다. 과거에 INSERT ... SELECT 문제를 해결하기 위해'SET TRANSACTION ISOLATION LEVEL READ COMMITTED; '를 사용했습니다; 이것이 여기에서도 유용 할 것이라고 생각합니까? –

답변

0

독점 잠금이 CREATE ... SELECT 쿼리가 아니고 그 전에 쿼리가 동일한 트랜잭션에 있어야한다는 것을 발견했습니다.

나는 중요한 세부 사항을 생략했습니다. CREATE ... SELECT 쿼리는 clients_permission_assignments에서 AFTER DELETE 트리거입니다. 문제가 DELAYE 쿼리가 일부 clients_permission_assignments 레코드에 독점 잠금을 보유하고있는 것을 발견하고 각 삭제 후에 CREATE ... SELECT 쿼리는 이미 DELETE 쿼리의 배타적 잠금이있는 레코드에서 공유 잠금을 가져 오려고 시도합니다. CREATE ... SELECT 쿼리는 모든 행을 삭제하고 배타적 잠금을 해제 할 때까지 기다려야합니다. 그러나이 프로세스가 진행되는 동안 사용자는 기다림을 즐기지 않았으므로 DELETE 쿼리를 다시 시작하여 교착 상태가 발생했습니다.

감사합니다.