격리 수준을 지정할 수 있도록 트랜잭션 내에서 실행하는 읽기 쿼리가 있습니다. 쿼리가 완료되면 어떻게해야합니까?
- 트랜잭션 커밋
- 트랜잭션 롤백
- 아무 작업도하지 않음 (사용 블록이 끝날 때 트랜잭션이 롤백 됨)
각각의 의미는 무엇입니까?
using (IDbConnection connection = ConnectionFactory.CreateConnection())
{
using (IDbTransaction transaction = connection.BeginTransaction(IsolationLevel.ReadUncommitted))
{
using (IDbCommand command = connection.CreateCommand())
{
command.Transaction = transaction;
command.CommandText = "SELECT * FROM SomeTable";
using (IDataReader reader = command.ExecuteReader())
{
// Read the results
}
}
// To commit, or not to commit?
}
}
편집 : 문제는 트랜잭션을 사용해야하는지 또는 트랜잭션 수준을 설정하는 다른 방법이 있는지 여부가 아닙니다. 문제는 아무것도 수정하지 않는 트랜잭션이 커밋되거나 롤백된다는 차이가 있는지 여부입니다. 성능 차이가 있습니까? 다른 연결에 영향을 줍니까? 다른 차이점이 있습니까?
답변
당신은 커밋합니다. 기간. 다른 현명한 대안은 없습니다. 트랜잭션을 시작한 경우 닫아야합니다. 커밋은 보유하고있을 수있는 모든 잠금을 해제하며 ReadUncommitted 또는 Serializable 격리 수준에서도 똑같이 합리적입니다. 암시 적 롤백에 의존하는 것은 (아마도 기술적으로 동등 할 수 있지만) 형식이 좋지 않습니다.
그것이 당신을 확신하지 못한다면, 당신의 코드 중간에 업데이트 문을 삽입하고 발생하고 그의 데이터를 제거하는 암시 적 롤백을 추적해야하는 다음 사람을 상상해보십시오.
답변
아무것도 변경하지 않은 경우 COMMIT 또는 ROLLBACK을 사용할 수 있습니다. 어느 쪽이든 획득 한 모든 읽기 잠금을 해제하고 다른 변경 사항을 적용하지 않았으므로 동일합니다.
답변
트랜잭션을 시작하면 항상 커밋하는 것이 가장 좋습니다. use (transaction) 블록 내에서 예외가 발생하면 트랜잭션이 자동으로 롤백됩니다.
답변
IMHO 트랜잭션에서 읽기 전용 쿼리를 래핑하는 것이 합리적 일 수 있습니다 (특히 Java에서) 트랜잭션을 “읽기 전용”으로 지정할 수 있으므로 JDBC 드라이버가 쿼리 최적화를 고려할 수 있습니다 (그럴 필요는 없으므로 아무도 INSERT
그럼에도 불구하고 발급하는 것을 막을 것입니다 ). 예를 들어, Oracle 드라이버는 읽기 전용으로 표시된 트랜잭션에서 쿼리에 대한 테이블 잠금을 완전히 방지하여 읽기 중심의 애플리케이션에서 많은 성능을 얻습니다.
답변
중첩 된 트랜잭션을 고려하십시오 .
대부분의 RDBMS는 중첩 트랜잭션을 지원하지 않거나 매우 제한된 방식으로 에뮬레이션을 시도합니다.
예를 들어 MS SQL Server에서 내부 트랜잭션 (실제 트랜잭션이 아닌 MS SQL Server는 트랜잭션 수준 만 계산합니다!)의 롤백은 가장 바깥 쪽 트랜잭션 (실제 트랜잭션) 에서 발생한 모든 것을 롤백합니다 .
일부 데이터베이스 래퍼는 내부 트랜잭션의 롤백을 오류가 발생했다는 신호로 간주하고 가장 바깥 쪽 트랜잭션이 커밋되거나 롤백되었는지 여부에 관계없이 가장 바깥 쪽 트랜잭션의 모든 항목을 롤백 할 수 있습니다.
따라서 COMMIT는 구성 요소가 일부 소프트웨어 모듈에서 사용된다는 것을 배제 할 수없는 안전한 방법입니다.
이것은 질문에 대한 일반적인 대답입니다. 코드 예제는 새 데이터베이스 연결을 열어 외부 트랜잭션 문제를 영리하게 해결합니다.
성능 관련 : 격리 수준에 따라 SELECT에 다양한 수준의 LOCK 및 임시 데이터 (스냅 샷)가 필요할 수 있습니다. 트랜잭션이 닫히면 정리됩니다. 이것이 COMMIT 또는 ROLLBACK을 통해 수행되는지 여부는 중요하지 않습니다. 사용 된 CPU 시간에는 미미한 차이가있을 수 있습니다. COMMIT는 ROLLBACK (두 문자 미만) 및 기타 사소한 차이보다 구문 분석이 더 빠릅니다. 분명히 이것은 읽기 전용 작업에만 해당됩니다!
완전히 요구되지 않음 : 코드를 읽을 수있는 다른 프로그래머는 ROLLBACK이 오류 조건을 의미한다고 가정 할 수 있습니다.
답변
참고로 다음과 같이 코드를 작성할 수도 있습니다.
using (IDbConnection connection = ConnectionFactory.CreateConnection())
using (IDbTransaction transaction = connection.BeginTransaction(IsolationLevel.ReadUncommitted))
using (IDbCommand command = connection.CreateCommand())
{
command.Transaction = transaction;
command.CommandText = "SELECT * FROM SomeTable";
using (IDataReader reader = command.ExecuteReader())
{
// Do something useful
}
// To commit, or not to commit?
}
그리고 구조를 조금만 변경하면 IDataReader에 대한 using 블록도 맨 위로 이동할 수 있습니다.
답변
SQL을 저장 프로 시저에 넣고이를 쿼리 위에 추가하는 경우 :
set transaction isolation level read uncommitted
그러면 C # 코드에서 험난한 작업을 수행 할 필요가 없습니다. 저장 프로 시저에서 트랜잭션 격리 수준을 설정해도 해당 연결의 모든 향후 사용에 설정이 적용되지는 않습니다 (연결이 풀링되기 때문에 다른 설정에 대해 걱정해야 할 사항 임). 저장 프로 시저의 끝에서 연결이 초기화 된 상태로 돌아갑니다.
![](http://daplus.net/wp-content/uploads/2023/04/coupang_part-e1630022808943-2.png)