[Django] Row Lock 동작방식

chrisjune
3 min readSep 18, 2019

--

장고 프레임워크에서 ORM의 row lock 테스트와 동작방식을 공유합니다.

Row level lock

기본적으로 데이터를 읽거나, 쓸 때 lock이 잡힙니다.

특정 row를 읽거나 쓸때는 row level의 lock이 잡힙니다. lock이 잡힌 상태에서는 다른 세션 또는 트랜젝션에서 해당 데이터를 접근하는데 제약이 있습니다.

read lock

  • 특정 데이터에 read lock을 걸은 경우, 다른 세션에서 read lock을 추가로 설정할 수 있습니다. 하지만 write lock을 잡을 수 없습니다. 즉, 다른 세션에서 데이터를 읽기만 가능합니다.

write lock

  • 특정 데이터에 write lock을 걸은 경우, 다른 세션에서 read lock 과 write lock 모두 설정할 수 없습니다. 즉, 다른 세션에서는 읽기와 쓰기가 불가능합니다.

따라서 read lock은 shared lock 그리고 write lock은 exclusive lock이라고도 불립니다.

Row level lock in Django

장고 프레임 워크에서는 기본적으로 데이터 쿼리를 ORM(Object-relational mapping)으로 하고, 실제 SQL 쿼리는 Django에서 자동적으로 생성하기 때문에 쿼리결과와 동작방식을 확신하기 어려울 때가 있습니다.

Lock이 잡히는 시점

객체를 변경하는 명령어가 실행되는 순간 락이 잡힙니다.

  1. 모델 객체를 변경하는 .save() 메서드가 실행되면, 해당 데이터에 row lock이 걸립니다.
  2. QuerySet객체를 변경하는 Model.objects.update() 할 때도 조건에 맞는 데이터에 row lock이 걸립니다.
from django.db import transaction  
with transaction.atomic():
model = ExampleModel.objects.get(pk=1)
model.name = 'new_name'
model.save()
# save가 실행되고나면 pk=1 row에 Lock 획득
with transaction.atomic():
model = ExampleModel.objects.filter(pk__in=[1,2,3])
model.update(name='new_name')
# update가 실행되고 나면 pk=1,2,3 row들에 lock 획득

Lock이 해제되는 시점

객체를 변경하는 명령어가 실행되는 순간 락이 잡힙니다. 그러나 락이 풀리는 시점은 트랜젝션의 유무에 따라 달라집니다.

트랜젝션이 없는 경우, 객체 변경명령이 완료되면 즉시 commit이되면서 row lock이 해제됩니다.

트랜젝션이 있는 경우, 객체를 변경이 완료되어도 lock은 유지되며, transaction 내부에서 에러가 발생하여 rollback되거나, transaction 로직이 모두 실행되어 마지막에 commit 될 때 lock이 해제됩니다.

데이터 동시 수정시 발생하는 예시

동일한 데이터를 동시에 수정하려고 할 때, LOCK을 먼저 잡은 Transaction1이 끝날 때 까지 Transaction2는 기다려야 합니다. Transaction1이 완료되면, Transacion2의 SQL 명령이 실행되고 해당 데이터는 Transaction2의 갱신내용이 최종으로 반영되어 저장됩니다.

--

--