8.10.1 내부 잠금 방법
이 섹션에서는 내부 잠금 장치, 즉 여러 세션에서 테이블 내용의 충돌을 관리하기 위해 MySQL 서버 자체 내에서 실행되는 잠금에 대해 설명합니다. 이 유형의 잠금은 완전히 서버에서 실행되는 다른 프로그램은 참여하지 않기 때문에 내부입니다. 다른 프로그램에 의해 MySQL 파일에 대해 실행되는 잠금 내용은 섹션 8.10.5 "외부 잠금" 을 참조하십시오.
행 수준 잠금
MySQL은 InnoDB
테이블에 행 수준 잠금 을 사용하여 여러 세션 동시 쓰기 액세스를 지원하고이를 여러 사용자 고급 병렬 처리 및 OLTP 애플리케이션에 적합합니다.
단일 InnoDB
테이블에 여러 개의 동시 쓰기 작업을 수행 할 때의 교착 상태 를 피하려면, 트랜잭션 뒤로 DML 문이있는 경우에도 변경이 예상되는 행의 그룹에 대해 SELECT ... FOR UPDATE
문을 실행하여 트랜잭션의 시작시에 필요한 잠금을 획득합니다. 트랜잭션에서 여러 테이블을 변경하거나 잠그는 경우 각 트랜잭션 내에서 해당 문을 같은 순서로 발행합니다. InnoDB
는 자동으로 교착 상태 상황을 감지 하고 영향을주는 하나의 트랜잭션을 롤백하기 위해 교착 상태는 심각한 오류를 나타내는 것보다 성능에 영향을줍니다.
행 수준 잠금의 장점 :
다른 세션이 다른 행에 액세스 할 경우 잠금 경합이 줄어 듭니다.
롤 변경이 적습니다.
하나의 행을 장시간 잠글 수 있습니다.
테이블 수준 잠금
MySQL은 MyISAM
, MEMORY
및 MERGE
테이블에 테이블 수준 잠금 을 사용하여 한 번에 하나의 세션이 그 테이블을 업데이트 할 수 있도록 그들을 읽기 전용, 읽기가 대부분 또는 단일 사용자 응용 프로그램에 적합합니다.
이러한 스토리지 엔진은 항상 쿼리의 처음 한 번만 필요한 모든 잠금을 요청하고 항상 동일한 순서로 테이블을 잠금하여 교착 상태 를 방지합니다. 이 트레이드 오프는이 전략에서는 병렬 가능성이 낮아진다 것입니다. 테이블을 변경하고자하는 다른 세션은 현재 DML 문이 끝날 때까지 대기해야합니다.
MySQL은 테이블 기입 락을 다음과 같이 허용합니다.
테이블에 락이 없으면 그것을 쓰기 잠급니다.
그렇지 않으면, 쓰기 잠금 큐에 잠금 요청을 켭니다.
MySQL은 테이블 읽기 잠금을 다음과 같이 허용합니다.
테이블에 쓰기 잠금이없는 경우, 그것을 읽기 잠급니다.
그렇지 않은 경우 읽기 잠금 큐에 잠금 요청을 켭니다.
테이블의 갱신은 테이블 검색보다 높은 우선 순위가 부여됩니다. 따라서 잠금이 해제되면 잠금은 쓰기 잠금 큐의 요청에 사용할 수 다음 읽기 잠금 대기열의 요청에 사용할 수 있습니다. 이렇게하면 테이블에 무거운 SELECT
활동이있는 경우에도 테이블에 대한 업데이트가 "부족"하는 것은 아닙니다. 그러나 테이블에 많은 업데이트가있을 경우 SELECT
문은 업데이트가 없어 질 때까지 기다립니다.
읽기와 쓰기의 우선 순위를 변경하는 방법은 섹션 8.10.2 "테이블 잠금 문제" 를 참조하십시오.
Table_locks_immediate
및 Table_locks_waited
상태 변수를 확인하여 시스템 테이블 잠금 경합을 분석 할 수 있습니다. 이 테이블 잠금 요청이 즉시 허용 된 횟수와 대기해야하는 횟수를 나타냅니다.
mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited | 15324 |
+-----------------------+---------+
MyISAM
스토리지 엔진은 특정 테이블의 리더와 라이터 간의 충돌을 줄이기 위해 동시 삽입을 지원하고 있습니다. MyISAM
테이블에서 데이터 파일의 중간에 빈 블록이없는 경우, 행은 항상 데이터 파일의 끝에 삽입됩니다. 이 경우 잠금없이 MyISAM
테이블에 동시 INSERT
및 SELECT
문을 자유롭게 조합 할 수 있습니다. 즉, 다른 클라이언트가 MyISAM
테이블에서 읽 자마자, 거기에 행을 삽입 할 수 있습니다. 테이블의 중간에 행이 삭제되거나 업데이트되면 틈새가 발생합니다. 틈새가있는 경우, 동시 삽입은 해제되지만 모든 틈새가 새로운 데이터로 채워진 경우 자동으로 다시 활성화됩니다. 이 동작은 concurrent_insert
시스템 변수로 변경합니다. 섹션 8.10.3 "동시 삽입" 을 참조하십시오.
LOCK TABLES
에서 명시 적으로 테이블 락을 획득하는 경우 READ
잠금 대신 READ LOCAL
잠금을 요청하고 테이블을 잠그고있는 동안 다른 세션이 동시 삽입을 수행 할 수 있도록 할 수 있습니다.
동시 삽입이 가능하지 않은 경우 테이블 real_table
에 많은 INSERT
및 SELECT
작업을 수행하려면 임시 테이블 temp_table
에 행을 삽입하고 정기적으로 임시 테이블에서 행에서 실제 테이블을 업데이트합니다 . 이것은 다음의 코드를 실행할 수 있습니다.
mysql>LOCK TABLES real_table WRITE, temp_table WRITE;
mysql>INSERT INTO real_table SELECT * FROM temp_table;
mysql>DELETE FROM temp_table;
mysql>UNLOCK TABLES;
테이블 레벨 잠금의 장점 :
필요한 메모리가 비교적 적습니다.
단일 잠금 만 필요하기 때문에 테이블의 대부분에 대해서 사용하는 경우 빠릅니다.
데이터의 대부분에 대해서
GROUP BY
작업을 자주 수행하거나 전체 테이블을 자주 스캔해야하는 경우 빠릅니다.
일반적으로 테이블 잠금은 다음의 경우에 적합합니다.
테이블에 대한 대부분의 명령문이 읽기입니다.
테이블에 대한 문이 읽기와 쓰기의 조합이며, 그 중 쓰기는 하나의 키 읽기에서 인출 할 수있는 단일 행에 대한 업데이트 또는 삭제합니다.
UPDATE
tbl_name
SETcolumn
=value
WHEREunique_key_col
=key_value
; DELETE FROMtbl_name
WHEREunique_key_col
=key_value
;동시
INSERT
문과 극소수의UPDATE
또는DELETE
문과 결합 된SELECT
.라이터를 사용하지 않는 테이블 전체에 많은 스캔 또는
GROUP BY
조작.