[DB] 공유락(Shared Lock)과 배타락(Exclusive Lock)

bbbooo·2024년 4월 5일
3

DataBase

목록 보기
3/3

들어가며

최근에 데이터베이스 락에 대해 공부하며 공유락과 배타락에 대해서도 알게 되었는데, 타 블로그들에서 보았던 정보들과 실습한 내용에서 상이한 부분이 있어 작성하게 되었다.



락이란 (Lock)

트랜잭션에서 조회한 데이터에 대해 다른 트랜잭션을 동시성 제어하고 싶은 경우 사용되는 것이 데이터베이스의 Lock이다.

이 락에는 두 가지 종류가 있는데 공유락과, 배타락이다.

공유락은 다른 트랜잭션에서 공유락을 얻을 수 있으나, 쓰기와 배타락을 얻는게 불가능하다.
배타락은 다른 트랜잭션에서 공유락과 배타락 둘다 얻을 수 없으나, 단순히 데이터를 select 하는 것은 가능하다.

위 정의가 이 글의 핵심이다.


공유락 (Shared Lock)

  • s-lock으로도 불리며 select ... for share로 락을 획득할 수 있다.
  • 다양한 트랜잭션에서 공유락을 가질 수 있으나, 공유락이 걸려있는 행에 대해 배타락을 가질 수 없다.
  • 공유락에 걸리게 되면 해당 조회가 커밋이 될때까지 어떠한 트랜잭션에서도 해당 행에 대해 쓰기 작업과 배타락을 가질 수 없다.

다음의 예시를 보며 함께 알아보자.

트랜잭션을 시작하며 CategoryNo에 대해 공유락을 걸었다.

// 트랜잭션 시작
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

// 공유락 획득
mysql> select c.categoryNo from category c for share;
+------------+
| categoryNo |
+------------+
|          4 |
|          5 |
|          3 |
|          1 |
|          6 |
|          7 |
|          2 |
+------------+
7 rows in set (0.00 sec)

이때 다른 트랜잭션에서 쓰기 작업이나 배타락을 얻고자 한다면 공유락을 걸었던 트랜잭션에서 commit이 되기 전까지 대기하게 된다.

// 새로운 트랜잭션
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

// 값 추가
mysql> insert into category values (8, 'popo');
		// !! 대기 상태

-----------------------------------------------------
        
// 기존 트랜잭션
...
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

// 새로운 트랜잭션
...
mysql> insert into category values (8, 'popo');
Query OK, 1 row affected (34.99 sec)

다른 트랜잭션에서도 공유락은 정상적으로 얻을 수 있다.

// 새로운 트랜잭션
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into category values (8, 'popo');
Query OK, 1 row affected (34.99 sec)

// 읽기락
mysql> select c.categoryNo from category c for share;
+------------+
| categoryNo |
+------------+
|          4 |
|          5 |
|          3 |
|          1 |
|          6 |
|          8 |
|          7 |
|          2 |
+------------+
8 rows in set (0.00 sec)

배타락 (Exclusive Lock)

  • x-lock으로도 불리며, select ... for update 로 락을 획득할 수 있다.
  • 배타락을 가지게 되면 다른 트랜잭션에서는 공유락, 배타락을 얻는게 불가능하다.
  • 즉, 쓰기 작업과 공유락 조회는 불가능하다.
  • 하지만 단순히 데이터를 select 하는 것이라면 읽기가 가능하다. (물론 트랜잭션 격리수준에 따라서 다르다.)

마찬가지로 다음의 예시를 보며 함께 알아보자.

트랜잭션을 시작하며 배타락을 걸었다.

// 트랜잭션 시작
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

// 배타락 획득
mysql> select * from category for update;
+------------+--------------+
| CategoryNo | CategoryName |
+------------+--------------+
|          4 | hi           |
|          5 | hidi         |
|          3 | hoo          |
|          1 | Novel        |
|          6 | popo         |
|          8 | popo         |
|          7 | roro         |
|          2 | Science      |
+------------+--------------+
8 rows in set (0.00 sec)

다른 트랜잭션에서는 해당 테이블에 대해 공유락, 배타락, 쓰기 작업 모두 불가능하다. 다만, 이는 작업이 아예 이루어질 수 없다기보다는 대기상태에 있는 것에 가깝다. 공유락과 마찬가지로 commit을 하면 대기 중이던 작업들이 실행된다.

락을 얻지 않는, 단순한 select의 경우는 바로 실행된다.


✅ 배타락에 대한 오해
1. 배타락은 읽기, 쓰기 둘다 잠금이라고 이해한 사람도 있으나 이는 아니다. 정확히는 공유락, 배타락 불가능이다.
2. 따라서, 락을 얻지 않는 단순한 조회의 경우 배타락에서도 읽는 것이 가능하다.
2. 그렇다고 무조건 읽는 것이 가능하냐면 그것은 아니다. 트랜잭션 격리수준에 따라서 배타락에서도 읽기가 불가능한 경우(Serializable)가 있다.



마치며

이전에는 나도 배타락의 경우 읽기, 쓰기 둘다 안된다고 알고 있었는데 실제로 학습을 해보니 잘못 알고 있었다는 것을 알게 되었다. 누군가에게 이 글이 도움이 될 수 있다면 매우 뿌듯할 것 같다.


참고자료
레코드 로킹

0개의 댓글

관련 채용 정보