14.2.4 일관성 nonlock 읽기
일관성 독해 는 InnoDB
가 멀티 버전을 사용하여 특정 시점의 데이터베이스 스냅 샷을 쿼리에 제공하는 것을 의미합니다. 쿼리는 그 시점 이전에 커밋 된 트랜잭션에 의한 변경 만 표시되고 그 시점보다 이후의 트랜잭션 또는 커밋되지 않은 트랜잭션에 의한 변경은 나타나지 않습니다. 이 규칙의 예외로서 동일한 트랜잭션 내의 이전 명령문에 의한 변경은 쿼리에 표시됩니다. 이 예외는 다음과 같은 문제가 발생합니다. 테이블의 일부 행을 업데이트하면 업데이트 된 행의 최신 버전이 SELECT
에 표시되지만 하나의 행의 이전 버전도 표시 될 수 있습니다. 다른 세션에서 같은 테이블이 동시에 업데이트되는 경우 그 이상 데이터베이스에 존재하지 않는 상태에서 테이블이 나타날 수 있음을 의미합니다.
트랜잭션 격리 수준 이 REPEATABLE READ
(기본 수준) 인 경우는 동일한 트랜잭션 내의 모든 일관성 독해 트랜잭션의 첫 번째 이러한 읽기에 설립 된 스냅 샷을 읽습니다. 현재 트랜잭션을 커밋 한 후에 새로운 쿼리를 실행하면 쿼리의 새로운 스냅 샷을 얻을 수 있습니다.
격리 수준이 READ COMMITTED
의 경우에는 트랜잭션의 각 일관성 독해 자신의 새로운 스냅 샷이 설정되어 읽혀집니다.
일관성 독해는 InnoDB
가 READ COMMITTED
및 REPEATABLE READ
격리 수준에서 SELECT
문을 처리 할 때의 기본 모드입니다. 일관성 독해는 액세스되는 테이블에 잠금이 설정되지 않으므로 다른 세션도 그 테이블에서 일관성 읽기가 실행될 때 동시에 그 테이블을 자유롭게 변경할 수 있습니다.
기본 REPEATABLE READ
격리 수준에서 실행하고 있다고 가정합니다. 일관성 독해 (즉, 일반적인 SELECT
문)을 발행하면 InnoDB
는 쿼리가 데이터베이스를 참조 할 때 기준이되는 타임 포인트를 트랜잭션에 부여합니다. 타임 포인트가 할당 된 후에 다른 트랜잭션이 행을 삭제하고 커밋하면 해당 행이 삭제 된 것으로 표시되지 않습니다. 삽입 및 업데이트도 마찬가지로 처리됩니다.
데이터베이스 상태의 스냅 샷은 트랜잭션의 SELECT
문에 적용되지만, DML 문에 반드시 적용되는 것은 아닙니다. 일부 행을 삽입 또는 수정하고 해당 트랜잭션을 커밋하는 경우 해당 세션에서 쿼리가 실행될 가능성이없는 경우에도 다른 병렬 실행 REPEATABLE READ
트랜잭션에서 발행 된 DELETE
또는 UPDATE
문 에 의해 위탁 된 막 행이 영향을받을 수 있습니다. 트랜잭션이 다른 트랜잭션에서 커밋 된 행이 갱신 또는 삭제되면 이러한 변경 내용을 현재 트랜잭션에 표시 할 수 있습니다. 예를 들어, 다음과 같은 상황이 발생할 수 있습니다.
SELECT COUNT (c1) FROM t1 WHERE c1 = 'xyz'; - Returns 0 : no rows match. DELETE FROM t1 WHERE c1 = 'xyz'; - Deletes several rows recently committed by other transaction. SELECT COUNT (c2) FROM t1 WHERE c2 = 'abc'; - Returns 0 : no rows match. UPDATE t1 SET c2 = 'cba'WHERE c2 = 'abc'; - Affects 10 rows : another txn just committed 10 rows with 'abc'values. SELECT COUNT (c2) FROM t1 WHERE c2 = 'cba'; - Returns 10 : this txn can now see the rows it just updated.
트랜잭션을 커밋하고 다른 SELECT
또는 START TRANSACTION WITH CONSISTENT SNAPSHOT
을 실행하면 타임 포인트를 진행할 수 있습니다.
이것은 다중 버전 병렬 처리 제어라고합니다.
다음 예제에서는 세션 B가 삽입 커밋 세션 A도 마찬가지로 커밋 한 경우에만 B에 의해 삽입 된 행이 A로 표시됩니다. 그러면 타임 포인트가 B의 커밋보다 먼저 진행합니다.
Session A Session B SET autocommit=0; SET autocommit=0; time | SELECT * FROM t; | empty set | INSERT INTO t VALUES (1, 2); | v SELECT * FROM t; empty set COMMIT; SELECT * FROM t; empty set COMMIT; SELECT * FROM t; --------------------- | 1 | 2 | --------------------- 1 row in set
데이터베이스의 "최신"상태를 확인하려면 READ COMMITTED
격리 수준과 잠금 읽기 중 하나를 사용합니다.
SELECT * FROM t LOCK IN SHARE MODE;
격리 수준이 READ COMMITTED
의 경우에는 트랜잭션의 각 일관성 독해 자신의 새로운 스냅 샷이 설정되어 읽혀집니다. LOCK IN SHARE MODE
의 경우 대신 잠금 읽기가 발생합니다. SELECT
는 최신 행이 포함 된 트랜잭션이 끝날 때까지 블록됩니다 ( 섹션 14.2.5 "잠금 읽기 (SELECT ... FOR UPDATE 및 SELECT ... LOCK IN SHARE MODE)" 참조).
특정 DDL 문은 일관성 읽기가 작동하지 않습니다.
DROP TABLE
에서는 MySQL이 삭제 된 테이블을 사용하지 않아 테이블은InnoDB
에 의해 파괴되기 때문에 일관성 읽기가 작동하지 않습니다.ALTER TABLE
은 그 문에서 원본 테이블의 임시 복사본을 만들어 원래의 테이블은 임시 복사본이 구축 될 때 삭제되기 때문에 일관성 읽기가 작동하지 않습니다. 트랜잭션에 일관성 읽기를 다시 실행해도 새로운 테이블의 행은 트랜잭션의 스냅 숏 된 경우에는 존재하지 않았기 때문에 표시 할 수 없습니다. MySQL 5.6.6의 시점에서는이 경우 트랜잭션에서 "Table definition has changed, please retry transaction"라는ER_TABLE_DEF_CHANGED
오류가 반환됩니다.
FOR UPDATE
또는 LOCK IN SHARE MODE
를 지정하지 않으면 INSERT INTO ... SELECT
, UPDATE ... (SELECT)
, CREATE TABLE ... SELECT
등의 어구의 선택은 읽기 유형이 다릅니다.
기본적으로
InnoDB
는 더욱 강력한 잠금을 사용하여SELECT
부분은READ COMMITTED
처럼 작동합니다. 이 경우 동일한 트랜잭션 내에서 각 일관성 독해 자신의 새로운 스냅 샷이 설정되어 읽혀집니다.이런 경우 일관성 독해를 사용하려면
innodb_locks_unsafe_for_binlog
옵션을 사용하여 트랜잭션 격리 수준을READ UNCOMMITTED
,READ COMMITTED
또는REPEATABLE READ
(즉,SERIALIZABLE
제외한 모든)로 설정합니다. 이 경우 선택한 테이블에서 읽은 행에 잠금이 설정되지 않습니다.