MySQL
MySQL LOCK TABLE
수색…
통사론
LOCK 테이블 table_name [읽기 | 쓰다]; // 테이블 잠금
UNLOCK TABLES; // 테이블 잠금 해제
비고
잠금은 동시성 문제를 해결하는 데 사용됩니다. 잠금은 트랜잭션을 실행할 때만 필요합니다. 먼저 데이터베이스에서 값을 읽은 다음 나중에 해당 값을 데이터베이스에 씁니다. 자체 포함 된 삽입, 업데이트 또는 삭제 작업에는 잠금이 필요하지 않습니다.
사용할 수있는 두 종류의 잠금 장치가 있습니다.
읽기 잠금 - 사용자가 테이블에서만 읽는 경우.
쓰기 잠금 - 사용자가 테이블을 읽고 쓰는 중일 때.
사용자가 테이블에 WRITE LOCK
을 유지하면 다른 사용자가 해당 테이블을 읽거나 쓸 수 없습니다. 사용자가 테이블에 READ LOCK
을 유지하면 다른 사용자도 READ LOCK
읽거나 유지할 수 있지만 사용자는 테이블에 WRITE LOCK
을 쓰거나 보관할 수 없습니다.
기본 저장소 엔진이 InnoDB 인 경우 MySQL은 자동으로 행 수준 잠금을 사용하므로 여러 트랜잭션이 서로를 대기시키지 않고 읽기 및 쓰기를 위해 동일한 테이블을 동시에 사용할 수 있습니다.
InnoDB 이외의 모든 스토리지 엔진의 경우, MySQL은 테이블 잠금을 사용합니다.
테이블 잠금에 대한 자세한 내용은 여기를 참조하십시오.
mysql 잠금
테이블 잠금은 ENGINE=MyISAM
에서 중요한 도구가 될 수 있지만 ENGINE=InnoDB
에서는 거의 유용하지 않습니다. InnoDB에서 테이블 잠금을 사용하려는 유혹에 빠져 있다면 트랜잭션 작업 방법에 대해 다시 생각해 봐야합니다.
MySQL은 클라이언트 세션이 테이블에 대한 액세스를 위해 다른 세션과 협력하거나 명시 적으로 세션에 대한 독점적 액세스가 필요한 기간 동안 다른 세션이 테이블을 수정하지 못하도록 명시 적으로 테이블 잠금을 획득 할 수있게합니다. 세션은 자체에 대해서만 잠금을 획득하거나 해제 할 수 있습니다. 하나의 세션은 다른 세션에 대한 잠금을 획득하거나 다른 세션에 의해 보유 된 잠금을 해제 할 수 없습니다.
테이블을 갱신 할 때 잠금을 사용하여 트랜잭션을에 D 레이트하거나 더 많은 속도를 확보 할 수 있습니다. 자세한 내용은이 섹션의 뒷부분에서 설명합니다.
명령 : LOCK TABLES table_name READ|WRITE;
단일 테이블에 잠금 유형 만 할당 할 수 있습니다.
예 (읽기 잠금) :
LOCK TABLES table_name READ;
예 (쓰기 잠금) :
LOCK TABLES table_name WRITE;
잠금이 적용되었는지 확인하려면 다음 명령을 사용하십시오.
SHOW OPEN TABLES;
모든 잠금을 플러시 / 제거하려면 다음 명령을 사용하십시오.
UNLOCK TABLES;
예:
LOCK TABLES products WRITE:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
위의 예에서 외부 연결은 테이블 테이블을 잠금 해제 할 때까지 제품 테이블에 데이터를 쓸 수 없습니다.
예:
LOCK TABLES products READ:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
위의 예에서 외부 연결은 테이블 테이블 잠금 해제가 발생할 때까지 제품 테이블에서 데이터를 읽을 수 없습니다.
행 수준 잠금
테이블이 InnoDB를 사용하면 (자), MySQL는 자동적으로 행 레벨의 락을 사용하므로, 복수의 트랜잭션 (transaction)가 서로를 대기하지 않고, read 및 write를 위해서 같은 테이블을 동시에 사용할 수 있습니다.
두 행이 동일한 행을 수정하려고하고 둘 다 행 수준 잠금을 사용하면 트랜잭션 중 하나는 다른 행이 완료 될 때까지 대기합니다.
행 수준 잠금은 수정 될 것으로 예상되는 각 행에 대해 SELECT ... FOR UPDATE
문을 사용하여 얻을 수도 있습니다.
행 레벨 잠금에 대해 자세히 설명하는 두 개의 연결 고려
연결 1
START TRANSACTION;
SELECT ledgerAmount FROM accDetails WHERE id = 1 FOR UPDATE;
연결 1에서 SELECT ... FOR UPDATE
문으로 얻은 행 수준 잠금.
연결 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
어떤 사용자가 connection 2에서 동일한 행을 업데이트하려고 시도하면 connection 1이 트랜잭션을 끝내기를 기다리거나 innodb_lock_wait_timeout
설정에 따라 오류 메시지가 표시됩니다. 기본값은 50 초입니다.
Error Code: 1205. Lock wait timeout exceeded; try restarting transaction
이 잠금에 대한 세부 사항을 보려면 SHOW ENGINE INNODB STATUS
실행하십시오.
---TRANSACTION 1973004, ACTIVE 7 sec updating
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 4, OS thread handle 0x7f996beac700, query id 30 localhost root update
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1
------- TRX HAS BEEN WAITING 7 SEC FOR THIS LOCK TO BE GRANTED:
연결 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 250 WHERE id=2;
1 row(s) affected
그러나 연결 2의 다른 행을 업데이트하는 동안 아무런 오류없이 실행됩니다.
연결 1
UPDATE accDetails SET ledgerAmount = ledgerAmount + 750 WHERE id=1;
COMMIT;
1 row(s) affected
이제 트랜잭션은 연결 1에서 커밋되기 때문에 행 잠금이 해제됩니다.
연결 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
1 row(s) affected
Connection은 Connection 1이 트랜잭션을 완료하여 행 잠금을 해제 한 후에 Connection 2에서 오류없이 실행됩니다.