2012-07-04 4 views
10

동일한 테이블에서 동시 클라이언트를 처리하는 동안 MySQL에서 발견 된 교착 상태를 이해하려고합니다.InnoDB 테이블에서 MySQL 데드락을 이해하려고 시도했습니다.

------------------------ 
LATEST DETECTED DEADLOCK 
------------------------ 
120704 16:17:51 
*** (1) TRANSACTION: 
TRANSACTION 0 3547576, ACTIVE 0 sec, process no 10886, OS thread id 140547111458560 inserting 
mysql tables in use 1, locked 1 
LOCK WAIT 2 lock struct(s), heap size 368, 1 row lock(s), undo log entries 1 
MySQL thread id 41941, query id 1725666 localhost testsuite update 
insert into `INode` (`status`,`_type`,`group`,`ctime`,`parent`,`shared`,`basename`,`_rowid`,`displayname`,`user`,`content_type`,`mtime`,`position`,`atime`,`size`) values ('Published','Group','12','2012-07-04 16:17:48.996869','2',null,'1','12','1','3','application/x-empty','2012-07-04 16:17:48.996896','1','2012-07-04 16:17:48.996914',null) 
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547576 lock mode S waiting 
Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 80000002; asc  ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc  ;; 

*** (2) TRANSACTION: 
TRANSACTION 0 3547575, ACTIVE 0 sec, process no 10886, OS thread id 140547107845888 inserting, thread declared inside InnoDB 493 
mysql tables in use 1, locked 1 
13 lock struct(s), heap size 3024, 17 row lock(s), undo log entries 21 
MySQL thread id 41940, query id 1725808 localhost testsuite update 
replace into `INode` (`status`,`_type`,`position`,`group`,`ctime`,`parent`,`basename`,`_rowid`,`displayname`,`user`,`content_type`,`mtime`,`shared`,`atime`,`size`) values ('Published','Group','0','2','2012-07-04 16:17:49','1','groups','2','admin','3','application/x-empty','2012-07-04 16:17:49',null,'2012-07-04 16:17:49',null),('Published','Group','1','11','2012-07-04 16:17:51.064074','2','1','11','1','3','inode/directory','2012-07-04 16:17:51.064074',null,'2012-07-04 16:17:51.064074',null) 
*** (2) HOLDS THE LOCK(S): 
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547575 lock_mode X locks rec but not gap 
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 
0: len 4; hex 80000001; asc  ;; 1: len 6; hex 67726f757073; asc groups;; 2: len 4; hex 80000002; asc  ;; 

Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 80000002; asc  ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc  ;; 

*** (2) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 5554 n bits 80 index `INodeparent_basename` of table `testsuite`.`INode` trx id 0 3547575 lock_mode X waiting 
Record lock, heap no 12 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 
0: len 4; hex 80000002; asc  ;; 1: len 1; hex 31; asc 1;; 2: len 4; hex 8000000b; asc  ;; 

*** WE ROLL BACK TRANSACTION (1) 

내가이 로그에서 이해하면 트랜잭션이 (1) 테이블 testsuite의 인덱스 INodeparent_basename에 공유 잠금을 얻기 위해 대기하고 있다는 것입니다 : 이것은 "SHOW 이노 상태"명령의 흥미로운 부분이다. INode. 이제 트랜잭션 (2)에는 이와 동일한 바로 인덱스에 대한 배타적 잠금이 있습니다. 그러나 이상한 것은 트랜잭션 (2)도 주어진 테이블에 대한 X 잠금을 기다리고 있다는 것입니다. 왜 그런가요? 트랜잭션 (2)에 이미 잠금이있는 경우, 잠금을 기다리는 이유는 무엇입니까?

(일반적으로, 나는 정확히 status 명령의 출력을 읽는 방법을 설명하고 모든 문서 발견하지 않았습니다 - 누군가가 너무 나에게 그 지적 수 있다면 재미있을 것이다)이 경우

+0

답변을 찾으셨습니까? 나는 같은 문제가있다. –

+0

아니요,이 문제에 대한 답을 찾을 수 없습니다. 몇 시간 동안 노력한 후에 MySQL을 통해 발견 된 교착 상태를 피하기 위해 프로세스를 다르게 코딩하고 프로그래밍 방식으로 데이터베이스 액세스를 직렬화해야했습니다. 성능면에서는 좋지는 않지만 다른 가능성은 없습니다. – RedGlow

+0

상태 명령 출력을 번역하는 방법에 대해, 당신 (또는 이에 대한 도움이 필요한 다른 사람)은이 블로그에서 https://www.percona.com/blog/2014/10/28/how- to-deal-with-mysql-deadlocks/ – CodeBurner

답변

1

을, 트랜잭션 2가 이전 명령문에 대한 공유 잠금을 획득했습니다. (* (2) 잠금 (S) :)

그런 다음 트랜잭션 1이 같은 행에 대한 배타적 잠금을 획득하려고 시도하고 제거 할 공유 잠금.

그런 다음 다른 명령문에서 트랜잭션 2가 동일한 행에서 배타적 잠금을 획득하려고 시도했습니다. 교착 상태가 발생했습니다.

+0

아니요, (2)는 이미 독점적 인 잠금을 보유하고 있습니다. (1) 너는 공유 된 잠금 장치를 얻으려고 노력하고있다. –

-1

도움이 될지 모르겠지만 잠금을 유발하는 작업 순서는 고려해야 할 사항 중 하나입니다. 없이

표 2 표 1 (단지 예)

을하고 같은 표 1 표 2

다른에서

으로 응용 프로그램의 한 위치에 당신이 잠금을 만드는 것으로 보인다 실제 코드를 보면서 나는 이와 같은 것들을 조사하고 작업/업데이트/삽입 순서가 동일하므로 이들 모두가 다음과 같이 작동하도록 권장한다.

테이블 1에서 삽입/업데이트 다음 테이블 삽입/업데이트 2

이렇게하면 첫 번째 잠금이 항상 먼저 테이블 1에서 시도됩니다. 그럴 수 없다면 테이블까지 시도하지 않습니다. 1이 출시되었습니다.

그런 다음 표 2에 변경 사항을 적용하고 거래를 완료하십시오. 그러면 테이블 2와 1이 모두 해제되면 테이블 1에서 해제 대기중인 다음 트랜잭션이 계속 진행될 수 있습니다.