DB

Database Lock (1) - Lock 이란?

자바생 2022. 12. 29. 17:07
728x90

글을 쓰게 된 이유

 

 

 

데이터베이스 트랜잭션, MVCC 등 공부를 하면서 lock을 알게 되었는데,

lock은 무엇이고, 왜 사용하는지 그리고 어떻게 사용되는지, 어떤 종류가 있는지 알아보겠습니다.

 

1. Lock이란(이번 글)

2. MySQL InnoDB Lock

 

 

 

의문점

 

 

lock을 제대로 공부하기 전에는 lock에서 낙관적 락, 비관적 락이 있다는 것만 알고 있었습니다.

 

그런데 서칭을 해보니 table lock, gap lock, next-key lock(트랜잭션 격리 수준에서 봄) 등이 존재했습니다.

 

 

그러면 이 lock들은 무엇이고, 낙관적 비관적 락은 무엇이며 각각 뭐가 다른 것인지 궁금했습니다.

 

 

 

트랜잭션과 Lock의 용도

 

 

트랜잭션을 공부하고 나서 Lock을 공부해보니 둘 다 동시성에 관련 있어서 헷갈렸습니다.

 

그래서 이번에 개념 정립을 하고자 정리해 보겠습니다.

 

트랜잭션All or Nothing으로 작업의 원자성을 보장하고,

lock동시성을 제어하기 위한 기능입니다.

 

그러면 왜 트랜잭션과 lock을 헷갈렸을까요?

 

 

제 생각에는 아마 트랜잭션 격리 수준 때문인 것 같습니다.

 

트랜잭션 격리 수준하나 또는 여러 트랜잭션 간 작업 간에 데이터를 어떻게 처리할지 전략을 말하는 것이고,

lock은 하나의 데이터에 대해 여러 커넥션이 접근하여 동시에 변경하는 것을 막기 위함입니다.

 

그래서 트랜잭션과 lock을 생각할 때는 트랜잭션 격리 수준이 아닌 트랜잭션 자체와 lock 자체를 비교하면 헷갈리지 않을 겁니다,,

(저만 헷갈릴 수도)

 

 

 

Lock의 종류

 

 

이제 Lock이 무엇인지 알았으니 RDBMS에서는 어떤 Lock을 사용하고 있는지 알아보겠습니다.

 

앞서 의문점에서 table lock, gap lock, next-key lock, 낙관적 락, 비관적 락에 대해서 의문점을 가졌었습니다.

 

결론부터 말하면 gap lock, next-key lock은 mysql innodb storage lock이고, table lock은 mysql engine lock입니다.

 

마지막으로 낙관적 락, 비관적 락은 RDB에서 사용되는 lock strategy라고 생각하시면 됩니다.

 

 

즉, MySQL에 종속적이지 않은 lock이고, 이전 lock들은 MySQL에 종속돼있는 lock이라 할 수 있습니다.

 

이번 글에서는 RDB에서 통용되고 있는 lock을 공부해 보고, 다음 글에서는 MySQL에 종속적인 lock에 대해서 공부해 보겠습니다.

 

 

 

RDB Common Lock

 

 

Lock 유형

 

 

먼저 여기서 말하는 table lock은 MySQL engine lock이 아닌 통용적으로 사용하는 테이블에 lock을 건다라고 생각하시면 됩니다.

 

exclusive lock(X lock, 배타적 락)

 

해당 lock을 가진 트랜잭션은 데이터를 수정할 수 있기 때문에 쓰기 잠금이라고도 합니다. 그래서 row나 table을 완전히 잠그고 트랜잭션이 독립적으로 수행되도록 합니다.

 

 

즉, S lock과 달리 한 시점에 하나의 트랜잭션만 특정 리소스에 대해 lock을 얻는 것입니다. 

 

 

T1이 X lock을 가지고 있다면 다른 트랜잭션(T2)는 T1이 lock을 해제할 때까지 X, S lock 모두 획득할 수 없습니다.

 

 

만약 리소스에 이미 S lock이 있으면 X lock을 획득할 수 없고, 반대로도 마찬가지입니다.

 

shared lock(S lock)

 

해당 lock을 가진 트랜잭션은 데이터를 읽을 수 있기 때문에 읽기 잠금이라고도 합니다.

 

 

