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


10

트래픽이 많은 웹 사이트가 있는데 매 시간마다 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입니다. 이 문제 해결을 시작하기 위해 어떤 시작 구성 설정 및 접근 방법을 권장합니까?

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

감사


프로덕션을위한 기본 my.cnf로 시작하고 있습니까? 남자, 당신은 그것을 더 최적화해야합니다. 내 대답에 더 자세히 설명하겠습니다. :-)

답변:


11

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

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

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

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

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

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


알아 둘만 한! show status 명령에서 잠금 및 관련 쿼리 및 테이블에 대한 정보를 볼 수 있습니다. 이것이 내 코드에 있다고 가정하면 status 명령에서이 정보를 사용하여 문제를 디버깅하기 시작하려면 어떻게해야합니까? PHP PDO 쿼리는 연결, 준비, 실행, 반복 등 매우 간단합니다. 도움이된다면 코드 나 상태 메시지를 게시하게되어 기쁩니다.
user658182

@ user658182 교착 상태를 처리하는 방법에 대한 stackoverflow 에서이 게시물을 확인하십시오 : 잠금을 시도 할 때 mysql 교착 상태를 피하는 방법
Valor

1
@ max-vernon 구문 편집에 감사드립니다. 분명히 영어는 모국어가 아닙니다 :-).
Valor

1
-e "SHOW ENGINE INNODB STATUS"
글리프

8

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

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 오류 로그의 모든 교착 상태에 대한 정보를 수집 할 수 있습니다 .

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.