트랜잭션
먼저 계속 말하더라. 데이터베이스의 일관성은 매우 중요하다. 항상 동기화, 락 이런 개념이 나오면 어려워지더라. 근데 그만큼 중요하니까..
드가보자..
먼저 트랜잭션부터 살펴보자.
트랜잭션은 디비에서 엄청 중요중요한 개념으로 하나의 논리적인 작업 단위를 말한다.
보통 ACID 특성이라고 하는데 이걸 잘 생각하면서 날려야 한다.
기억이 가물가물한데 ATOMY, CONSISTENCY, ISOLATION, DE... 기억안난다..
DURABILITY라고 한다 (역시 GPT)
한번 살펴보자.
1. 원자성
A. 트랜잭션 내의 모든 작업은 한번에 처리되어야 한다.
B. 모두 성공적으로 실행되거나 아니면 아예 100% 실행되지 말아야 한다.
2. 일관성
A. 트랜잭션이 성공적으로 완료되면, 데이터베이스는 하나의 일관된 상태에서 다른 일관된 상태로 전환되어야 한다.
3. 고립성
A. 동시에 실행되는 여러 트랜잭션들은 서로 영향을 주어서는 안된다.
B. 각 트랜잭션은 독립적으로 실행되어야 한다.
4. 지속성
A. 트랜잭션이 성공적으로 완료되면, 그 결과는 시슽엠의 장애가 발생하더라도 영구적으로 반영되어야 한다.
-- 데이터베이스 작업 수행
INSERT INTO myTable (Column1) VALUES ('Value1');
UPDATE myTable SET Column1 = 'Value2' WHERE Column2 = 'Condition';
DELETE FROM myTable WHERE Column3 = 'Condition';
-- 모든 작업이 성공적으로 완료되면 트랜잭션을 커밋합니다.
COMMIT TRANSACTION;
-- 만약 오류가 발생하면 트랜잭션을 롤백합니다.
ROLLBACK TRANSACTION;
다음으로 이런 경우도 가능해졌다.
BEGIN TRANSACTION
DELETE dbo.Employee
WHERE EmpID = ‘S0002’
ROLLBACK TRANSACTION
GO
아까는 비슷한 사례가 롤백이 안되었었는데 이제는 롤백 트랜잭션 ( 취소 ) 가 가능하다.
XACT ABORT 옵션에 대해서
명시적 트랜잭션에서 필수로 달고 있어야 하는 것 같다.
주로 DML문에서 많이 쓴다.
대부분의 오류가 트랜잭션을 자동으로 롤백하게 하지만, 모든 종류의 오류가 트랜잭션을 롤백하는 것은 아니다.
예를 들어서 구문오류 같은 일부 오류는 트랜잭션을 롤백하지 않는다.
트랜잭션 중에 발생하는 모든 오류가 트랜잭션을 자동으로 롤백하게 한다.
오류가 발생하면 SQL 서버가 현재 실행 중인 트랜잭션을 즉시 종료하고 이전 상태로 되돌린다.
중요성
오류 처리 간소화
이 옵션을 사용하면 복잡한 오류 처리 로직을 작성할 필요가 없다.
트랜잭션 중 발생하는 어떠한 오류도 자동으로 트랜잭션을 롤백하기 때문이다.
이것은 특히 또또또 데이터 무결성을 유지하는 것에 중요하다.
데이터 무결성 보장
쿼리 오류가 발생하면 모든 변경사항이 롤백되므로, 데이터 베이스는 일관된 상태를 유지한다.
트랜잭션이 발생하는 과정을 살펴보면,
먼저, SQL 서버는 트랜잭션 로그를 남긴다.
다음에 체크포인트마다 실제 데이터에 반영을 한다.
근데! 여기서 롤 포워드 / 롤 백 개념이 나오는데 함 보자
예를 들어서
트랜잭션이 일어났고, 체크포인트를 지나서 별 오류 없이 잘 끝났다.
그러면 체크포인트에서 저장된 이후의 내용을 트랜잭션 로그를 참고해서 마저 진행한다.
트랜잭션이 일어났고 체크포인트를 지났는데 갑자기 시스템 정지와 같은 상황이 벌어져서 잘 안끝났다.
그렇게 되면 체크포인트 이후의 반영은 안된 것이기 때문에, 트랜잭션 로그를 참고해서 다시 롤백한다.
지금 트랜잭션 모드가 3개 나왔자나
1. 자동 커밋 트랜잭션 ( default )
A. SQL SERVER가 알아서..
B. DELETE 특히 취소 안댐
2. 명시적 트랜잭션
A. SET XECT_ABORT ON은 거의 여기선 필수인듯
3. 묵시적 트랜잭션
A. 자동 커밋 트랜잭션과 정반대 되는 개념이다.
B. 자동 커밋 트랜잭션 모드에서 DML 문을 수행하면 SQL SERVER가 자동으로 커밋해버려서 취소가 안된다.
C. 하지만! 묵시적 트랜잭션 모드에서는 DML문을 수행한 이후에 커밋과 롤백을 사용자가 결정한다!
트랜잭션과 락은 깊은 연관 관계를 가진다.
기본적으로 운영체제든 뭐던 간에 항상!! 항상!!! 동기화가 어려웠다. 스핀락이었나 그것도 그런 내용 같았는데 뭐 어쨋든..
ㄴ 맞다 히힣.. 기억이 좀 남아있긴한가보네
어쨋든 다시 돌아가서
이번에 잠금에 대해서 알아보게따.
요약)
공유잠금 S는 읽을때
단독잠금 X는 변경할때
공유잠금(S)이란 누가 읽고 있을 때 그 내용에 대해서 단독 잠금(X)를 못걸게 한다. 근데 공유잠금은 걸 수 있다.. 읽을 수 있다는 것이당
말로 좀 풀어서 상식적으로 생각해보면, 읽고 있는데 읽고 있는 내용을 누가 변경은 못한다는 것이다.
그 다음은 단독잠금 (X) 인데 단독 잠금은 데이터를 변경할때 거는 것이다.
1. 일단 단독잠금이 걸린 데이터는 다른 트랜잭션이 공유잠금을 걸 수 없다!!
2. 단독 잠금도 못건다!!! ( 오직 트랜잭션 하나만이 데이터에 대한 단독 잠금을 걸 수 있다 )
그라믄 좀 너무하지 않는가 바꾸고 있는거 읽을 수는 있게 해줄 수 있지 않는가
그래서 준비했다!
1. 잠금 힌트
2. 트랜잭션 격리수준으로 그걸 가능케!
그래서 어떻게 하는지 책에 안나와있어서 GPT로 좀 파보자.
1. 잠금힌트
A. 잠금힌트를 사용하면 SQL서버의 기본 잠금 동작을 오버라이드 하는 것이다.
B. 예를 들어서 NOLOCK 힌트를 사용하면 ( 이게 힌트라기 보다는 무슨 꼬리표 같은 느낌이네 ) 다른 트랜잭션이 단독 잠금을 가지 ㄴ데이터를 읽을 수 있다. 하지만 이 방법은 ‘더러운 읽기’(Dirty Read)를 발생시킬 수 있기 때문에 주의가 필요하다.
C. 어떻게 쓰는지 함 보자
i. SELECT * FROM Employees WITH (NOLOCK)
D. 아아 그 더러운 읽기 먼저 알아보자
E. 더티 읽기는 데이터 베이스에서 트랜잭션 처리과정 중에 발생할 수 있는 현상인데, 한 트랜잭션이 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 경우에 발생한다. 근데 더티까지는 아닌 것 같은데 더티라고 부르는 이유는 읽은 데C774ㅓ가 최종적으로 데이터 베이스에 반영되지 않을 수도 있기 때문이다.
F. 더러운 읽기의 예시를 알아보자
트랜잭션 A : 얘는 데이터를 수정하는중
BEGIN TRANSACTION
UPDATE Employees SET Salary = Salary + 5000 WHERE EmployeeID = 1;
( 아직 커밋 안함 )
트랜잭션 B : 얘는 동시에 실행중인 트랜잭션인데 읽으려나보다
SELECT Salary FROM Employees WHERE EmployeeID = 1;
이 경우에 트랜잭션 B는 아직 커밋을 안한 A의 데이터를 읽는 거기 때문에 (더러운) 걸로 치자.
아아아아아아ㅏㅇ아ㅏ아아 생각도 못한게 있어따.
생각해보니까 트랜잭션 A는 롤백될 수도 있다. 근데 롤백될 수 도 있는데 바꾸고 있는걸 읽게 되면 완전히 낙동강 오리알 될 수 있는거
( 이제 더럽다고 한 게 이해 되따 )
2. 트랜잭션 격리수준
3. 트랜잭션 중요도 수준
A. DEADLOCK_PRIORITY -10 ~ 10
B. DEADLOCK_PRIORITY LOW / NORMAL(default) / HIGH (5)
4. 근데 이것들이 왜 필요할까?
A. 데드락 상태 때문이다.
GO에 대해서 한번 그냥 궁금해져서
SQL은 배치batch를 하나의 단위로 해서 컴파일한다.
배치 내에서 선언된 로컬 변수는 해당 배치 안에서만 유효하다.
스코프 같은 느낌
각 배치는 서로 독립적으로 실행되어 한 배치의 실행이 다른 배치에 영향을 주지 않는다.
그래서 배치가 독립적으로 실행된다는게 병렬로 cpu가 실행하는건지가 궁금해져따
근데 그건 아니라고 하고
데이터베이스 안에서 별도의 실행단위로 처리된다는 것을 나타낸다고 한다.
하나의 배치가 완전히 실행되고 나면 다음 배치가 실행되며
각 배치는 서로 독립적인 컴파일과 실행 컨텍스트를 가진다.
SQL SERVER에서 배치 간의 독립적 실행이 의미하는 것은, 각 배치가 데이터베이스 엔진에 의해서 별도로 컴파일되고 실행된다는 것을 의미한다.
하나의 배치 안에서 실행된 명령은 다른 배치의 실행과는 별개로 관리된다.
이것은 배치 내에서 선언된 변수나 임시 테이블 등이 다른 배치와 공유되지 않음을 의미한다.
즉! 내가 생각했던 병렬 프로그래밍을 SQL SERVER에서는 사용하지 않는다!
다만, 쿼리 실행계획의 일부로 병렬처리를 사용할 수 있다고 한다.
데드락
세션
개요
SQL SERVER에서의 세션은 클라이언트 어플리케이션과 데이터베이스 서버 간의 연결을 의미함
세션은 사용자의 로그인부터 로그아웃까지, 또는 연결이 시작되어서 종료될 때까지의 지속되는 대화나 상호작용의 기간을 나타낸다.
각 세션은 고유한 세션 ID로 식별되며, SQL SERVER는 이를 통해서 동시에 여러 클라이언트의 요청을 처리할 수 있다.
세션의 특징 및 고유성
고유성
각 세션은 고유한 세션 ID ( @@SPID ) 를 가지며, 이를 통해 개별 클라이언트와의 상호작용을 관리한다.
상태유지성
세션은 클라이언트와 SQL SERVER 간의 상태를 유지한다. 예를 들어서, 세션 내에서 선언도니 변수나 트랜잭션 상태는 해당 세션에서만 유효
리소스관리
SQL SERVER는 각 세션에 할당된 리소스 ( 메모리, 잠금 등 )을 관리한다.
세션 종료시에 해당 세션에 할당된 모든 리소스가 자동으로 해제된다.
병렬처리
동시에 여러 세션을 처리함으로써, SQL SERVER는 다중 사용자 환경에서의 병렬 처리와 고성능을 지원한다.
SQL SERVER에서의 세션관리
세션 생성
클라이언트 어플리케이션이 SQL SERVER에 연결을 요청할 때 세션이 생성된다. 이 과정에서 로그인, 인증, 및 세션 초기화가 수행된다.
세션은 T-SQL 명령을 실행하고 결과를 클라이언트에 반환한다.
세션동안 여러 T-SQL 명령을 실행할 수 있으며, 각 명령은 독립적으로 또는 트랜잭션의 일부로 처리될 수 있다.
세션종료
클라이언트 어플리케이션이 연결을 종료하거나, 네트워크 오류 등으로 세션이 끊어지면, SQL Server는 세션을 종료하고, 해당 세션에 할당된 모든 리소스를 정리한다.
세션과 관련된 T-SQL 명령
@@ SPID : 시스템 전역변수 : 현재 세션의 세션 ID
KILL 세션 아이디 : 지정된 세션 ID의 세션을 강제로 종료함
트랜잭션 격리수준 ( Transaction Isolation Level )
SET TRANSACTION ISOLATION LEVEL ~~~
BEGIN TRANSACTION
END TRANSACTION
이 단어 잘 살펴보면 ACID 성질의
I가 들어가 있다. 그만큼 중요하다는거.
일단 SQL SERVER에서의 트랜잭션 격리수준이라는게 뭘 말하는 걸까.
트랜잭션의 실행 중 다른 트랜잭션으로부터 데이터를 어느정도로 보호할지 결정하는 설정이다.
격리수준은 데이터의 정확성과 동시성 사이의 균형을 조정하는데 사용된다.
다중 트랜잭션 중 발생할 수 있는 다양한 사고들
더티읽기
비반복읽기
팬텀읽기
SQL SERVER는 다섯가지 트랜잭션 격리수준을 지원한다.
SET TRANSACTION ISOLATION LEVEL
READ UNCOMMITTED
GO
SELECT * FROM dbo.Employee
WHERE EmpID = ‘S0001’
GO
트랜잭션 격리수준을 설정할건데, READ COMMITTED로 설정할거야.
가장 낮은 격리수준이고, 더티리드가 가능해. 보고 있는 와중에 롤백하게 되버리면 다른 결과를 보는거야
트랜잭션은 확실히 락에 들어오니까 어렵다.
한번 다시 정리해보자.
일단 락은 읽기 - 공유락S, 쓰기 - 단독락X이 있고, IX, IS, SIX를 적절히 활용해서 잠금된 데이터에 대한 식별 속도를 높인다.
알아두어야 할 것은
1. 트랜잭션 격리수준
SET TRANSACTION ISOLATION LEVEL ~~ 격리수준
A. READ UNCOMMITTED
i. Dirty Read 가능
ii. non-repeatable read 가능
iii. phontom read 가능
B. READ COMMITTED ( default )
i. Dirty Read 불가능 (당연히)
ii. non-Repeatable Read 불가능
iii. phantom read 가능
C. REPEATABLE READ
i. Phantom Read 가능
ii. non-Repeatable Read 불가능
D. SNAPSHOT
i. 트랜잭션이 시작될 때의 데이터 스냅샷을 기반으로 작업을 수행함
ii. 비반복 읽기와 팬텀읽기를 모두 방지하고, 동시에 동시성을 높인다.
E. SERIALIZABLE
i. 가장 높은 격리수준
ii. 트랜잭션이 읽거나 수정한 모든 데이터에 잠금을 걸어 다른 트랜잭션의 접근을 완전히 차단
iii. 동시성이 가장 낮지만, 데이터의 일관성과 정확성이 가장 높게 유지된다.
2. 테이블 힌트
쿼리문을 작성할때 FROM 절에 오는 테이블 이름 다음에 WITH 구문으로 옵션을 설정한다.
원래 쿼리 최적화기가 자동으로 하는 기능인데, 사용자가 강제로 원하는 형태로 하겠다는 것이다.
A. 잠금힌트
B. .... 이것저것 있는데 여기서는 잠금 힌트만 다룬다.
3. 좋지 않은 것들
A. Dirty Read
i. 커밋되지 않은 내용을 읽는 것
ii. 성능은 높으나, 단점은 당연히 위험하겠지. 불확실한 데이터인데
B. Phantom Read
i. 한 트랜잭션 내에서 쿼리를 두번 실행했을 때 첫번째 쿼리 실행과 두번째 쿼리 실행 사이에 다른 트랜잭션이 새로운 데이터를 삽입하거나 삭제하여 두 쿼리 결과가 다르게 나타내는 현상
ii. 예시
1. 트랜잭션 a가 특정 조건을 만족하는 모든 행을 조회한다.
2. 트랜잭션 b가 같은 조건을 만족하는 새로운 행을 삽입한 후 커밋한다.
3. 트랜잭션 a가 그 다음에 다시 같은 조건으로 쿼리를 실행했을 때, 새로 삽입된 행이 포함된 결과를 얻게 된다.
4. 결론적으로 같은 쿼리인데 다른 결과가 나오는거.
C. Non-Repeatable read
i. 일어나는 이유는 같은 데이터 행의 값 변경으로 인해서 발생한다.
4. 팬텀(유령)읽기와 비반복읽기가 헷깔린다.
A. 공통점은 두 현상모두 한 트랜잭션 내에서 데이터의 일관성을 유지하는데 문제를 일으킬 수 있으며, 다중 트랜잭션 환경에서 발생한다는 것
B. 차이점은
i. 비반복 읽기는 같은 데이터 행의 값 변경으로 인해서 발생하는 반면에
ii. 팬텀읽기는 쿼리 결과집합의 행 자체가 변경(추가나 삭제) 되어 발생한다.
iii. 정리하면 비반복 읽기는 데이터 값의 변경에 초점을 맞추고
iv. 팬텀읽기는 결과 집합의 구성 변경에 초점을 맞춘다.