거래가 원자 적이라는 사실을 이해하는 방법에 대해 정말 혼란 스럽습니다. 트랜잭션이 “쿼리”로 설정되어 있으면 어떻게 원자적일 것입니다. 저는 “쿼리”라는 단어를 일반적인 SQL 쿼리와 관련시킵니다. 따라서 트랜잭션은 동시에 실행되는 SQL 쿼리 집합에 지나지 않습니다. 그러나 각 쿼리가 여러 작업을 수행한다는 사실은 이후 쿼리에서 오류가 발생하는 경우 이전에 실행 된 쿼리 (동일한 집합에서)가 어떻게 롤백되는지 실제로 알 수 없습니다. 내가 여기서 무엇을 놓치고 있습니까? 감사합니다!
답변
TL; DR; 트랜잭션 로그에는 트랜잭션에 대한 커밋 레코드가 포함되어 있는지 여부에 따라 각 트랜잭션을 다시 생성하거나 실행 취소하는 데 필요한 모든 정보가 포함되어 있습니다.
SQL 데이터베이스에서 트랜잭션 원자 성은 다음을 사용하여 가장 자주 구현됩니다. 미리 쓰기 로깅 (트랜잭션 로그 항목이 실제 테이블과 인덱스가 업데이트되기 전에 기록됨을 의미)
엄격한 의미의 쿼리, 즉 SELECT
문 및 데이터베이스 상태를 변경하지 않는 기타 읽기 작업은 커밋하거나 롤백 할 항목이 없기 때문에 기록되지 않습니다. 따라서 원 자성 개념은 여기에 실제로 적용되지 않습니다. 적어도 DBMS 수준에서. 쿼리 결과를 사용하는 애플리케이션은 후속 쿼리 중 하나가 실패하여 롤백을 유발하는 경우 이전 쿼리의 결과를 삭제하여 원 자성을 적용해야 할 수 있습니다.
DML 문 (INSERT
, UPDATE
, DELETE
, MERGE
) 및 데이터베이스 상태를 변경하는 기타 문은 실행되면 변경 사항이 먼저 WAL (Write-Ahead Log)에 기록됩니다. 모든 문이 성공하고 커밋 (명시 적 또는 암시 적)이 실행되면이 사실이 WAL에도 기록되고 로그가 유지됩니다. 이렇게하면 변경 사항이 지속됩니다. 나중에 체크 포인트 또는 로그 재생 중에 실제 테이블 및 인덱스 세그먼트에 기록 될 수 있습니다.
그러나 명령문 중 하나가 실패하면 로그에 커밋 레코드가 없습니다. 이 트랜잭션과 DBMS는 해당 트랜잭션의 이전 로그 레코드를 사용하여 지금까지 이루어진 테이블 및 인덱스 변경을 취소합니다.
마찬가지로, DBMS 프로세스가 충돌하거나 전원이 꺼지면 작업이 수행되지 않습니다. 진행중인 트랜잭션에 대한 커밋 레코드와 이미 유지되었을 수있는 테이블 또는 인덱스 변경 사항은 로그 재생 중에 취소됩니다.
댓글
- 정확하지 않음 ' : " 엄격한 의미의 쿼리, 즉 SELECT 문 및 기타 읽기 작업 데이터베이스 상태를 변경하지 않고 커밋하거나 롤백 할 것이 없기 때문에 기록되지 않습니다. "-데이터베이스 설정에 따라 SELECT조차도 암시 적 tr을 시작할 수 있습니다. ansaction. brentozar.com/archive/2018/02/ …
- 나 ' 그들이 ' 거래 통제하에 있지 않다고 말하는 것이 아니라 ' 아무것도 변경하지 않으면 기록되지 않습니다.
답변
트랜잭션은 다음과 같이 캡슐화 될 때 원자 적입니다. 이것은 :
BEGIN TRAN UPDATE dbo.Users SET Reputation = Reputation + 1 WHERE Id = 26837; UPDATE dbo.Posts SET Score = Score + 1 WHERE Id = 227563; COMMIT
이 경우 두 개의 개별 테이블에 대한 두 업데이트가 함께 커밋되거나 함께 롤백 (실패)됩니다. 원자 성은 이것은 커밋 할 트랜잭션의 가장 작은 단위입니다.
그러나 나중에 해당 범위 밖에서 별도의 쿼리를 실행하려고하면 별도의 트랜잭션이됩니다.
다음과 같은 것을 시도하면 :
BEGIN TRAN UPDATE dbo.Users SET Reputation = Reputation + 1 WHERE Id = 26837;
그런 다음 애플리케이션에서 C # 코드와 같은 다른 종류의 작업을 수행 한 다음 데이터베이스로 돌아옵니다. 나중에 다음을 수행하십시오.
UPDATE dbo.Posts SET Score = Score + 1 WHERE Id = 227563; COMMIT
그러면 이전 사용자 업데이트와 후속 게시물 업데이트가 모두 함께 성공하거나 실패합니다.
그러나 실제로는 다음과 같은 거래를 보류 할 수 없습니다. 다른 사람들이 데이터베이스에서 작업하는 것을 차단하기 때문입니다. 그렇기 때문에 “거래를 짧고 달콤하게 유지하십시오”와 같은 조언을 자주 보게 될 것입니다. 트랜잭션을 명시 적으로 보류하지 마십시오.
댓글
- 트랜잭션은 항상 원자 적이며 ' 그렇습니까?
- 예,하지만 데이터베이스 설정에 따라 암시 적 트랜잭션이 켜져있을 수 있습니다. 즉, ' BEGIN TRAN을 요청하지 않아도 ' 얻습니다. 공급 업체에 따라 다릅니다. 예를 들어 Oracle은 암시 적 트랜잭션을 기본값으로 사용하지만 SQL Server는 그렇지 않습니다.Oracle 배경에서 온 경우 ' SQL Server에서 여러 트랜잭션을 가져 오는 경우 트랜잭션이 하나만 발생한다고 생각할 수 있습니다. 각 트랜잭션은 원자 적입니다.
li>