DBMS 2
DA, SQL, DB보안 등 실무자를 위한 위한 DB기술 바이블!
MySQL은 MyISAM 및 MEMORY 테이블에 대해서는 테이블-레벨 잠금을 사용하며, BDB 테이블에 대해서는 페이지-레벨 잠금을, 그리고 InnoDB 테이블에 대해서는 열-레벨 잠금을 사용한다. 대부분의 경우에, 여러분은 특정 어플리케이션에 대해서 가장 최선의 잠금 방식을 경험적으로 선택할 수 있으나, 주어진 잠금 방식이 다른 타입에 비해 우수하다고 단정짓는 것은 매우 어렵다. 사용하는 어플리케이션에 따라서 서로 다른 잠금 방식을 사용할 수 있다. 스토리지 엔진을 열 레벨 잠금과 함께 사용하기 위해서는, 여러분이 사용하는 어플리케이션 및 그것이 사용하는 선택 및 업데이트에는 어떤 것들이 있는지를 잘 살펴 보아야 한다. 예를 들면, 대부분의 웹 어플리케이션들은 많은 선택은 하지만, 상대적으로 적은 삭제를 하며, 업데이트는 주로 키 값을 기반으로 실행하고, 열 삽입은 몇몇 특정 테이블에 대해서만 실행을 한다. MySQL의 MyISAM 설정은 이런 용도에 잘 들어 맞게 튜닝된 것이다. MySQL에서의 테이블 잠금은 테이블 레벨 잠금을 사용하는 스토리지 엔진에 대해서 데드락-프리 (deadlock-free)가 된다. 쿼리를 시작할 때 항상 모든 필요한 잠금을 한번에 요청하고 항상 동일한 순서로 테이블을 잠금으로써 데드락을 없앨 수가 있다. WRITE 잠금을 위해 MySQL이 사용하는 테이블 잠금 방식은 아래와 같다: READ 잠금 동작을 위한 테이블 잠금 방식은 다음과 같다: 잠금이 해제가 되면, 그 잠금은 쓰기 잠금 큐에 있는 쓰레드가 사용할 수 있게 되며 그 다음에는 읽기 잠금 큐에 있는 쓰레드가 사용할 수 있게 된다. 이것은 여러분이 테이블에 대해서 많은 업데이트를 했다면, SELECT 명령문은 더 이상의 업데이트가 생기기 않을 때까지 기다리게 된다는 것을 의미하는 것이다. 여러분은 Table_locks_waited 및 Table_locks_immediate 상태 변수를 검사함으로써 시스템 상의 테이블 잠금 경쟁을 분석할 수가 있다: 만일 MyISAM 테이블이 중간에 어떠한 자유 블럭 (free block)도 가지고 있지 않다면, 열 삽입은 항상 데이터 파일의 맨 마지막에 이루어진다. 이와 같은 경우에는, 자유롭게 INSERT 및 SELECT 명령문을 잠금 없이 MyISAM 테이블 용으로 동시에 사용할 수 있다. 즉, 여러분은 다른 클라이언트가 MyISAM 테이블을 읽는 동안에도 이 테이블 안에 열을 삽입할 수가 있다는 것이다. 만일 동시 삽입이 불가능한 상태에서 많은 수의 INSERT 및 SELECT 동작을 한 테이블에서 실행하고자 한다면, 여러분은 임시 테이블 temp_table에 열을 삽입하고 난 후에 이 임시 파일에 있는 열을 가지고 실제 테이블을 업데이트 하면 된다. 아래의 코드를 가지고 실행하면 된다: InnoDB는 열 레벨의 잠금을 사용하고 BDB는 페이지 레벨의 잠금을 사용한다. 이 두 가지 스토리지 엔진의 경우, 데드락이 발생할 가능성이 있는데, 그 이유는 이 엔진들은 트랜젝션이 시작되는 시점이 아닌SQL 명령문을 실행하는 동안 자동으로 잠금을 얻어내기 때문이다. 열 레벨 잠금의 장점으로는 다음과 같은 것이 있다: 반면에, 열 잠금의 단점은 다음과 같다: 아래의 경우에는, 테이블 잠금이 나머지 두 개의 잠금 방식보다 훨씬 성능이 좋게 된다: 보다 높은 레벨의 잠금을 사용하면, 서로 다른 형태의 잠금을 지원함으로써 어플리케이션을 보다 쉽게 튜닝할 수가 있는데, 그 이유는 잠금으로 인한 오버 헤드가 낮은 레벨 (lower-level) 잠금보다 덜 생기기 때문이다. 매우 빠른 잠금을 위해서 MySQL은 InnoDB 및 BDB를 제외한 모든 스토리지 엔진에 대해서는 테이블 잠금을 사용한다. InnoDB 및 BDB 테이블의 경우에는LOCK TABLES를 가지고 명확하게 테이블을 잠그는 경우에만 테이블 잠금을 사용한다. 이러한 스토리지 엔진에 대해서는 LOCK TABLES를 사용하지 말 것을 권장하는데, 그 이유는 페이지 트랜젝션 분리 (isolation)를 위해서 InnoDB는 자동 열 레벨 잠금을 그리고 BDB 는 자동 레벨 잠금을 사용하기 때문이다. 대형 테이블의 경우, 대부분의 어플리케이션에 대해서는 열 잠금 보다는 테이블 잠금이 보다 좋기는 하지만, 아래와 같이 몇 가지의 예외적인 경우가 존재한다: 테이블 잠금은 아래와 같은 시나리오 아래에서도 단점을 가지게 된다: 아래의 사항들은 테이블 잠금에 의해 야기되는 경쟁 상황을 피하거나 또는 절감 시킬 수 있는 여러 가지 방법을 설명해 주는 것들이다: 아래의 내용은 MySQL에서 테이블 잠금에 대해 고려해야 할 몇 가지 팁 들을 나열한 것이다: MyISAM 테이블의 경우, 테이블 중간에 삭제된 열이 없다면, SELECT 명령문이 구동 중에 있는 동안에도 열을 추가하기 위한 동시 삽입을 사용할 수가 있다. 동시 삽입을 사용할 수 있는 경우에는, INSERT 명령문에 대해서 DELAYED 모디파이어 (modifier)를 사용할 필요가 거의 없다. 여러분이 바이너리 로그를 사용하고 있다면, 동시 삽입은 CREATE ... SELECT 또는 INSERT ... SELECT 명령문에 대해서는 정상 삽입 (normal insert)으로 변환된다. 이것은 백업 동작이 진행되는 동안 로그를 적용 시킴으로써 여러분이 테이블의 정확한 복사본을 재 생성할 수 있게 끔 해 준다. 만일 여러분이 동시 삽입 조건을 만족 시키는MyISAM 테이블과 함께CONCURRENT를 지정한다면 (즉, 테이블 중간에 아무런 프리 블럭 (free block)도 없는 경우), LOAD DATA INFILE를 사용해서 LOAD DATA가 실행되는 동안에 다른 쓰레드가 테이블에서 데이터를 추출할 수 있도록 해 준다. 이 옵션을 사용하면 LOAD DATA의 성능에 다소 영향을 줄 수가 있는데, 비록 다른 쓰레드가 동시에 테이블을 사용하는 경우에도 가능하게 된다.잠금 이슈
잠금 이슈
잠금 방법
mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited | 15324 |
+-----------------------+---------+
mysql> LOCK TABLES real_table WRITE, insert_table WRITE;
mysql> INSERT INTO real_table SELECT * FROM insert_table;
mysql> TRUNCATE TABLE insert_table;
mysql> UNLOCK TABLES;
UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;
DELETE FROM tbl_name WHERE unique_key_col=key_value;
Table 잠금 이슈
동시 삽입