들어가며
SELECT ... FOR SHARE- 읽은 모든 행에 공유 모드 잠금을 설정
- 다른 세션은 행을 읽을 수 있지만 트랜잭션이 커밋될 때까지 수정할 수 없다.
- 아직 커밋되지 않은 다른 트랜잭션에 의해 이러한 행이 변경된 경우 쿼리는 해당 트랜잭션이 종료될 떄까지 기다린 다음 최신 값을 사용합니다.
예전에는 이렇게 쓴거같다.
SELECT ... LOCK IN SHARE MODEMySQL 8.0.22 이전에는 SELET … FOR SHARE 권한 혹은 SELECT 중 하나 이상이 필요
MySQL 8.0.22부터 SELECT ... FOR SHARE 명령문은 MySQL 권한 부여 테이블에 대한 읽기 잠금을 획득하지 않는다.
SELECT ... FOR UPDATE사전 준비
Docker를 통해서 MySQL 실행하기
❯ docker pull mysql:latestmysql container 띄우기
❯ docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=<루트 패스워드> -d -p 3306:3306 mysql:latestmysql 접속하기
- 2개의 세션을 연결하여 테스트
❯ docker exec -it mysql-container bash2개의 세션이 연결되었는지 확인
mysql> show processlist;
+----+-----------------+-----------+------------+---------+-------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+------------+---------+-------+------------------------+------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 34795 | Waiting on empty queue | NULL |
| 10 | root | localhost | lock_tests | Sleep | 31 | | NULL |
| 11 | root | localhost | lock_tests | Query | 0 | init | show processlist |
+----+-----------------+-----------+------------+---------+-------+------------------------+------------------+
3 rows in set (0.00 sec)테스트용 테이블 생성
mysql> CREATE TABLE `coffee` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` varchar(255) NOT NULL COMMENT '커피 이름'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;시나리오 1
- Primary Key를 이용해서 조회 시 Row Level 단위로 락이 걸린다.
session 1
START TRANSACTION;
SELECT * FROM coffee id = 1 FOR UPDATE;
+----+-------+
| id | name |
+----+-------+
| 1 | latte |
+----+-------+session 2
START TRANSACTION;
SELECT * FROM coffee WHERE id = 1 FOR UPDATE;
--; 대기 중