검수요청.png검수요청.png

"락"의 두 판 사이의 차이

해시넷
이동: 둘러보기, 검색
(교착상태)
잔글 (관련 개념)
 
(사용자 3명의 중간 판 37개는 보이지 않습니다)
1번째 줄: 1번째 줄:
'''락'''(Lock)이란 [[트랜잭션]](Transaction) 처리의 순차성을 보장하기 위한 방법이다.
+
'''락'''(Lock)이란 [[데이터베이스]](Database)에서 [[트랜잭션]](Transaction) 처리의 순차성을 보장하기 위해 데이터 변경을 일시적으로 중지하는 것을 말한다. '''록'''이라고도 한다. '''데이터 잠금'''으로 번역할 수 있다.
  
 
==개요==
 
==개요==
[[데이터베이스]](DataBase)와 같은 시스템은 같은 [[데이터]]에 대해서 동시에 접근을 하는 경우가 생길 수 밖에 없는데 이럴 경우 데이터가 오염 될 있다. 그렇게 되지 않도록 데이터의 일관성과 무결성을 유지할 필요가 있는데 이런 경우에 [[DBMS]](DataBase Management System)가 사용하는 공통적인 방법이 락(Lock)이다.<ref name="티스토리">차곡차곡 사바라다, 〈[https://sabarada.tistory.com/121 (데이터베이스) Lock에 대해서 알아보자 - 기본편]〉, 《티스토리》, 2020-10-29</ref>
+
락은 데이터의 일관성과 무결성을 유지하기 위해 [[데이터베이스 관리 시스템]](DataBase Management System)이 사용하는 공통적인 방법이다. [[데이터베이스]]와 같은 시스템은 같은 [[데이터]]에 대해서 동시에 접근하는 경우가 생길 수밖에 없는데, 이럴 경우 데이터가 오염될 있기 때문이다.<ref name="티스토리">차곡차곡 사바라다, 〈[https://sabarada.tistory.com/121 (데이터베이스) Lock에 대해서 알아보자 - 기본편]〉, 《티스토리》, 2020-10-29</ref>
  
==데이터베이스==
+
== 크기 ==
데이터베이스(DataBase, DB)여러 사람이 공유하여 사용할 목적으로 체계화해 통합,관리하는 데이터의 집합이다. 여러 응용 [[시스템]]들의 통합된 정보들을 저장하여 운영할 있는 공용 데이터들의 묶음이다. 논리적으로 연관된 하나 이상의 자료의 모음으로 그 내용을 고도로 구조화함으로써 검색과 갱신의 효율화를 꾀한 것이다. 즉, 몇개의 자료 [[파일]]을 조직적으로 통합하여 자료 항목의 중복을 없애고 자료를 [[구조화]]하여 기억 시켜 놓은 자료의 집합체라고 할 수 있다.
+
락의 크기는 어느 정도의 범위를 잠글 것인지 나타낸다. 대체로 로우 락(Row Lock), 페이지 락(Page Lock), 테이블 락(Table Lock)이 있다. 잠금 비용이란 잠금을 거는 과정에서 발생하는 성능 손실을 말한다. 만약 락을 걸어야 하는 페이지가 너무 많다면, 차라리 테이블 전체에 락을 거는 것이 잠금 비용의 손실을 줄일 수 있다. 동시성 비용이란 락을 걸면서 동시성이 낮아져서 발생하는 성능 손실을 의미한다. 페이지 락 여러 개를 테이블 하나로 대체한다면 잠금 비용은 낮아지겠지만, 대신 동시성 비용은 높아질 것이다. [[에스큐엘]](SQL) 서버는 잠금 비용과 동시성 비용 간에 균형을 적절히 고려하여 락의 범위를 설정하게 된다. 일반적으로 약 40%의 페이지에 락을 걸어야 한다면 테이블 락으로 대체된다. 락의 크기를 줄이기 위해서는 적절한 인덱스를 찾는 것이 중요한데, 인덱스를 타지 못하여 테이블 풀 스캔이 발생한다면 업데이트할 데이터를 찾는 과정에서 테이블 전체에 락을 걸게 되기 때문이다. 잠금의 길이란 잠금이 지속되는 시간을 의미한다. 일반적인 공유잠금은 SELECT문이 끝나면 자동으로 풀린다. 반면에 배타잠금과 갱신잠금은 트랜잭션 종료 시까지 지속된다. 공유잠금의 길이는 경우에 따라 달라질 있어, 격리 수준이 Serializable이나 Repeatable Read인 경우 공유잠금도 트랜잭션 종료 시까지 지속된다.<ref name="쿠안"> kuaaan, [https://kuaaan.tistory.com/97 잠금에 관한 고찰(1) - 잠금(Lock) 매커니즘에 대하여]〉, 《티스토리》, 2009-02-03 </ref>
  
===모델===
+
== 종류==
실제적인 데이터베이스 구현을 위한 현재 몇몇 개념화된 논리적 데이터 모델이 있다.
+
락의 종류는 공유잠금, 배타잠금, 갱신잠금, 집중잠금이 있다.
* 관계 데이터 모델(relational datamodel) : 데이터 모델 중에서 가장 개념이 간단한 모델로 상대 수학적인 이론을 기반으로 한다. 데이터 모델을 개발하기 위해서는 테이블 관계로 묘사하는 이론적 모델 과정이 발생하는데 이를 [[개체관계모델]](entity relational model)이라고 한다. 이 관계 데이터베이스를 위한 설계 과정은 이론적으로 관계수학에 기초한 실지 구현이라 보면 된다. 현실 세계는 [[객체]]관계 [[다이어그램]]으로 표현되며, [[개체]]와 그 관계는 각기 사각과 선으로 그려진다.
 
* SQL(Structured Query Language) :이 언어는 수학적 관계 대수와 관계 논리(relational calculus)에 기반을 두고 있다. 데이터 모델은 데이터를 조작하기 위한 연산 집합을 가져야 한다. 왜냐하면 그것은 데이터베이스 구조와 제약 조건을 정의하기 때문이다. 다시 말해, 관계 데이터 모델 연산 집합은 관계 대수로 표현되고, 그 연산은 사용자에게 여러 질의를 가능하게 한다.
 
  
===장단점===
+
===공유잠금===
* 데이터베이스 장점 : 데이터 베이스의 장점으로는, 데이터를 공유하며 중복을 최소화하고 표준화가 가능하다. 또한 일관성, 무결성, 보안성을 유지하며 데이터 저장 공간도 절약된다.
+
공유잠금(Shared Lock)은 가장 낮은 강도의 잠금으로, 데이터를 읽을 때 사용되는 락이다. 일반적으로 SELECT를 할 때 공유잠금이 발생하며, SELECT가 완료되면 즉시 공유잠금은 해제된다. 이런 공유잠금은 공유잠금끼리 동시에 접근이 가능하다. , 하나의 데이터를 읽는 것은 여러 사용자가 동시에 할 수 있다. 하지만 공유잠금이 설정된 데이터에 배타잠금을 사용할 수는 없다.<ref name="티스토리"></ref><ref name="쿠안"></ref>
* 데이터베이스 단점 : 데이터베이스 전문가가 필요하고 많은 비용이 부담될 수 있다. 또한 시스템이 복잡하고 대용량 [[디스크]]로 [[엑세스]]가 집중되면 과부하도 발생할 수 있으며, 데이터 백업과 복구가 어렵다.<ref>〈[https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4 데이터베이스]〉, 《위키백과》</ref>
 
  
===트랜잭션===
+
===배타잠금===
트랜잭션(Transaction)은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 일련의 연산들을 의미한다. 트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위고, 사용자가 시스템에 대한 [[서비스]] 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업 단위이다.
+
배타잠금(Exclusive Lock)은 가장 높은 강도의 잠금이다. 데이터를 변경하고자 때 사용되며, 트랜잭션이 완료될 때까지 유지된다. 배타잠금이 해제될 때까지 다른 트랜잭션은 해당 [[리소스]]를 접근할 수 없다. 또한 해당 락은 다른 트랜잭션이 수행되고 있는 데이터에 대해서는 접근하여 함께 락을 설정할 수 없다.<ref name="티스토리"></ref> 배타잠금은 다른 모든 종류의 잠금과 호환되지 않는다. 즉, 어떠한 약한 잠금이라도 걸려 있는 레코드에 대해서는 Update가 불가능하며, 반대로 Update가 진행 중인 레코드에 대해서는 SELECT를 포함한 어떠한 작업도 불가능하다.<ref name="쿠안"></ref>
* 원자성(Atomicity) : 트랜잭션의 연산은 데이터베이스에 모두 반영되는지 아니면 전혀 반영되지 않아야 하고, 트랜잭션 내의 모든 명령은 반드시 완벽히 수행되어야 한다. 모두가 완벽히 수행되지 않고 어느 하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 한다.
+
 
* 일관성(Consistency) : 트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 변환되고, 시스템이 가지고 있는 고정 요소는 트랜잭션 수행 전과 트랜잭션 수행 완료 후의 상태가 같아야 한다.
+
===갱신잠금===
* 독립성, 격리성(Isolation) : 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행중에 다른 트랜잭션의 연산이 끼어들 수는 없다. 수행중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다.
+
갱신잠금(Update Lock)은 공유잠금과 배타잠금의 중간 강도의 잠금이다. 공유잠금과는 호환되지만 다른 갱신잠금이나 배타잠금과는 호환되지 않는다. 일반적으로는 Update의 Filter(Where절)가 수행되는 단계에서 갱신잠금이 걸리며, Filter 된 결과에 대해 실제로 Update를 시도할 때 갱신잠금은 배타잠금으로 전환된다. 공유잠금과 배타잠금이 서로 호환되지 않기 때문에 공유잠금에서 배타잠금으로 변환될 때 락 대기시간(Lock Wait)이 발생한다. 이 대기 시간은 공유잠금이 해제될 때까지의 시간을 의미하는데, 이때 잠재적인 교착상태에 빠질 가능성이 생긴다. 예를 들어 [[업데이트]](Update)를 위해 공유잠금 모드에서 배타잠금 모드로 변환하려고 하는데, 또 다른 트랜잭션이 업데이트를 위해 공유잠금을 필요로 하는 경우, 공유잠금을 해제하려는 트랜잭션과 필요로 하는 트랜잭션 사이에 교착 상태가 된다. 이런 교착 상태를 해결하기 위해서 사용되는 락이 갱신잠금 모드이다. 갱신잠금은 잠금 힌트를 통해 업데이트문이 아닌 SELECT문에도 걸 수 있다. 보통 컨버전 데드락을 방지하기 위해 SELECT문에 갱신잠금을 거는 경우가 많다.<ref name="티스토리"></ref><ref name="쿠안"></ref>
* 연속성, 지속성(Durablility) : 성공적으로 완료된 트랜잭션의 결과는 시스템이 고장 나더라도 영구적으로 반영되어야 한다.
+
 
하나의 트랜잭션은 Commit 되거나 Rollback된다.
+
===집중잠금===
* Commit연산 : 하나의 트랜잭션에 대한 작업이 성공적으로 끝났고 데이터베이스가 다시 일관된 상태에 있을 때 이 트랜잭션이 행한 갱신 연산이 완료된 것을 트랜잭션 관리자에게 알려주는 연산이다.
+
집중잠금(Intent Lock)은 [[에스큐엘]] [[서버]]에서 데이터베이스나 테이블 내의 일부 데이터 영역에 이미 공유잠금이나 배타잠금이 걸려 있다는 것을 다른 커넥션에게 알리기 위해서 사용한다.<ref name="쁨쁨">쁨쁨, 〈[https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=0164624348&logNo=40008761293 DB-Lock 의 종류와 호환성.]〉, 《네이버블로그》, 2014-12-13</ref>
* Rollback연산 : 하나의 트랜잭션 처리가 비정상적으로 종료되어 데이터베이스의 일관성을 깨뜨렸을 때 이 트랜잭션의 일부가 정상적으로 처리되었더라도 트랜잭션의 원자성을 구현하기 위해 이 트랜잭션이 행한 모든 연산을 취소 하는 연산이다. Rollback시에는 해당 트랜잭션을 재시작하거나 폐기한다. <ref>코딩팩토리, 〈[https://coding-factory.tistory.com/226 (DB기초) 트랜잭션이란 무엇인가?]〉, 《티스토리》, 2018-08-20</ref>
+
 
 +
==설정 범위==
 +
락의 설정 범위(Level)는 6가지가 있다.
 +
* '''[[데이터베이스]]'''(Database) : 전체 데이터베이스를 기준으로 락이 걸린다. 1개의 [[세션]]이 하나의 데이터베이스의 데이터에 접근할 수 있다. DB 전체에 영향이 있는 DB 업데이트와 같은 작업에서만 사용한다.
 +
* '''[[파일]]'''(file) : 데이터베이스 파일을 기준으로 락이 걸린다. 데이터베이스에서 파일이란, 테이블 등과 같이 실제 데이터가 쓰이는 물리적인 저장소를 뜻한다. 파일 전체를 백업할 때 사용한다.
 +
* '''[[테이블]]'''(Table) : 테이블 기준으로 락이 걸린다. 전체 테이블에 대한 데이터 변경이 있으면 사용한다. 테이블을 제어하는 [[DDL]] 구문을 사용할 때 락이 걸린다고 'DDL 락'이라고도 한다.
 +
* '''[[페이지]]·[[블럭]]'''(Page·block) : 파일을 구성하는 페이지와 블록을 기준으로 락이 걸린다.
 +
* '''[[컬럼]]'''(Column) : 컬럼 기준으로 락이 걸린다. 다만 락 설정 및 해제 시 리소스가 많이 든다. 그래서 잘 사용하지 않는다.
 +
* '''[[행]]'''(Row) : 행 수준의 락을 건다. 가장 많이 사용되는 락이다.<ref>평범한 개발자 센트빈, 〈[https://centbin-dev.tistory.com/40 (개발자 면접) Database Lock 종류 및 기능]〉, 《티스토리》, 2021-01-25</ref>
  
==락의 종류==
+
== 관련 개념 ==
락(Lock)의 종류는 공유락(Shared Lock)과 베타락(Exclusive Lock)이 있다. 공유락은 다른 말로 Read Lock이라고 불리며 베타락은 Write Lock이라고도 불린다.  
+
===데이터베이스===
 +
[[데이터베이스]]는 여러 사람이 공유하여 사용할 목적으로 체계화해 통합, 관리하는 데이터의 집합이다. 여러 응용 [[시스템]]들의 통합된 정보들을 저장하여 운영할 수 있는 공용 데이터들의 묶음이다. 논리적으로 연관된 하나 이상의 자료의 모음으로 그 내용을 고도로 구조화함으로써 검색과 갱신의 효율화를 꾀한 것이다. 즉, 몇 개의 자료 [[파일]]을 조직적으로 통합하여 자료 항목의 중복을 없애고 자료를 [[구조화]]하여 기억 시켜 놓은 자료의 집합체라고 할 수 있다.<ref>〈[https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4 데이터베이스]〉, 《위키백과》</ref>
  
===공유락===
+
===트랜잭션===
공유락(Shared Lock)데이터를 읽을 때 사용되어지는 락이다. 이런 공유락은 공유락끼리는 동시에 접근이 가능하다. , 하나의 데이터를 읽는 것은 여러 사용자가 동시에 할 수 있다. 하지만 공유락이 설정된 데이터에 베타락을 사용할 수는 없다.
+
[[트랜잭션]]데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산을 의미한다. 트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위고, 사용자가 시스템에 대한 [[서비스]] 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업 단위이다.
  
===베타락===
+
* '''원자성'''(Atomicity) : 트랜잭션의 연산은 데이터베이스에 모두 반영되는지 아니면 전혀 반영되지 않아야 하고, 트랜잭션 내의 모든 명령은 반드시 완벽히 수행되어야 한다. 모두가 완벽히 수행되지 않고 어느 하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 한다.
베타락(Exclusive Lock)은 데이터를 변경하고자 할 때 사용되며, 트랜잭션이 완료될 때 까지 유지된다. 베타락이 해제될 까지 다른 트랜잭션은 해당 [[리소스]]를 접근할 수 없다. 또한 해당 락은 다른 트랜잭션이 수행되고 있는 데이터에 대해서는 접근하여 함께 락을 설정할 수 없다.<ref name="티스토리"></ref>
+
* '''일관성'''(Consistency) : 트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 변환되고, 시스템이 가지고 있는 고정 요소는 트랜잭션 수행 전과 트랜잭션 수행 완료 후의 상태가 같아야 한다.
 +
* '''독립성, 격리성'''(Isolation) : 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행 중에 다른 트랜잭션의 연산이 끼어들 수는 없다. 수행 중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다.
 +
* '''연속성, 지속성'''(Durability) : 성공적으로 완료된 트랜잭션의 결과는 시스템이 고장 나더라도 영구적으로 반영되어야 한다.
 +
하나의 트랜잭션은 커밋(Commit) 되거나 롤백(Rollback) 된다.
 +
* '''커밋 연산''' : 하나의 트랜잭션에 대한 작업이 성공적으로 끝났고 데이터베이스가 다시 일관된 상태에 있을 이 트랜잭션이 행한 갱신 연산이 완료된 것을 트랜잭션 관리자에게 알려 주는 연산이다.
 +
* '''롤백 연산''' : 하나의 트랜잭션 처리가 비정상적으로 종료되어 데이터베이스의 일관성을 깨뜨렸을 이 트랜잭션의 일부가 정상적으로 처리되었더라도 트랜잭션의 원자성을 구현하기 위해 이 트랜잭션이 행한 모든 연산을 취소하는 연산이다. 롤백 시에는 해당 트랜잭션을 재시작하거나 폐기한다.<ref>코딩팩토리, 〈[https://coding-factory.tistory.com/226 (DB기초) 트랜잭션이란 무엇인가?]〉, 《티스토리》, 2018-08-20</ref>
  
==락의 설정 범위==
+
가장 흔한 예로 계좌이체 작업이 있다. A라는 계좌에서 B계좌로 이체하는 작업은 A 계좌의 잔액을 읽어서 이체할 금액 차감이 가능하면 차감 후 잔액을 A 계좌에 기록하고 B 계좌에 이체 금액만큼 더하여 그 결과를 B 계좌에 기록하면 모든 작업이 완료된다. 하지만 A계좌의 차감까지 진행된 상태에서 전원이 나가는 등의 장애로 B 계좌에 더해진 금액이 기록되지 않으면 문제가 발생한다. 이러한 문제 발생을 막기 위해서는 위의 개별적인 작업들을 하나로 묶어 트랜잭션으로 구성하게 된다.<ref>〈[http://www.devholic.net/xe/?menu_code=tipsql&category=0&search_target=title&search_keyword=&sort_target=&sort_type=DESC&page=1&listStyle=&document_srl=1000292&act= 트랜잭션(Transaction)]〉, 《devholic》</ref>
락(Lock)의 설정 범위(Level)은 6가지가 있다.
 
* 데이터베이스(DataBase) : 전체 데이터베이스를 기준으로 락이 걸린다. 1개의 [[세션]]이 하나의 데이터베이스의 데이터에 접근할 수 있다. DB전체에 영향이 있는 DB 업데이트와 같은 작업에서만 사용한다.
 
* [[파일]] : 데이터베이스 파일을 기준으로 락이 걸린다. 데이터베이스에서 파일이란, 테이블 등과 같이 실제 데이터가 쓰여지는 물리적인 저장소를 뜻한다. 파일 전체를 백업할 때 사용한다.
 
* [[테이블]](Table) : 테이블 기준으로 락이 걸린다. 전체 테이블의 대한 데이터 변경이 있을 경우 사용한다. 테이블을 제어하는 [[DDL]] 구문을 사용할 때 락이 걸린다고 'DDL Lock' 이라고도 한다.
 
* 페이지와 블럭 : 파일을 구성하는 페이지와 블록을 기준으로 락이 걸린다.
 
* [[컬럼]](Column) : 컬럼 기준으로 락이 걸린다. 다만 락 설정 및 해제 시 리소스가 많이 든다. 그래서 잘 사용하지 않는다.
 
* 행(Row) : 행 수준의 락을 건다. 가장 많이 사용되는 락이다.<ref>평범한 개발자 센트빈, 〈[https://centbin-dev.tistory.com/40 (개발자 면접) Database Lock 종류 및 기능]〉, 《티스토리》, 2021-01-25</ref>
 
  
==블로킹==
+
===블로킹===
[[블로킹]](Blocking)은 락간의 결합이라고 볼 수 있다. 즉, 특정 트랜잭션이 끝나지 않아 락이 걸린 상태로 멈춰있는 상태를 의미한다. 베타락-베타락 이나 공유락-베타락 끼리 블로킹이 발생할 수 있다. 이를 해결하기 위에서는 트랜잭션 Commit이나 Rollback을 사용해야 한다.  
+
[[블로킹]](Blocking)은 락 간의 결합이라고 볼 수 있다. 즉, 특정 트랜잭션이 끝나지 않아 락이 걸린 상태로 멈춰 있는 상태를 의미한다. 배타잠금-배타잠금이나 공유잠금-배타잠금끼리 블로킹이 발생할 수 있다. 이를 해결하기 위해서는 트랜잭션 컴밋이나 롤백을 사용해야 한다.  
  
DB를 사용하는 [[프로그래밍]]을 진행하면서 몇 가지 주의사항이 있다.
+
데이터베이스를 사용하는 [[프로그래밍]]을 진행하면서 몇 가지 주의사항이 있다.
* 한 트랜잭션의 길이를 너무 길게하는 것은 경합의 확률을 올린다.
+
* 한 트랜잭션의 길이를 너무 길게 하는 것은 경합의 확률을 올린다.
* 처음부터 설계할 때 같은 데이터를 갱신하는 트랜잭션이 동시에 수행되지 않도록 해야한다.
+
* 처음부터 설계할 때 같은 데이터를 갱신하는 트랜잭션이 동시에 수행되지 않도록 해야 한다.
 
* 트랜잭션 격리성 수준을 불필요하게 상향 조정하지 않는다.
 
* 트랜잭션 격리성 수준을 불필요하게 상향 조정하지 않는다.
* 쿼리를 오랜시간 잡아두지 않도록 적절한 [[튜닝]]을 진행한다.
+
* [[쿼리]]를 오랜 시간 잡아두지 않도록 적절한 [[튜닝]]을 진행한다.
 
이 외에 DBMS에 따라서 락 대기 시간 등을 설정할 수 있다.<ref name="티스토리"></ref>
 
이 외에 DBMS에 따라서 락 대기 시간 등을 설정할 수 있다.<ref name="티스토리"></ref>
  
==교착상태==
+
===교착상태===
교착상태(DeadLock)두 트랜잭션이 각각 락을 성정하고 다음 서로의 락에 접근하여 값을 얻어오려고 할 때 이미 각각의 트랜잭션에 의해 락이 설정되어 있기 때문에 양쪽 트랜잭션 모두 영원히 처리가 되지 않게 되는 상태를 말한다. 상대방 락이 끝나야 원하는 데이터를 가져오는데 바라보고 있는 서로의 락이 같은 상태가 되다보니 영원히 끝나지 않는 상황이 발생하게 된다. 이를 방지하기 위해서는 접근 순서를 동일하게 하는것이 중요함으로, 접근 순서 규칙을 정해야 한다. 교착상태를 해결하려면 둘 중 하나의 트랜잭션을 강제로 종료해야 한다. <ref name="티스토리"></ref>
+
[[교착상태]](DeadLock) 또는 데드락은 두 트랜잭션이 각각 락을 성정하고 다음 서로의 락에 접근하여 값을 얻어오려고 할 때 이미 각각의 트랜잭션에 의해 락이 설정되어 있기 때문에 양쪽 트랜잭션 모두 영원히 처리되지 않게 되는 상태를 말한다. 상대방 락이 끝나야 원하는 데이터를 가져오는데 바라보고 있는 서로의 락이 같은 상태가 되다 보니 영원히 끝나지 않는 상황이 발생하게 된다. 이를 방지하기 위해서는 접근 순서를 동일하게 하는 것이 중요함으로, 접근 순서 규칙을 정해야 한다. 교착상태를 해결하려면 둘 중 하나의 트랜잭션을 강제로 종료해야 한다.<ref name="티스토리"></ref>
  
 
{{각주}}
 
{{각주}}
64번째 줄: 68번째 줄:
 
* 코딩팩토리, 〈[https://coding-factory.tistory.com/226 (DB기초) 트랜잭션이란 무엇인가?]〉, 《티스토리》, 2018-08-20
 
* 코딩팩토리, 〈[https://coding-factory.tistory.com/226 (DB기초) 트랜잭션이란 무엇인가?]〉, 《티스토리》, 2018-08-20
 
* 평범한 개발자 센트빈, 〈[https://centbin-dev.tistory.com/40 (개발자 면접) Database Lock 종류 및 기능]〉, 《티스토리》, 2021-01-25
 
* 평범한 개발자 센트빈, 〈[https://centbin-dev.tistory.com/40 (개발자 면접) Database Lock 종류 및 기능]〉, 《티스토리》, 2021-01-25
 +
* 쁨쁨, 〈[https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=0164624348&logNo=40008761293 DB-Lock 의 종류와 호환성.]〉, 《네이버블로그》, 2014-12-13
 +
* 〈[http://www.devholic.net/xe/?menu_code=tipsql&category=0&search_target=title&search_keyword=&sort_target=&sort_type=DESC&page=1&listStyle=&document_srl=1000292&act= 트랜잭션(Transaction)]〉, 《devholic》
 +
* kuaaan, 〈[https://kuaaan.tistory.com/97 잠금에 관한 고찰(1) - 잠금(Lock) 매커니즘에 대하여]〉, 《티스토리》, 2009-02-03
  
 
==같이 보기==
 
==같이 보기==
73번째 줄: 80번째 줄:
 
* [[해시]]
 
* [[해시]]
  
 
+
{{데이터|검토 필요}}
{{프로그래밍|검토 필요}}
 

2021년 9월 29일 (수) 14:13 기준 최신판

(Lock)이란 데이터베이스(Database)에서 트랜잭션(Transaction) 처리의 순차성을 보장하기 위해 데이터 변경을 일시적으로 중지하는 것을 말한다. 이라고도 한다. 데이터 잠금으로 번역할 수 있다.

개요[편집]

락은 데이터의 일관성과 무결성을 유지하기 위해 데이터베이스 관리 시스템(DataBase Management System)이 사용하는 공통적인 방법이다. 데이터베이스와 같은 시스템은 같은 데이터에 대해서 동시에 접근하는 경우가 생길 수밖에 없는데, 이럴 경우 데이터가 오염될 수 있기 때문이다.[1]

크기[편집]

락의 크기는 어느 정도의 범위를 잠글 것인지 나타낸다. 대체로 로우 락(Row Lock), 페이지 락(Page Lock), 테이블 락(Table Lock)이 있다. 잠금 비용이란 잠금을 거는 과정에서 발생하는 성능 손실을 말한다. 만약 락을 걸어야 하는 페이지가 너무 많다면, 차라리 테이블 전체에 락을 거는 것이 잠금 비용의 손실을 줄일 수 있다. 동시성 비용이란 락을 걸면서 동시성이 낮아져서 발생하는 성능 손실을 의미한다. 페이지 락 여러 개를 테이블 하나로 대체한다면 잠금 비용은 낮아지겠지만, 대신 동시성 비용은 높아질 것이다. 에스큐엘(SQL) 서버는 잠금 비용과 동시성 비용 간에 균형을 적절히 고려하여 락의 범위를 설정하게 된다. 일반적으로 약 40%의 페이지에 락을 걸어야 한다면 테이블 락으로 대체된다. 락의 크기를 줄이기 위해서는 적절한 인덱스를 찾는 것이 중요한데, 인덱스를 타지 못하여 테이블 풀 스캔이 발생한다면 업데이트할 데이터를 찾는 과정에서 테이블 전체에 락을 걸게 되기 때문이다. 잠금의 길이란 잠금이 지속되는 시간을 의미한다. 일반적인 공유잠금은 SELECT문이 끝나면 자동으로 풀린다. 반면에 배타잠금과 갱신잠금은 트랜잭션 종료 시까지 지속된다. 공유잠금의 길이는 경우에 따라 달라질 수 있어, 격리 수준이 Serializable이나 Repeatable Read인 경우 공유잠금도 트랜잭션 종료 시까지 지속된다.[2]

종류[편집]

락의 종류는 공유잠금, 배타잠금, 갱신잠금, 집중잠금이 있다.

공유잠금[편집]

공유잠금(Shared Lock)은 가장 낮은 강도의 잠금으로, 데이터를 읽을 때 사용되는 락이다. 일반적으로 SELECT를 할 때 공유잠금이 발생하며, SELECT가 완료되면 즉시 공유잠금은 해제된다. 이런 공유잠금은 공유잠금끼리 동시에 접근이 가능하다. 즉, 하나의 데이터를 읽는 것은 여러 사용자가 동시에 할 수 있다. 하지만 공유잠금이 설정된 데이터에 배타잠금을 사용할 수는 없다.[1][2]

배타잠금[편집]

배타잠금(Exclusive Lock)은 가장 높은 강도의 잠금이다. 데이터를 변경하고자 할 때 사용되며, 트랜잭션이 완료될 때까지 유지된다. 배타잠금이 해제될 때까지 다른 트랜잭션은 해당 리소스를 접근할 수 없다. 또한 해당 락은 다른 트랜잭션이 수행되고 있는 데이터에 대해서는 접근하여 함께 락을 설정할 수 없다.[1] 배타잠금은 다른 모든 종류의 잠금과 호환되지 않는다. 즉, 어떠한 약한 잠금이라도 걸려 있는 레코드에 대해서는 Update가 불가능하며, 반대로 Update가 진행 중인 레코드에 대해서는 SELECT를 포함한 어떠한 작업도 불가능하다.[2]

갱신잠금[편집]

갱신잠금(Update Lock)은 공유잠금과 배타잠금의 중간 강도의 잠금이다. 공유잠금과는 호환되지만 다른 갱신잠금이나 배타잠금과는 호환되지 않는다. 일반적으로는 Update의 Filter(Where절)가 수행되는 단계에서 갱신잠금이 걸리며, Filter 된 결과에 대해 실제로 Update를 시도할 때 갱신잠금은 배타잠금으로 전환된다. 공유잠금과 배타잠금이 서로 호환되지 않기 때문에 공유잠금에서 배타잠금으로 변환될 때 락 대기시간(Lock Wait)이 발생한다. 이 대기 시간은 공유잠금이 해제될 때까지의 시간을 의미하는데, 이때 잠재적인 교착상태에 빠질 가능성이 생긴다. 예를 들어 업데이트(Update)를 위해 공유잠금 모드에서 배타잠금 모드로 변환하려고 하는데, 또 다른 트랜잭션이 업데이트를 위해 공유잠금을 필요로 하는 경우, 공유잠금을 해제하려는 트랜잭션과 필요로 하는 트랜잭션 사이에 교착 상태가 된다. 이런 교착 상태를 해결하기 위해서 사용되는 락이 갱신잠금 모드이다. 갱신잠금은 잠금 힌트를 통해 업데이트문이 아닌 SELECT문에도 걸 수 있다. 보통 컨버전 데드락을 방지하기 위해 SELECT문에 갱신잠금을 거는 경우가 많다.[1][2]

집중잠금[편집]

집중잠금(Intent Lock)은 에스큐엘 서버에서 데이터베이스나 테이블 내의 일부 데이터 영역에 이미 공유잠금이나 배타잠금이 걸려 있다는 것을 다른 커넥션에게 알리기 위해서 사용한다.[3]

설정 범위[편집]

락의 설정 범위(Level)는 6가지가 있다.

  • 데이터베이스(Database) : 전체 데이터베이스를 기준으로 락이 걸린다. 1개의 세션이 하나의 데이터베이스의 데이터에 접근할 수 있다. DB 전체에 영향이 있는 DB 업데이트와 같은 작업에서만 사용한다.
  • 파일(file) : 데이터베이스 파일을 기준으로 락이 걸린다. 데이터베이스에서 파일이란, 테이블 등과 같이 실제 데이터가 쓰이는 물리적인 저장소를 뜻한다. 파일 전체를 백업할 때 사용한다.
  • 테이블(Table) : 테이블 기준으로 락이 걸린다. 전체 테이블에 대한 데이터 변경이 있으면 사용한다. 테이블을 제어하는 DDL 구문을 사용할 때 락이 걸린다고 'DDL 락'이라고도 한다.
  • 페이지·블럭(Page·block) : 파일을 구성하는 페이지와 블록을 기준으로 락이 걸린다.
  • 컬럼(Column) : 컬럼 기준으로 락이 걸린다. 다만 락 설정 및 해제 시 리소스가 많이 든다. 그래서 잘 사용하지 않는다.
  • (Row) : 행 수준의 락을 건다. 가장 많이 사용되는 락이다.[4]

관련 개념[편집]

데이터베이스[편집]

데이터베이스는 여러 사람이 공유하여 사용할 목적으로 체계화해 통합, 관리하는 데이터의 집합이다. 여러 응용 시스템들의 통합된 정보들을 저장하여 운영할 수 있는 공용 데이터들의 묶음이다. 논리적으로 연관된 하나 이상의 자료의 모음으로 그 내용을 고도로 구조화함으로써 검색과 갱신의 효율화를 꾀한 것이다. 즉, 몇 개의 자료 파일을 조직적으로 통합하여 자료 항목의 중복을 없애고 자료를 구조화하여 기억 시켜 놓은 자료의 집합체라고 할 수 있다.[5]

트랜잭션[편집]

트랜잭션은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산을 의미한다. 트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위고, 사용자가 시스템에 대한 서비스 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업 단위이다.

  • 원자성(Atomicity) : 트랜잭션의 연산은 데이터베이스에 모두 반영되는지 아니면 전혀 반영되지 않아야 하고, 트랜잭션 내의 모든 명령은 반드시 완벽히 수행되어야 한다. 모두가 완벽히 수행되지 않고 어느 하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 한다.
  • 일관성(Consistency) : 트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 변환되고, 시스템이 가지고 있는 고정 요소는 트랜잭션 수행 전과 트랜잭션 수행 완료 후의 상태가 같아야 한다.
  • 독립성, 격리성(Isolation) : 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행 중에 다른 트랜잭션의 연산이 끼어들 수는 없다. 수행 중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다.
  • 연속성, 지속성(Durability) : 성공적으로 완료된 트랜잭션의 결과는 시스템이 고장 나더라도 영구적으로 반영되어야 한다.

하나의 트랜잭션은 커밋(Commit) 되거나 롤백(Rollback) 된다.

  • 커밋 연산 : 하나의 트랜잭션에 대한 작업이 성공적으로 끝났고 데이터베이스가 다시 일관된 상태에 있을 때 이 트랜잭션이 행한 갱신 연산이 완료된 것을 트랜잭션 관리자에게 알려 주는 연산이다.
  • 롤백 연산 : 하나의 트랜잭션 처리가 비정상적으로 종료되어 데이터베이스의 일관성을 깨뜨렸을 때 이 트랜잭션의 일부가 정상적으로 처리되었더라도 트랜잭션의 원자성을 구현하기 위해 이 트랜잭션이 행한 모든 연산을 취소하는 연산이다. 롤백 시에는 해당 트랜잭션을 재시작하거나 폐기한다.[6]

가장 흔한 예로 계좌이체 작업이 있다. A라는 계좌에서 B계좌로 이체하는 작업은 A 계좌의 잔액을 읽어서 이체할 금액 차감이 가능하면 차감 후 잔액을 A 계좌에 기록하고 B 계좌에 이체 금액만큼 더하여 그 결과를 B 계좌에 기록하면 모든 작업이 완료된다. 하지만 A계좌의 차감까지 진행된 상태에서 전원이 나가는 등의 장애로 B 계좌에 더해진 금액이 기록되지 않으면 문제가 발생한다. 이러한 문제 발생을 막기 위해서는 위의 개별적인 작업들을 하나로 묶어 트랜잭션으로 구성하게 된다.[7]

블로킹[편집]

블로킹(Blocking)은 락 간의 결합이라고 볼 수 있다. 즉, 특정 트랜잭션이 끝나지 않아 락이 걸린 상태로 멈춰 있는 상태를 의미한다. 배타잠금-배타잠금이나 공유잠금-배타잠금끼리 블로킹이 발생할 수 있다. 이를 해결하기 위해서는 트랜잭션 컴밋이나 롤백을 사용해야 한다.

데이터베이스를 사용하는 프로그래밍을 진행하면서 몇 가지 주의사항이 있다.

  • 한 트랜잭션의 길이를 너무 길게 하는 것은 경합의 확률을 올린다.
  • 처음부터 설계할 때 같은 데이터를 갱신하는 트랜잭션이 동시에 수행되지 않도록 해야 한다.
  • 트랜잭션 격리성 수준을 불필요하게 상향 조정하지 않는다.
  • 쿼리를 오랜 시간 잡아두지 않도록 적절한 튜닝을 진행한다.

이 외에 DBMS에 따라서 락 대기 시간 등을 설정할 수 있다.[1]

교착상태[편집]

교착상태(DeadLock) 또는 데드락은 두 트랜잭션이 각각 락을 성정하고 다음 서로의 락에 접근하여 값을 얻어오려고 할 때 이미 각각의 트랜잭션에 의해 락이 설정되어 있기 때문에 양쪽 트랜잭션 모두 영원히 처리되지 않게 되는 상태를 말한다. 상대방 락이 끝나야 원하는 데이터를 가져오는데 바라보고 있는 서로의 락이 같은 상태가 되다 보니 영원히 끝나지 않는 상황이 발생하게 된다. 이를 방지하기 위해서는 접근 순서를 동일하게 하는 것이 중요함으로, 접근 순서 규칙을 정해야 한다. 교착상태를 해결하려면 둘 중 하나의 트랜잭션을 강제로 종료해야 한다.[1]

각주[편집]

  1. 1.0 1.1 1.2 1.3 1.4 1.5 차곡차곡 사바라다, 〈(데이터베이스) Lock에 대해서 알아보자 - 기본편〉, 《티스토리》, 2020-10-29
  2. 2.0 2.1 2.2 2.3 kuaaan, 〈잠금에 관한 고찰(1) - 잠금(Lock) 매커니즘에 대하여〉, 《티스토리》, 2009-02-03
  3. 쁨쁨, 〈DB-Lock 의 종류와 호환성.〉, 《네이버블로그》, 2014-12-13
  4. 평범한 개발자 센트빈, 〈(개발자 면접) Database Lock 종류 및 기능〉, 《티스토리》, 2021-01-25
  5. 데이터베이스〉, 《위키백과》
  6. 코딩팩토리, 〈(DB기초) 트랜잭션이란 무엇인가?〉, 《티스토리》, 2018-08-20
  7. 트랜잭션(Transaction)〉, 《devholic》

참고자료[편집]

같이 보기[편집]


  검수요청.png검수요청.png 이 락 문서는 데이터에 관한 글로서 검토가 필요합니다. 위키 문서는 누구든지 자유롭게 편집할 수 있습니다. [편집]을 눌러 문서 내용을 검토·수정해 주세요.