읽기 트랜잭션을 커밋하거나 롤백해야합니까?
격리 수준을 지정할 수 있도록 트랜잭션 내에서 실행하는 읽기 쿼리가 있습니다. 쿼리가 완료되면 어떻게해야합니까?
- 트랜잭션 커밋
- 트랜잭션 롤백
- 아무 작업도하지 않음 (사용 블록이 끝날 때 트랜잭션이 롤백 됨)
각각의 의미는 무엇입니까?
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 블록도 맨 위로 이동할 수 있습니다.
If you put the SQL into a stored procedure and add this above the query:
set transaction isolation level read uncommitted
then you don't have to jump through any hoops in the C# code. Setting the transaction isolation level in a stored procedure does not cause the setting to apply to all future uses of that connection (which is something you have to worry about with other settings since the connections are pooled). At the end of the stored procedure it just goes back to whatever the connection was initialized with.
ROLLBACK is mostly used in case of an error or exceptional circumstances, and COMMIT in the case of successful completion.
We should close transactions with COMMIT (for success) and ROLLBACK (for failure), even in the case of read-only transactions where it doesn't seem to matter. In fact it does matter, for consistency and future-proofing.
A read-only transaction can logically "fail" in many ways, for example:
- a query does not return exactly one row as expected
- a stored procedure raises an exception
- data fetched is found to be inconsistent
- user aborts the transaction because it's taking too long
- deadlock or timeout
If COMMIT and ROLLBACK are used properly for a read-only transaction, it will continue to work as expected if DB write code is added at some point, e.g. for caching, auditing or statistics.
Implicit ROLLBACK should only be used for "fatal error" situations, when the application crashes or exits with an unrecoverable error, network failure, power failure, etc.
Given that a READ does not change state, I would do nothing. Performing a commit will do nothing, except waste a cycle to send the request to the database. You haven't performed an operation that has changed state. Likewise for the rollback.
You should however, be sure to clean up your objects and close your connections to the database. Not closing your connections can lead to issues if this code gets called repeatedly.
If you set AutoCommit false, then YES.
In an experiment with JDBC(Postgresql driver), I found that if select query breaks(because of timeout), then you can not initiate new select query unless you rollback.
In your code sample, where you have
// Do something useful
Are you executing a SQL Statement that changes data ?
If not, there's no such thing as a "Read" Transaction... Only changes from an Insert, Update and Delete Statements (statements that can change data) are in a Transaction... What you are talking about is the locks that SQL Server puts on the data you are reading, because of OTHER transactions that affect that data. The level of these locks is dependant on the SQL Server Isolation Level.
But you cannot Commit, or ROll Back anything, if your SQL statement has not changed anything.
If you are changing data, then you can change the isolation level without explicitly starting a transation... Every individual SQL Statement is implicitly in a transaction. explicitly starting a Transaction is only necessary to ensure that 2 or more statements are within the same transaction.
If all you want to do is set the transaction isolation level, then just set a command's CommandText to "Set Transaction Isolation level Repeatable Read" (or whatever level you want), set the CommandType to CommandType.Text, and execute the command. (you can use Command.ExecuteNonQuery() )
NOTE: If you are doing MULTIPLE read statements, and want them all to "see" the same state of the database as the first one, then you need to set the isolation Level top Repeatable Read or Serializable...
Do you need to block others from reading the same data? Why use a transaction?
@Joel - My question would be better phrased as "Why use a transaction on a read query?"
@Stefan - If you are going to use AdHoc SQL and not a stored proc, then just add the WITH (NOLOCK) after the tables in the query. This way you dont incur the overhead (albeit minimal) in the application and the database for a transaction.
SELECT * FROM SomeTable WITH (NOLOCK)
EDIT @ Comment 3: Since you had "sqlserver" in the question tags, I had assumed MSSQLServer was the target product. Now that that point has been clarified, I have edited the tags to remove the specific product reference.
I am still not sure of why you want to make a transaction on a read op in the first place.
참고URL : https://stackoverflow.com/questions/309834/should-i-commit-or-rollback-a-read-transaction
'program tip' 카테고리의 다른 글
iOS 버전 6.0에서 더 이상 사용되지 않는 최소 글꼴 크기 (0) | 2020.09.04 |
---|---|
비동기 / 대기 대 스레드 (0) | 2020.09.04 |
Ruby의 번 들러 / Perl의 상자에 해당하는 Python은 무엇입니까? (0) | 2020.09.04 |
API 문서 함수 매개 변수를 해석하는 방법은 무엇입니까? (0) | 2020.09.04 |
생성자 이니셜 라이저에서 멤버 배열 초기화 (0) | 2020.09.04 |