쿼리가 테이블 수준 잠금을 기다리는 것을 방지하는 방법


10

고객의 데이터베이스를 추가 서버로 이동 한 후 문제가 발생했습니다. 이는 사이트 성능에 긍정적 인 영향을 미쳤지 만 MyISAM에서 테이블 잠금에 문제가 있습니다. (MyISAM 대신 InnoDB를 사용한다고 들었지만 가까운 시일 내에 엔진을 변경할 수는 없습니다).
중재자가 기사 사이트에 대한 주석을 활성화 할 때 수행되는 업데이트 쿼리를 발견 할 수 있습니다. 이것은 과정이다 :

  • 업데이트 쿼리가 처리됩니다 SET status = 1 WHERE id = 5(인덱스가 설정 됨)
  • 페이지의 캐시 된 파일이 삭제됩니다

이 시점에서 전체 페이지가 느려집니다. 데이터베이스 자체가 몇 분 동안 사용 중입니다. 프로세스 목록을 몇 번 가져 왔으며 테이블 선택 잠금을 기다리는 상태에있는 다른 선택 쿼리의 약 60 개 항목을 보았습니다 .

1. 테이블에서이 업데이트 가 테이블 수준 잠금을 기다리는 article_comments테이블의 select 문에 영향을주는 이유를 이해하지 못합니다 article. processlist에서 거의 모든 대기 쿼리가이 테이블에있었습니다. 업데이트 / 삽입이 선택보다 선호된다는 사실에 대해 읽었으며 이러한 문제가 발생할 수 있지만 주석이 활성화 될 때 기사 테이블 자체는 업데이트되지 않으므로 선택이 대기하지 않아야합니다. 내가 그것을 이해하지 못했습니까?
2.이 동작을 방지하거나 최소한 더 나은 균형을 얻기 위해 InnoDB로 변경하는 것 외에 다른 것이 있습니까? 데이터베이스를 새 서버로 옮기기 전에이 문제가 나타나지 않았다는 사실에 매우 짜증이납니다. 구성이 잘못되었지만 식별 방법을 모르겠습니다.


1
일반 로깅을 사용 가능하게하고이 테이블 사이에서 JOIN 문을 감시하십시오. 선택하면 암시 적 읽기 잠금이 생성됩니다. MYISAM은 ROW LEVEL 잠금을 지원하지 않으므로 테이블 레벨에서 잠금됩니다. 이 잠금이 이전 서버에서 발생했지만 아무도보고 있지 않은 경우 일 수 있습니다. my.cnf 라인을 호스트 사이의 라인과 비교하고 특히 key_buffer가 올바르게 조정되었는지 확인하십시오.
randomx

이전 서버에서 몇 가지 다른 성능 문제가 있었으며 종종 프로세스 목록을 보았습니다. 주로 수면 프로세스가 많이 있었지만 대기중인 프로세스는 눈치 채지 못했습니다 (일반적으로이 새 서버에서 처음으로이 정보를 보았습니다). 동료는 이전 my.cnf를 복사하고 값을 기존의 새 하드웨어로 조정했지만 항목이 많지 않았습니다. 또한 "SHOW VARIABLES"의 출력을 비교했지만 실제로 무엇을 볼지 몰랐습니다. 내일 키 버퍼를 다시 확인해 드리겠습니다.
32bitfloat

최근 비슷한 문제가있었습니다. 처음에 우리 key_buffer_size는로 설정되었습니다 1GB. 10GB문제 를 줄이려면 늘리십시오.
Haluk

@Rick James 감사합니다. 당신은 오늘 날 많은 문제를 저장했습니다. 아마존 또는 다른 곳에 위시리스트가 있습니까? :) query_cache_limit를 1024로 설정했습니다. 지금은 잠금 문제가 없습니다. 처음에는 mysql 클라이언트에서 변수로 수행했습니다. 전역 query_cache_limit = 1024로 설정; 이제 my.cnf에 씁니다. 이 솔루션을 사용하면 스트레스없이 innodb 마이그레이션을 계획 할 수있게되었습니다. 감사합니다.

답변:


8

MyISAM Storage Engine은 모든 DML (INSERT, UPDATE, DELETE)에 대해 전체 테이블 잠금을 수행하는 것으로 격렬하게 악명이 높습니다. InnoDB는 장기적으로 그 문제를 해결할 것입니다.

MyISAM vs InnoDB 사용의 장단점에 대해 썼습니다

현재 질문과 관련하여 가능한 시나리오는 다음과 같습니다.

  • article그리고 article_commentsMyISAM 테이블입니다.
  • article_comments하나 이상의 색인을 status열로 사용
  • 에 대한 색인 페이지 업데이트 article_comments가 MyISAM 키 버퍼 ( key_buffer_size로 크기 조정)에 캐시되어 MyISAM 키 버퍼에서 오래된 색인 페이지가 발생 함
  • article와 사이에 JOIN을 수행하는 SELECT 쿼리가 있습니다.article_comments

내가 제안한 시나리오에서 article테이블 에 대한 SELECT는 article_commentsDML이 없어 질 때까지 기다려야하므로 쓰기를 허용 하지 않을 수 있습니다 (이 경우에는 UPDATE)


귀하의 답변 (및 링크)에 감사드립니다. 시나리오는 실제입니다. 나는 대부분의 선택된 기사가 실제로 주석 테이블에 참여한다는 것을 알지 못했습니다 (즉, phpmyadmin의 processlist에서 불완전한 진술을 보았습니다). 여러 대기 쿼리를 방지하기위한 단기 솔루션을 알고 있습니까? 특정 문장에서 "UPDATE LOW_PRIORITY"로 이미 시도했지만 눈에 띄게 변경되지 않았습니다. 우리는 앞으로 innodb로 바뀔 것입니다. 그러나 현재 개선을위한 방법이 있는지 궁금합니다.
32bitfloat

최상의 솔루션 : 테이블을 InnoDB로 변환하십시오. MyISAM을 InnoDB로 변환하는 방법 은 내 게시물 dba.stackexchange.com/a/9422/877 을 참조하십시오
RolandoMySQLDBA

7

이 시점에서 전체 페이지가 느려집니다. 데이터베이스 자체가 몇 분 동안 사용 중입니다.

Query_cache가 큰 것 같은 냄새가나요?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

쓰기가 많은 프로덕션 시스템의 경우 query_cache를 끌 수도 있습니다.

주어진 테이블에 대한 query_cache의 모든 항목은 해당 테이블에 대한 쓰기가 발생 하면 제거됩니다 . QC가 클수록이 작업은 느려집니다.

MyISAM은 "테이블 수준"잠금을 사용합니다. 동시에 같은 테이블에서 읽기와 쓰기를 수행 할 수 없습니다. 조잡하지만 효과적입니다.


1
그래 약 64M 캐시 크기가 있습니다. 그러나 나에게 새로운 정보를 주셔서 감사하지만 이전 서버에서 테이블 잠금을 인식하지 못하는 동일한 값을 가졌습니다. 우리는 이미 InnoDB로 옮기기 시작했지만이 사실은 미스터리로 남아 있습니다.
32bitfloat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.