태그 보관물: deadlock

deadlock

시간당 1000 개의 삽입을 처리하도록 MySQL Innodb를 구성하려면 어떻게해야합니까? => 1000

트래픽이 많은 웹 사이트가 있는데 매 시간마다 1000 개의 새로운 레코드가 삽입 될 수 있습니다.

이 하나의 오류는 사이트를 무너 뜨리고 있습니다.

PDOException: SQLSTATE[40001]: Serialization failure: 1213
Deadlock found when trying to get lock;
try restarting transaction: INSERT INTO {location_instance}
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4);
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] =>
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] =>
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )

MySQL이 이런 유형의로드를 처리 할 수 ​​없다면 매우 놀랐습니다. 그렇다면 제 질문은 데이터베이스 문제입니까? 이처럼 많은 트래픽을 처리 할 수 ​​있도록 MySQL을 어떻게 구성 할 수 있습니까?

웹 사이트에 추가되는 콘텐츠의 부하를 시뮬레이트하는 스크립트를 사용하여 개발 서버에 웹 사이트 사본을 설정했습니다. 16GB의 RAM으로 Ubuntu, LAMP 스택을 실행 중입니다.

분명히, 나는 데이터베이스에 대해 잘 모른다. 사실, ‘apt-get install’이 끝나면 기본 my.cnf로 시작합니다. 테이블은 모두 Innodb입니다. 이 문제 해결을 시작하기 위해 어떤 시작 구성 설정 및 접근 방법을 권장합니까?

더 많은 정보가 필요한지 알려주세요.

감사



답변

성능 병목 현상 문제가 아닌 교착 상태를 처리하고 있습니다.

시간당 수천 개의 새 레코드가있는 경우 MySQL 한계에 훨씬 못 미칩니다. MySQL은로드의 50 배 이상을 처리 할 수 ​​있습니다.

교착 상태는 응용 프로그램 코드로 인한 것이며 데이터베이스 서버의 결함이 아닙니다. 특정 상황을 제외하고 MySQL 서버 측에서 교착 상태를 수정할 수 없습니다.

InnoDBSHOW ENGINE INNODB STATUSMySQL 프롬프트에서 또는를 사용하여 자세한 교착 상태 정보를 표시 할 수 있습니다 mysql -uroot -p... -e "SHOW ENGINE INNODB STATUS".

그러나 이것은 마지막으로 발생한 교착 상태 만 표시하며 교착 상태 로그는 없습니다.

고맙게도 문제를 해결 하는 툴 pt-deadlock-logger가 있으며 폴링 InnoDB상태를 관리 하고 새로운 교착 상태로 새로 고치기 전에 모든 상세 교착 상태 정보를 저장합니다.


답변

이것은 트랜잭션을 실행하는 코드의 한 부분만큼 간단 할 수 있습니다.

insert into t1...
insert into t2...
commit;

코드의 다른 부분은 동일한 테이블을 다른 순서로 수정합니다.

delete from t2 where...
delete from t1 where...
commit;

두 트랜잭션이 동시에 실행되면 경쟁 조건이 발생할 수 있습니다. 첫 번째 트랜잭션은 t2두 번째 트랜잭션에 의해 잠겨 있기 때문에 수정할 수 없습니다 . 두 번째 트랜잭션은 t1첫 번째 트랜잭션에 의해 잠겨 있기 때문에 유사하게 차단 됩니다. MySQL은 하나의 트랜잭션을 INSERT / UPDATE / DELETE가 실패하는 “피해자”로 선택합니다. 애플리케이션은 해당 오류를 포착하고 명령문을 재 시도해야합니다. 일시 정지 후 다른 트랜잭션이 완료 될 시간이 있습니다. 용량 제한과는 아무런 관련이 없으며 코드 배열 방식으로 악화 될 수있는 불행한 타이밍입니다. 트랜잭션 # 2의 DELETE 또는 트랜잭션 # 1의 INSERT를 전환하면 충돌이 없습니다. 각 트랜잭션은 필요한 테이블에 대한 액세스를 기다립니다.

MySQL 5.6에서는 innodb_print_all_deadlocks 옵션을 활성화하여 MySQL 오류 로그의 모든 교착 상태에 대한 정보를 수집 할 수 있습니다 .

[면책 조항 : 저는 오라클 직원입니다. 위의 내용은 공식적인 진술이 아닌 개인적인 견해입니다.]


답변