T1이 S lock을 소유하면서 다른 트랜잭션(T2)이 S lock을 요청한다면 T2는 S lock을 획득할 수 있습니다. 그러나 X lock은 획득할 수 없습니다.

 

 

Intent lock

 

 

intent lock은 말 그대로 의도를 가진 lock입니다. 이 뜻은 하위 수준 lock을 갖기 전에 그보다 더 높은 수준의 lock을 먼저 갖습니다.

 

만약에 내가 특정 row의 lock을 획득하기 위해서는 그 table의 lock을 먼저 갖는 것을 말합니다.

 

그러면 왜 굳이 2번의 lock을 획득(table, row) 2단계 lock을 적용하는 걸까요?

 

먼저, 하위 수준 락이 무효화되는 상위 수준 리소스를 변경할 경우를 예방하기 위해서입니다.

예를 들면 row가 write를 하고 있는데 테이블 스키마가 변경되는 경우가 있습니다.

 

두 번째로 상위 수준에서 lock conflict를 detecting 하여 database engine의 효율성을 개선할 수 있습니다.

예를 들면 테이블 수준에서만 intent lock을 검사하여 트랜잭션이 해당 테이블에 대한 잠금을 안전하게 획득할 수 있는지 여부를 알 수 있습니다. 즉, 트랜잭션이 table lock을 얻기 위해 table의 모든 row lock을 확인할 필요가 없어집니다.

 

mysql innodb engine intent lock

 

Lock strategy

 

낙관적 락(optimistic lock)

 

트랜잭션에서 충돌이 대부분 발생하지 않는다고(낙관적) 가정하여 충돌이 발생할 경우 조치를 취합니다.

그래서 DB가 제공하는 락이 아닌 애플리케이션이 제공하는 락을 사용하는 방법입니다.

 

record를 읽고 버전 번호를 기록하며 record를 다시 write 하기 전에 버전이 변경되지 않았는지 확인합니다.

버전을 기록하고 확인하는 이유는 record를 다시 write 할 때 이전에 업데이트되었는지 atomic을 확인하기 위해서입니다.

 

왜 낙관적 락을 애플리케이션이 제공하는 락이라고 할까요?

 

낙관적 잠금은 DBMS에서 제공하는 것이 아니라 애플리케이션 자체에서 Version이라는 것을 통해 구현하기 때문에 애플리케이션이 제공하는 락이라고 합니다.

 

 

비관적 락(pessimistic lock)

 

트랜잭션 충돌이 발생(비관적)한다고 가정하고 트랜잭션 시작 시점에 락을 걸어버리는 방식입니다.

(대표적으로는 select ... for update)

 

 

 

당연히 낙관적 락보다는 높은 데이터 무결성을 가지지만 데드락이 발생할 수 있습니다.

 

 

그러면 두 locking strategy 중 어느 상황에 더 적합할까?

 

낙관적 락은 데이터 경합이 낮고, lock을 소유하고 있는 시간이 짧은 애플리케이션에서 사용된다고 합니다.

또한 충돌 가능성이 높지만 실제로는 충돌이 잘 발생하지 않는 상황에서 유용하다고 합니다.

 

충돌 가능성이 높지만 실제로는 충돌이 잘 발생하지 않는 상황은 어떤 것이 있을까요?

 

도서관에 좌석 예약 시스템을 사용한다고 가정해 보겠습니다. 여러 사용자가 동시에 한 좌석을 예약할 수 있지만, 도서관에서의 좌석은 많기 때문에 이러한 상황이 발생할 가능성이 낮습니다. 그래서 해당 상황에서는 낙관적 락을 사용하면 데이터의 일관성과 무결성을 유지하면서 트랜잭션 기간 동안 locking 시간에 따른 오버헤드를 방지할 수 있습니다.

 

반대로 비관적 락은 데이터 경합이 높은 애플리케이션에 적합합니다. (ex. 은행 계좌 시스템)

 

 

 

REFERENCES

 

 

 

Real MySQL

https://stackoverflow.com/questions/27087442/relationship-between-isolation-level-and-locks

lock 기준

RDB common lock

낙관적 락, 비관적 락(medium)

낙관적 락, 비관적 락(stackoverflow)

lock 유형(mysql 공식 문서)

intent lock(stackexchange)

728x90