항상 거래를 만드는 것은 나쁜 습관입니까?


88

항상 거래를 만드는 것은 나쁜 습관입니까?

예를 들어 단 하나의 단순한 트랜잭션 만 생성하는 것이 좋습니다 SELECT.

실제로 필요하지 않은 트랜잭션을 작성하는 비용은 얼마입니까?

와 같은 격리 수준을 사용하더라도 READ UNCOMMITTED나쁜 습관입니까?


1
BEGIN TRAN SELECT ... COMMITvs의 영향을 살펴보면 성능 차이 SELECT극히 미미한 것으로 보입니다 .
Martin Smith

답변:


100

항상 거래를 만드는 것이 나쁜 습관입니까?

여기서 말하는 내용에 따라 다릅니다. 업데이트 인 경우 TRANSACTIONS를 명시 적으로 사용하는 것이 좋습니다. SELECT 인 경우 NO (명시 적으로)입니다.

그러나 먼저 이해해야 할 것이 더 있습니다. SQL 서버의 모든 것이 트랜잭션에 포함되어 있습니다.

세션 옵션을 사용하는 경우 IMPLICIT_TRANSACTIONS입니다 OFF당신은 명시 적으로 지정 begin tran하고 commit/rollback다음이가 흔히 알려져 있습니다 명시 적 트랜잭션 . 그렇지 않으면 자동 커밋 트랜잭션이 발생합니다.

하면 IMPLICIT_TRANSACTIONS된다 암시 적 트랜잭션이 책 온라인 기사 (예에서 설명하는 문장 유형 중 하나를 실행할 때 자동으로 시작됩니다 / / ) 그리고 노력으로 또는 명시 적으로 롤백해야합니다. 이 모드에서 a 를 실행하면 다른 "중첩 된"트랜잭션 이 증가 하고 시작됩니다)ONSELECTUPDATECREATEBEGIN TRAN@@TRANCOUNT

사용중인 모드를 전환하려면

SET IMPLICIT_TRANSACTIONS ON

또는

SET IMPLICIT_TRANSACTIONS OFF

select @@OPTIONS & 2

위의 값이 2를 반환하면 암시 적 트랜잭션 모드입니다. 0을 반환하면 자동 커밋에있는 것입니다.

실제로 필요하지 않을 때 거래를 만드는 데 드는 비용은 얼마입니까?

데이터베이스를 일관성있는 한 상태에서 다른 일관성있는 상태로 가져 오려면 트랜잭션이 필요합니다. 거래에 대한 대안이 없기 때문에 거래에는 비용이 없습니다. 참조 : 행 버전 관리 기반 격리 수준 사용

격리 수준 read_uncomitted를 사용하더라도 나쁜 습관입니까? 잠금에는 문제가 없어야합니다.

READ_UNCOMMITED 격리 수준은 정의에 의한 더티 읽기를 허용합니다. 즉, 한 트랜잭션이 다른 트랜잭션에 의해 커밋되지 않은 변경 사항을 볼 수 있습니다. 이 격리 수준의 역할은 잠금의 오버 헤드를 완화하여 데이터베이스 동시성을 보호하기 위해 잠금을 획득하는 방법입니다.

연결 / 쿼리 수준에서 사용할 수 있으므로 다른 쿼리에는 영향을 미치지 않습니다.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Jeff Atwood가 Dining Philosophers Puzzle로 인한 교착 상태와 읽기 커밋 된 스냅 샷 격리 수준을 설명 하는 흥미로운 기사 를 찾았 습니다 .

편집하다:

호기심으로, 아래 그래프와 같이 Log Bytes Flushed / Sec, Log Flush Waits / Sec (LOG 플러시 대기중인 초당 커밋 수)와 같은 Perfmon 카운터를 사용하여 T-log에 미치는 영향을 아래 그래프와 같이 테스트했습니다.

여기에 이미지 설명을 입력하십시오

샘플 코드 :

create table testTran (id int, Name varchar(8))
go

