쿼리가 테이블 수준 잠금을 기다리는 것을 방지하는 방법 수행되는 업데이트

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

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

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

1. 테이블에서이 업데이트 가 테이블 수준 잠금을 기다리는 article_comments테이블의 select 문에 영향을주는 이유를 이해하지 못합니다 article. processlist에서 거의 모든 대기 쿼리가이 테이블에있었습니다. 업데이트 / 삽입이 선택보다 선호된다는 사실에 대해 읽었으며 이러한 문제가 발생할 수 있지만 주석이 활성화 될 때 기사 테이블 자체는 업데이트되지 않으므로 선택이 대기하지 않아야합니다. 내가 그것을 이해하지 못했습니까?

2.이 동작을 방지하거나 최소한 더 나은 균형을 얻기 위해 InnoDB로 변경하는 것 외에 다른 것이 있습니까? 데이터베이스를 새 서버로 옮기기 전에이 문제가 나타나지 않았다는 사실에 매우 짜증이납니다. 구성이 잘못되었지만 식별 방법을 모르겠습니다.



답변

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)


답변

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

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은 “테이블 수준”잠금을 사용합니다. 동시에 같은 테이블에서 읽기와 쓰기를 수행 할 수 없습니다. 조잡하지만 효과적입니다.