-- 19 sec
-- Autocommit transaction
declare @i int
set @i = 0
while @i < 100000
begin 
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
---------------------------------------------------
-- 2 sec
-- Implicit transaction
SET IMPLICIT_TRANSACTIONS ON
declare @i int
set @i = 0
while @i < 100000
begin 
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
COMMIT;
SET IMPLICIT_TRANSACTIONS OFF


----------------------------------------------------
-- 2 sec
-- Explicit transaction
declare @i int
set @i = 0
BEGIN TRAN
WHILE @i < 100000
Begin
INSERT INTO testTran values (1,'Kin Shah')
set @i = @i+1
End
COMMIT TRAN

자동 커밋 거래 : (@TravisGan에 의해 강조 표시된대로 편집 됨)

  • 삽입하는 데 19 초가 걸렸습니다.
  • 모든 자동 커밋은 자동 커밋으로 인해 디스크에 T-log 버퍼를 플러시합니다 (@TravisGan이 강조 표시되고 언급하지 않은 경우).
  • 플러시해야하는 더티 로그 버퍼의 양이 자주 조용해 지므로 CHECKPOINT 프로세스는 빠르게 완료됩니다.

묵시적 및 명시 적 거래 :

  • 삽입하는 데 2 ​​초가 걸렸습니다.
  • EXPLICIT 트랜잭션의 경우 로그 버퍼가 가득 찼을 때만 플러시됩니다.
  • 자동 커밋 트랜잭션과 달리 EXPLICIT 트랜잭션에서 CHECKPOINT 프로세스는 플러시 할 로그 버퍼가 더 많기 때문에 시간이 더 오래 걸립니다 (로그 버퍼가 가득 찼을 때만 플러시 됨).

데이터베이스 레벨에서 트랜잭션에 대한 정보를 리턴 하는 DMV sys.dm_tran_database_transactions 가 있습니다.

분명히, 이것은 영향을 보여주는 더 간단한 테스트입니다. 디스크 하위 시스템, 데이터베이스 자동 증가 설정, 데이터베이스의 초기 크기, 동일한 서버 \ 데이터베이스에서 실행되는 다른 프로세스 등과 같은 다른 요소도 영향을 미칩니다.

위의 테스트에서 암시 적 트랜잭션과 명시 적 트랜잭션 사이에는 거의 차이가 없습니다.

답변에 더 많은 것을 추가하는 데 도움을 주신 @TravisGan에게 감사합니다.


35

SQL 문은 항상 트랜잭션에서 실행됩니다. 명시 적으로 시작하지 않으면 모든 SQL 문이 자체 트랜잭션으로 실행됩니다.

하나의 트랜잭션에 여러 명령문을 묶을 지 여부 만 선택할 수 있습니다. 여러 명령문에 걸친 트랜잭션은 동시성을 손상시키는 잠금을 남깁니다. 따라서 "항상"트랜잭션을 생성하는 것은 좋은 생각이 아닙니다. 이익과 비용의 균형을 유지해야합니다.


1

문제는 작업 그룹을 단일 작업으로 취급해야하는지 여부입니다. 즉, 모든 작업을 완료하고 커밋해야합니다. 그렇지 않으면 어떤 작업도 커밋 할 수 없습니다. 예비 데이터를 읽고 해당 데이터를 기반으로 업데이트를 수행해야하는 시나리오가있는 경우 초기 읽기는 트랜잭션의 일부 여야합니다. 참고 : 고의로 선택 / 삽입 / 업데이트를 피하고 있습니다. 트랜잭션 범위는 실제로 응용 프로그램 수준에 있으며 여러 데이터베이스 작업이 관련 될 수 있습니다. 비행기 좌석 예약 또는 은행 잔고 조회 / 출금과 같은 고전적인 패턴을 생각해보십시오. 전체 응용 프로그램에서 안정적이고 일관된 데이터를 얻을 수 있도록 문제를보다 넓게 파악해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.