사용자 삽입 이미지

MS-SQL 2008 RC0 한글판이 나와서 집에있는 노트북에 설치를 해 봤다.
시간이 열~~라 오래 걸린다. Virtual PC에 설치하는줄 알았다 완전.. -_-;

그래도 설치하고 나서 이것저것 몇개 해보니 그럭저럭 쓸만하다!
역시 내 노트북!!

MS-SQL 2005 공부도 얼마 못했는데 벌써 2008 출시가 임박해지다니..
얼른얼른 열심히 준비해 봐야겠다~! ^-^

AND


서버 이전작업시 master DB를 그대로 이전한다고 했을때
MS-SQL 2000에서는 대상서버로 master DB를 이전하려면 master DB의 백업본을 가지고 단일 사용자 모드에서 복원하던지
대상서버의 MSSQL 서비스를 중지시킨 다음 원본 서버의 mdf 파일을 복사해 서비스를 시작시키면 기존의 master DB를 사용할 수 있었다.

하지만 이때 master DB에 저장되어 있는 연결된 서버 정보를 그대로 사용할 수 있으므로
이런 정보를 이용하여 다른 서버에 특정 권한으로 접근할 수 있게 된다.
이러한 문제 때문인지 MS-SQL 2005에서 보안이 강화되어 master DB를 사용하기 위한 추가적인 작업이 필요해졌다.

MS-SQL 2005에서는 "서비스 마스터 키" 라는 개념이 도입되었다.
BOL을 보면 "서비스 마스터 키"는 다음과 같이 설명되어 있다.

서비스 마스터 키는 연결된 서버 암호, 인증서 또는 데이터베이스 마스터 키를 처음으로 암호화할 필요가 있을 자동으로 생성됩니다. 서비스 마스터 키는 로컬 시스템 또는 Windows 데이터 보호 API 사용하여 암호화됩니다. API SQL Server 서비스 계정의 Windows 자격 증명으로부터 파생된 키를 사용합니다.

서비스 마스터 키의 암호는 해당 키가 만들어진 서비스 계정이나 해당 서비스 계정의 Windows 자격 증명에 대한 액세스 권한이 있는 보안 주체 의해서만 해독될 있습니다. 따라서 SQL Server 서비스를 실행 중인 Windows 계정을 변경하면 서비스 마스터 키의 암호 해독도 계정으로 활성화해야 합니다.

만일 master DB를 복사해 오거나 복원을 했다면 서비스를 시작했을 때 sp_readerrorlog를 통해 다음과 같은 오류 메시지를 확인할 수 있다.
(사용자 DB도 모두 정상적으로 시작되고 언뜻 보기엔 정상으로 보일 수 있다.)

2008-06-06 12:08:08.680 spid4s 오류: 15466, 심각도: 16, 상태: 1.
2008-06-06 12:08:08.680 spid4s An error occurred during decryption.

그리고 연결된 서버를 읽거나 추가/수정/삭제 하려고 하면 다음과 같은 화면을 만나게 된다.
"암호화 해독 중에 오류가 발생했습니다."



이때는 원본 서버에서 서비스 마스터키를 파일로 백업해서 대상 서버에서 복원시키면 정상적으로 암호화된 정보를 이용할 수 있다.

BACKUP SERVICE MASTER KEY TO FILE = 'c:\service_master_key' ENCRYPTION BY PASSWORD = 'password'
RESTORE SERVICE MASTER KEY FROM FILE = 'c:\service_master_key' DECRYPTION BY PASSWORD = 'password' -- [FORCE]

RESTORE시 FORCE 옵션은 서비스 마스터 키 복구로 인해 기존에 생성된 정보가 손실될 수 있는 경우 오류 메시지가 발생하게 되는데
이를 무시하고 적용하겠다는 옵션이다.

이렇게 서비스 마스터 키를 복원하고 나서 MS-SQL 2005 서비스를 재시작하면 sp_readerrorlog에서 오류 메시지가 사라진 것을 확인할 수 있다.

이런 이유로 master DB를 백업할 때 서비스 마스터 키도 함께 백업을 해 두어야
나중에 복구할 이슈가 발생했을 때 master DB의 암호화된 정보를 사용할 수 있을 것 같다.


[별첨] BOL에서 설명하고 있는 보안수준.
SQL Server 수준에서의 최상위 정보가 서비스 마스터 키 이며,
데이터베이스 암호화시도 이 서비스 마스터 키를 이용하여 암호화를 한다고 함.

하만철 / Ha Man cheol

AND

 

CI(Clustered Index) NCI(Non-Clustered Index) 인덱스 상황에 따라 NCI Seek를 어떤식으로 하는지 테스트 해 보았습니다.

 

@@ 테스트 환경

OS : Windws XP Professional

SQL : Microsoft SQL Server 2005 - 9.00.3054.00 (Intel X86)

             Mar 23 2007 16:28:52

             Copyright (c) 1988-2005 Microsoft Corporation

             Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 3)

 

 

--drop table idxTest

create table idxTest (

c1 int

, c2 int

, c3 int

, c4 int

)

 

-- 유니크 CI 한 개를만들고 넌클을1개 만든다.

create unique clustered index idx1 on idxTest (c1, c2)

create index idx3 on idxTest (c3, c4)

 

-- 테스트 데이터 입력

insert into idxTest select 1,1,1,1

insert into idxTest select 2,1,2,1

insert into idxTest select 3,1,3,1

insert into idxTest select 4,1,4,1

insert into idxTest select 5,1,5,1

insert into idxTest select 6,1,6,1

 

set statistics profile on

 

-- NCI 조건을 먼저 넣고, CI조건의 첫번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c1=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)

                           AND [testDB].[dbo].[idxTest].[c1]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- NCI 에서 NCI+CI모두를 가지고 seek 했다. ~ CI의 키가 NCI의 넌리프 레벨에 붙어 있는가보다.!

 

 

-- NCI 조건을 먼저 넣고, CI조건의 두번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c2=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)), 

             WHERE:([testDB].[dbo].[idxTest].[c2]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- CI 키가 NCI 키의 뒤에 순서대로 붙기 때문에 필터절로 빠진다.

 

 

-- CI의 유니크 상태에 따라 다른점이 있는지 확인해 보기 위해 CI에서 유니크를 빼고 다시 걸어 보았다.

drop index idxTest.idx1

create clustered index idx1 on idxTest (c1, c2)

 

 

-- NCI 조건을 먼저 넣고, CI조건의 첫번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c1=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)

                           AND [testDB].[dbo].[idxTest].[c1]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- 역시 NCI 에서 NCI+CI모두를 가지고 seek 했다. 무조건 CI의 키가 NCI의 넌리프에 붙어 있는건가?

 

 

 

-- NCI를 제거 후 유니크를 넣고 다시 걸어 보았다.

drop index idxTest.idx3

create unique index idx3 on idxTest (c3, c4)

 

 

-- 다시 NCI 조건을 먼저 넣고, CI조건의 첫번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c1=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)), 

             WHERE:([testDB].[dbo].[idxTest].[c1]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- 유니크 NCI로 생성하니 NCI의 넌리프에서 CI의 키가 빠진 것 같다.

-- 어차피 유니크니 데이터를 SEEK해서 내려가면 1개의 데이터밖에 없어서 그런 것 같다.

 

 

-- 다시 CI에 유니크를 추가해 보았다.

drop index idxTest.idx1

create unique clustered index idx1 on idxTest (c1, c2)

 

-- 다시 NCI 조건을 먼저 넣고, CI조건의 첫번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c1=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)), 

             WHERE:([testDB].[dbo].[idxTest].[c1]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- 역시 CI의 키에 대해서는 필터처리를 했다.

 

-- 결론!

NCI의 넌리프 레벨에 CI의 키가 붙을지 말지는 NCI의 유니크 상황에 따라 결정이 되는 것 같다.

NCI 가 유니크한 경우 : CI의 키가 NCI의 넌리프레벨에 포함되지 않는다.

NCI 가 유니크하지 않은 경우 : CI의 키가 NCI의 넌리프레벨에 포함된다.



넥슨 DB 팀 ( http://nexondbteam.tistory.com )
하만철 / Ha Man cheol

AND

 

로그파일의 VLF 개수가 성능에 어느정도 영향을 미치는지 간단히 확인해 보았습니다.

테스트는 2개의 DB를 생성하고, VLF 개수를 다르게 한 다음 UPDATE 작업에 걸리는 시간을 측정해 보았습니다.

 

테스트를 위해 두 개의 DB를 생성한 다음 백업을 해서 로그가 잘 쌓이도록 한다.

로그파일 크기는 1MB로 한다.

-- DB 생성

CREATE DATABASE logTest1

ON PRIMARY

(

                                   NAME = logTest1_Data

,                                  FILENAME = 'D:\logTest1_Data_PRIMARY.mdf'

)

LOG ON

(

                                   NAME = logTest1_Log

,                                  FILENAME = 'D:\logTest1_LOG_01.ldf'

,                                  SIZE = 1MB

,                                  FILEGROWTH = 1MB

)

 

-- 백업

BACKUP DATABASE logTest1 TO DISK = 'd:\temp\logTest1.BAK'

 

현재 로그파일 상태를 확인해 보면 4개의 VLF가 생성되어 있는걸 볼 수 있다.

DBCC loginfo

 

FileId : 로그파일의 id

FileSize : VLF의 크기(byte)

StartOffset : 전체 트랜잭션 로그 파일에서의 위치

FSeqNo : VLF Sequence Number.

Status : VLF의 상태(0:비활성, 2:활성VLF)

Parity : 알듯말듯 도대체 뭔지 모르겠다. 나중에 확인해 보자!!!

CreateLSN : 알듯말듯 도대체 뭔지 모르겠다. 나중에 확인해 보자!!!

 

## 로그파일을 증가시킬 때 VLF의 개수는 아래와 같은 공식에 의해 결정된다고 한다.

로그파일 증가크기

VLF 개수

VLF당 크기

1MB 까지

2~4

248KB ~ 334KB

64MB 까지

4

256KB ~ 16MB

1GB 까지

8

8MB ~ 128MB

1GB 초과

16

64MB ~

# 테스트로 테이블 생성시 로그파일 크기를 10GB로 설정했더니 640MB짜리 VLF가 생성되었다.

 

이제 로그파일의 크기를 1MB씩 증가시켜 VLF개수를 마구마구 증가시켜 보도록 한다.

먼저 50개만 만들어 보도록 하자.

DECLARE @i INT

DECLARE @qry VARCHAR(8000)

 

SET @i = 2

 

WHILE @i < 14 BEGIN

                  SET @qry = 'ALTER DATABASE logTest1

                  MODIFY FILE

                  (

                                   NAME = logTest1_Log

                  ,                 Size = ' +CONVERT(VARCHAR(10), @i) + ')'

 

                  EXEC (@qry)

 

                  SET @i = @i + 1

END

 

WHILE문에 의해 12번이 실행되어서 48개의 VLF가 추가되었다.

52개의 VLF가 생성되었고, 로그파일의 전체용량은 13MB가 되었다.

 

그리고 비교 테스트를 위해 logTest2 DB를 생성한 다음 이 DB의 경우 초기 로그파일의 크기를 13MB로 지정하여

VLF 개수를 4개가 되도록 한다.

-- DB 생성

CREATE DATABASE logTest2

ON PRIMARY

(

                                   NAME = logTest2_Data

,                                  FILENAME = 'D:\logTest2_Data_PRIMARY.mdf'

)

LOG ON

(

                                   NAME = logTest2_Log

,                                  FILENAME = 'D:\logTest2_LOG_01.ldf'

,                                  SIZE = 13MB

,                                  FILEGROWTH = 1MB

)

 

-- 백업

BACKUP DATABASE logTest2 TO DISK = 'd:\temp\logTest2.BAK'

 

이제 logTest1, logTest2 두 개의 DB에서 테이블을 하나 생성한 다음 insert, update, delete 작업에 대해 성능차이가 있는지 보도록 하겠다.

-- INSERT Test

-- logTest1 DB에서 시간 확인

USE logTest1

GO

 

-- 테이블 생성

CREATE TABLE t (a INT)

 

-- 데이터 INSERT

DECLARE @i INT

DECLARE @s DATETIME, @e DATETIME

SET @i = 1

 

SET @s = GETDATE()

WHILE @i < 20001 BEGIN

                  INSERT INTO t SELECT @i

                  SET @i = @i + 1

END

SET @e = GETDATE()

 

-- 걸린 시간 측정

SELECT DATEDIFF(ms, @s, @e)

 

Result1> 4063

Result2> 4170

Result3> 4186

 

-- logTest2 DB에서 시간 확인

USE logTest2

GO

 

-- 테이블 생성

CREATE TABLE t (a INT)

 

-- 데이터 INSERT

DECLARE @i INT

DECLARE @s DATETIME, @e DATETIME

SET @i = 1

 

SET @s = GETDATE()

WHILE @i < 20001 BEGIN

                  INSERT INTO t SELECT @i

                  SET @i = @i + 1

END

SET @e = GETDATE()

 

-- 걸린 시간 측정

SELECT DATEDIFF(ms, @s, @e)

 

Result1> 3876

Result2> 3876

Result3> 3890

 

 

-- UPDATE TEST

-- logTest1 DB Test

USE logTest1

GO

 

-- Index 생성

CREATE INDEX idx_t ON t (a)

 

-- Log BACKUP(Update Backup 3 반복했을 걸린 시간)

BACKUP LOG logTest1 TO DISK = 'D:\logTest1.TRN'

GO

파일15에서데이터베이스'logTest1', 파일'logTest1_Log'에대해1254개의페이지를처리했습니다.

BACKUP LOG() 1254개의페이지를0.939초동안처리했습니다(10.935MB/).

 

파일16에서데이터베이스'logTest1', 파일'logTest1_Log'에대해1254개의페이지를처리했습니다.

BACKUP LOG() 1254개의페이지를1.217초동안처리했습니다(8.440MB/).

 

파일17에서데이터베이스'logTest1', 파일'logTest1_Log'에대해1254개의페이지를처리했습니다.

BACKUP LOG() 1254개의페이지를0.795초동안처리했습니다(12.919MB/).

 

-- 데이터UPDATE

DECLARE @i INT

DECLARE @s DATETIME, @e DATETIME

SET @i = 0

 

SET @s = GETDATE()

WHILE @i < 10001 BEGIN

                  UPDATE t SET a=a-1 WHERE a=@i

                  SET @i = @i + 1

END

SET @e = GETDATE()

 

-- 걸린시간측정

SELECT DATEDIFF(ms, @s, @e)

 

Result1> 3906

Result2> 3720

Result3> 3923

 

 

 

-- logTest2 DB Test

USE logTest2

GO

 

-- Index 생성

CREATE INDEX idx_t ON t (a)

 

-- Log BACKUP(Update Backup 3 반복했을 걸린 시간)

BACKUP LOG logTest2 TO DISK = 'D:\logTest2.TRN'

GO

파일11에서데이터베이스'logTest2', 파일'logTest2_Log'에대해1255개의페이지를처리했습니다.

BACKUP LOG() 1255개의페이지를0.653초동안처리했습니다(15.734MB/).

 

파일12에서데이터베이스'logTest2', 파일'logTest2_Log'에대해1255개의페이지를처리했습니다.

BACKUP LOG() 1255개의페이지를0.778초동안처리했습니다(13.205MB/).

 

파일13에서데이터베이스'logTest2', 파일'logTest2_Log'에대해1254개의페이지를처리했습니다.

BACKUP LOG() 1254개의페이지를0.689초동안처리했습니다(14.909MB/).

 

-- 데이터UPDATE

DECLARE @i INT

DECLARE @s DATETIME, @e DATETIME

SET @i = 0

 

SET @s = GETDATE()

WHILE @i < 10001 BEGIN

                  UPDATE t SET a=a-1 WHERE a=@i

                  SET @i = @i + 1

END

SET @e = GETDATE()

 

-- 걸린시간측정

SELECT DATEDIFF(ms, @s, @e)

 

Result1> 3610

Result2> 3673

Result3> 3563

 

 

 

-- DELETE TEST

-- logTest1 DB Test

USE logTest1

GO

 

TRUNCATE TABLE t

 

-- Log BACKUP

BACKUP LOG logTest1 TO DISK = 'D:\logTest1.TRN'

GO

 

-- 데이터INSERT

DECLARE @i INT

SET @i = 1

 

WHILE @i < 20001 BEGIN

                  INSERT INTO t SELECT @i

                  SET @i = @i + 1

END

 

-- Log BACKUP

BACKUP LOG logTest1 TO DISK = 'D:\logTest1.TRN'

GO

 

 

-- 데이터DELETE

DECLARE @i INT

DECLARE @s DATETIME, @e DATETIME

SET @i = 1

 

SET @s = GETDATE()

WHILE @i < 20001 BEGIN

                  DELETE t WHERE a=@i

                  SET @i = @i + 1

END

SET @e = GETDATE()

 

-- 걸린시간측정

SELECT DATEDIFF(ms, @s, @e)

 

Result1> 5750

Result2> 4983

Result3> 4936

 

 

 

-- logTest2 DB Test

USE logTest2

GO

 

TRUNCATE TABLE t

 

-- Log BACKUP

BACKUP LOG logTest2 TO DISK = 'D:\logTest2.TRN'

GO

 

-- 데이터INSERT

DECLARE @i INT

SET @i = 1

 

WHILE @i < 20001 BEGIN

                  INSERT INTO t SELECT @i

                  SET @i = @i + 1

END

 

-- Log BACKUP

BACKUP LOG logTest2 TO DISK = 'D:\logTest2.TRN'

GO

 

 

-- 데이터DELETE

DECLARE @i INT

DECLARE @s DATETIME, @e DATETIME

SET @i = 1

 

SET @s = GETDATE()

WHILE @i < 20001 BEGIN

                  DELETE t WHERE a=@i

                  SET @i = @i + 1

END

SET @e = GETDATE()

 

-- 걸린시간측정

SELECT DATEDIFF(ms, @s, @e)

 

Result1> 4576

Result2> 4750

Result3> 4690

 

INSERT, UPDATE, DELETE 테스트 결과

 

logTest1

logTest2

VLF 개수

52

4

INT INSERT 2만건시 시간

Result1> 4063 ms

Result2> 4170 ms

Result3> 4186 ms

Result1> 3876 ms

Result2> 3876 ms

Result3> 3890 ms

INT UPDATE 1만건시 시간

Result1> 3906 ms

Result2> 3720 ms

Result3> 3923 ms

Result1> 3610 ms

Result2> 3673 ms

Result3> 3563 ms

UPDATE Log백업 시간

0.939초동안처리(10.935MB/)

1.217초동안처리(8.440MB/)

0.795초동안처리(12.919MB/)

0.653초동안처리(15.734MB/)

0.778초동안처리(13.205MB/)

0.689초동안처리(14.909MB/)

INT DELETE 2만건시 시간

Result1> 5750 ms

Result2> 4983 ms

Result3> 4936 ms

Result1> 4576 ms

Result2> 4750 ms

Result3> 4690 ms

 

 

VLF 개수를 증가시켜서 위와 같은 방법으로 다시 테스트 해 보았더니 아래와 같은 결과가 나타났다.

 

logTest1

logTest2

VLF 개수

500 (로그파일을 1MB씩 증가시켜 생성)

16 (로그파일을 30MB씩 증가시켜 생성)

로그파일 크기

126 MB

120 MB

INT INSERT 20만건시 시간

Result1> 40516 ms

Result2> 40106 ms

Result3> 40826 ms

Result1> 36813 ms

Result2> 36330 ms

Result3> 36686 ms

INTUPDATE 10만건시 시간

Result1> 37703 ms

Result2> 36263 ms

Result3> 36313 ms

Result1> 35953 ms

Result2> 35593 ms

Result3> 34953 ms

UPDATE Log백업 시간

6.512초동안처리(15.736MB/)

6.707초동안처리(15.275MB/)

7.226초동안처리(14.178MB/)

5.386초동안처리(19.021MB/)

5.177초동안처리(19.795MB/)

5.409초동안처리(18.941MB/)

INT DELETE 20만건시 시간

Result1> 49156 ms

Result2> 48860 ms

Result3> 48975 ms

Result1> 45550 ms

Result2> 45750 ms

Result3> 45475 ms

 

 

 

결과적으로 UPDATE에 의해 로그를 쓰는 시간은 약 10%정도 차이가 있었고,

로그백업 작업의 경우처럼 로그파일을 읽을때는 25% 정도 차이가 있었습니다.

로그파일을 읽고 쓸때 로그파일 내에서 똑 같은 수의 VLF들에 대해 랜덤 IO가 발생할텐데

왜 이정도 차이가 발생하는지는 아직 잘 모르겠습니다.

 

 

 

 

 

 

 

 

 

AND

Data까지 스크립트로 생성할 수 있다!! 오~


출처 : http://www.microsoft.com/downloads/details.aspx?FamilyId=56E5B1C5-BF17-42E0-A410-371A838E570A&displaylang=en


Overview

SQL Server Database Publishing Wizard enables the deployment of SQL Server databases into a hosted environment on either a SQL Server 2000 or 2005 server. It generates a single SQL script file which can be used to recreate a database (both schema and data) in a shared hosting environment where the only connectivity to a server is through a web-based control panel with a script execution window. If supported by the hosting service provider, the Database Publishing Wizard can also directly upload databases to servers located at the shared hosting provider.

Optionally, SQL Server Database Publishing Wizard can integrate directly into Visual Studio 2005 and/or Visual Web Developer 2005 allowing easy publishing of databases from within the development environment.

 Top of page

System Requirements

  • Supported Operating Systems: Windows Server 2003; Windows Vista; Windows XP

 Top of page

Instructions


  1. Install any required components from above that have not already been installed
  2. Click the Download button on this page to start the download
  3. Install the SQL Server Database Publishing Wizard by selecting the Run option

 Top of page

Additional Information

For more information, visit the SQL Server Hosting Toolkit project page

 Top of page

 Top of page

AND

그런데 비가 너무 많이 온다..

젠장.. 그 멀리까지 어떻게 간다냐 ㅠ_ㅠ
AND

출처 : http://www.microsoft.com/technet/technetmag/issues/2007/07/SQLQA/default.aspx?rss=http://www.microsoft.com/technet/technetmag/issues/2007/07/SQLQA&loc=ko

SQL Q&A
클러스터링의 작동 원리, 원인을 알 수 없는 지연, SA 계정 외
편집자: Nancy Michell

Q: 클러스터링의 작동 원리에 대해 자세히 알고 싶습니다. SQL Server™ 2005를 실행하는 64비트 Windows Server® 2003, SQL Server Reporting Services(SSRS) 웹 팜(보고서 서버의 수평 확장 배포), SSRS TempDB 카탈로그 서버, 연결된 서버를 통해 타사 데이터베이스에서 데이터를 가져와 SSRS용으로 저장하는 SQL Server로 환경을 구성하려고 합니다.

또한 3노드 액티브/액티브/패시브 클러스터를 사용하려고 합니다. 노드 1은 액티브 노드로 설정하여 타사 데이터베이스에서 가져온 데이터를 저장하고, 노드 2도 액티브 노드로 설정하여 SSRS 카탈로그를 저장하려고 합니다. 마지막으로 노드 3은 패시브 노드로 설정하여 노드 1이나 노드 2에 오류가 발생할 경우 장애 조치용으로 사용하려고 합니다. 도움을 주실 수 있을까요?


A: 안타깝게도 많은 사람들이 SQL Server 클러스터링과 관련하여 액티브/액티브 및 액티브/패시브의 개념을 잘못 이해하고 있는 것 같습니다. 대부분 SQL 클러스터링이 데이터베이스나 SQL 인스턴스 하나를 여러 서버에 "수평 확장"하도록 지원하는 것으로 이해하고 있지만 사실은 그렇지 않습니다. SQL Server에 액티브/액티브 데이터베이스나 인스턴스라는 것은 없습니다. "인스턴스"란 관련 데이터베이스와 함께 설치된 SQL Server를 의미합니다. SQL Server 인스턴스 하나당 지원되는 클러스터링은 액티브(1) 대 패시브(n)입니다. 이때 n은 1에서 7까지의 값이며 설치된 SQL Server 버전에 따라 다릅니다. 바로 이 때문에 SQL Server 클러스터링을 장애 조치 클러스터링이라고 하는 것입니다.

이러한 개념을 이해하고 나면 한 노드 집합에 장애 조치 클러스터링의 여러 인스턴스를 설치하는 것을 고려해 볼 수 있습니다. 예를 들어 공유 디스크를 사용하는 세 개의 물리적 서버가 있는 경우 기본적으로 액티브 상태인 인스턴스 하나를 노드 1에 두고 기본적으로 액티브 상태인 두 번째 인스턴스를 노드 2에 둘 수 있으며, 두 노드 모두 노드 3으로 장애 조치가 이루어지도록 할 수 있습니다. 이 두 인스턴스는 완전히 별개이며 서로 데이터를 공유하지 않으므로 액티브/액티브가 아닙니다. 두 인스턴스는 모두 액티브/패시브며 동일한 장애 조치 인스턴스를 공유합니다. 두 인스턴스 모두 노드 3으로 장애 조치가 수행되는 경우 시간이 경과되면서 이러한 로드로 인해 노드 3의 성능이 저하되는지 확인해야 합니다. 본래 장애 조치는 장애 조치 노드의 처리 성능에 의존합니다. 로드가 가장 많을 때 정상적인 작동 상태에서 처리를 위해 두 개의 노드가 필요하다고 가정할 경우 노드 3은 두 노드에 일반적으로 할당되는 최대 로드를 감당하기가 어렵습니다.

하지만 클러스터를 실행할 수 있는 하드웨어의 가격이 상대적으로 고가인 점을 감안하면 사람들이 두 개의 주 노드에서 동시에 오류가 발생하여 전체 로드를 한 노드에 넘겨야 하는 가능성에 그다지 무게를 두고 있지 않다는 것을 이해할 수 있습니다. 이러한 생각으로 100% 장애 조치 성능을 갖춘 하드웨어를 구입하는 대신 위험을 감수하는 결정을 내리게 되는 것입니다.

몇 가지 좋은 소식도 있습니다. SQL Server 2005는 단일 SAN을 사용하는 클러스터링을 통해 클러스터보다 빠르게 장애 조치를 수행하고 데이터 복사본까지 유지할 수 있는 대체 기술을 포함하여 보다 다양한 HA(고가용성) 옵션을 제공합니다. 이러한 옵션으로는 미러링, 피어 투 피어 복제 등이 있습니다. 이러한 새 대체 기술과 함께, 다양한 HA 기능을 조합할 수 있는 몇몇 기술을 비롯하여 모든 종류의 요구 사항을 충족시킬 수 있는 훨씬 더 다양한 옵션을 사용할 수 있습니다.

이제 Microsoft® Cluster Configuration Validation Wizard(ClusPrep)를 다운로드하여 HCL(Hardware Certification List) 테스팅 대신 사용할 수 있습니다. HCL을 사용하는 경우 구성이 클러스터링에서 지원 가능한지 확인하는 데 몇 달이 소요될 수도 있었습니다. 이제 이 하드웨어 유효성 검사 도구를 통해 DBA는 인증된 하드웨어를 적절히 배치하는 데 드는 시간과 비용을 크게 줄일 수 있게 되었습니다. 이 도구는 이기종 하드웨어의 유효성을 검사하여 이러한 하드웨어를 한 클러스터 노드 집합 내에 배포하는 것도 가능하게 합니다.


Q: 제 컴퓨터 중 하나에서 삭제 프로시저를 실행했는데 12시간이 지난 후에도 완료되지 않고 있습니다. 작업이 차단된 것은 아닙니다. 가장 느린 쿼리 계획을 살펴보니 한 트리거가 87,327초 동안 실행 중인데 이 트리거에서 프로시저가 지연되고 있는 것 같습니다. 어떻게 하면 지연되고 있는 문을 확인할 수 있을까요?


A: 여러 가지 이유로 트리거 내의 루프가 종료되지 않고 있을 가능성이 높습니다. 오랜 시간 동안 작업이 지연되는 경우 현재 실행 중인 문을 보려면 그림 1의 코드를 실행해 보십시오. 그러면 현재 실행 중인 문을 확인할 수 있는데, 이 문으로 인해 컴퓨터가 지연되고 있을 가능성이 큽니다.


Q: 방화벽을 통해 트랜잭션 복제를 지원해야 합니다. 게시자와 배포자는 방화벽 외부에 있고 구독자는 방화벽 내부에 있습니다. 구독자는 1433 포트에서 수신하도록 설정되어 있으며, 컴퓨터 이름은 게시자의 경우 PUBMACHINE, 배포자의 경우 DISTMACHINE, 구독자의 경우 SUBMACHINE입니다. 초기 스냅숏 및 게시 밀어넣기에 성공하려면 어떤 포트를 열어야 합니까?


A: 밀어넣기 구독을 사용하는 경우 배포 에이전트가 배포자 컴퓨터(방화벽 외부)에서 실행되고 스냅숏 에이전트에 의해 생성된 스냅숏 파일에 로컬로 액세스할 수 있으므로 SQL Server 포트(이 경우 1433)만 열어도 충분합니다. 그러나 끌어오기 구독을 사용하는 경우에는 구독자 컴퓨터에서 실행되는 배포자 에이전트가 방화벽을 통해 스냅숏 파일에 액세스할 수 있어야 합니다. 다음과 같은 옵션을 고려할 수 있습니다.

방화벽 외부의 파일 공유에서 스냅숏 파일에 액세스할 수 있다고 가정할 경우, 방화벽을 통해 Windows® 파일 공유 포트를 열어 방화벽 내부에서 실행되는 배포 에이전트가 방화벽 외부에 있는 스냅숏 파일에 액세스하도록 할 수 있습니다. 단, 이 경우 인프라의 다른 부분에서 발생할 수 있는 보안 문제를 고려해야 합니다. 기본 스냅샷 위치(SSMS 기본값)로 로컬 경로를 구성한 경우 배포 에이전트의 /AltSnapshotFolder 옵션을 사용하여 스냅샷 파일 선택 위치를 다시 정의해야 할 수도 있습니다.

스냅샷 파일 전송 시 FTP를 사용하도록 복제를 구성할 수도 있습니다. 이 경우 포트 21을 열어야 합니다.


Q: SQL Server 2005의 SA 계정을 사용하지 않을 경우의 단점과 이렇게 하면 정말로 보안에 도움이 되는지 알고 싶습니다. 이 질문과 관련된 백서가 있을까요?


A: SQL Server 2005를 새로 설치한 경우, 혼합 모드를 사용하지 않으면 SA 계정이 기본적으로 사용되지 않도록 설정되며 이를 위한 임의 암호가 생성됩니다. 이 계정을 사용하지 않도록 직접 설정할 수도 있습니다. 이 질문과 관련된 백서는 없습니다. 하지만 최상의 구현 사례 백서에서 로그인을 사용하지 않도록 설정하거나 이름을 바꾸는 자세한 내용을 볼 수 있습니다.

SA 계정을 손상시키려는 시도로부터 컴퓨터를 보호하려면 계정 이름을 바꿔 보십시오. 단, 사용하지 않도록 설정한 계정을 나중에 사용하는 경우 암호를 새로 설정해야 합니다.

SA 계정을 사용하지 않을 경우 보안에 정말로 도움이 되는지에 대해 말씀드리겠습니다. 이 계정을 사용하지 않음으로써 보안이 개선되는 까닭은 계정이 사용되지 않는 동안에는 암호 추측 시도가 아무런 효과가 없기 때문입니다. 해커나 바이러스가 어떤 방법을 사용하더라도 잠긴 계정에 대한 무작위 공격은 성공하지 못합니다. SA 계정의 이름을 바꾸거나 사용하지 않도록 설정하면 SA 계정을 통해 연결하는 응용 프로그램이 제대로 작동하지 않게 됩니다. 따라서 먼저 이러한 응용 프로그램을 찾아서 수정하거나 제거해야 합니다. 앞에서도 언급했듯이 계정을 다시 사용하도록 설정하기 전까지는 해당 계정으로 데이터베이스에 연결할 수 없습니다. 또한 이전에 인증 절차가 실패했으므로 실패한 시도는 공격받은 시스템에 별로 해가 되지 않습니다.


Q: 대용량 OLTP(Online Transaction Processing) 데이터베이스 중 하나에 데이터 파일 크기의 두 배인 로그 파일이 있습니다. 다음 명령을 사용하여 로그 파일의 크기를 어느 정도 줄였는데 이보다 더 줄이고 싶습니다.

backup database syslogs to backupfile
DBCC SHRINKFILE (syslogs_log)

A: backup database 문을 backup log 문으로 변경해야 합니다. 또는 데이터베이스를 단순 복구 모드로 설정한 다음 shrinkfile 문을 실행할 수도 있습니다. 로그 축소가 끝나면 데이터베이스를 다시 이전 복구 모드로 설정한 다음 데이터베이스를 백업합니다. 이렇게 해도 원하는 크기로 축소되지 않으면 dbcc opentran 문을 사용하여 열려 있는 트랜잭션이 있는지 확인하십시오. 자세한 내용은 다음 기술 자료 문서를 참조하십시오. support.microsoft.com/kb/907511.


Q: 예약된 SQL Server 에이전트 작업 중 장애 조치가 수행될 경우 장애 조치가 끝난 후에 이 작업은 어떻게 됩니까? 수동으로 다시 시작해야 합니까?


A: 다른 프로세스가 실행 중인 경우가 아니면 작업을 수동으로 시작해야 합니다. 작업을 수동으로 다시 시작하지 않으려면 작업 완료 시 테이블을 업데이트하는 스크립트를 작성해 보십시오. 값이 1이면 작업이 실행되었음을 나타내고, 값이 1이 아니면 작업이 완료되지 않았으며 나중에 두 번째 작업이 발생하고 시작 명령을 실행함을 나타냅니다. 따라서 작업이 실행되는 동안 장애 조치가 수행되어 작업을 다시 실행해야 하는 경우 스크립트를 작성하면 다음 업무일 이전에 반드시 완료되어야 하는 중요한 야간 작업에 대해 염려할 필요가 없습니다.

팁: 업그레이드 및 DBCC UPDATEUSAGE

SQL Server 2000에서 SQL Server 2005로 업그레이드할 계획입니까?

그렇다면 데이터베이스를 업그레이드한 후 바로 DBCC UPDATEUSAGE를 실행하십시오.

DBCC UPDATEUSAGE는 카탈로그 뷰의 잘못된 페이지 및 행 개수를 보고하고 수정합니다. 정확하지 않은 수치가 있으면 sp_spaceused 시스템 저장 프로시저가 잘못된 공간 사용률 보고서를 반환할 수 있으므로 반드시 수정해야 합니다. SQL Server 2005에서는 이러한 값이 항상 올바르게 유지되므로 데이터베이스에서 잘못된 개수가 발견되는 일이 없습니다. 그러나 SQL Server 2005로 업그레이드된 데이터베이스에는 잘못된 개수가 포함될 수 있으므로 업그레이드 후 DBCC UPDATEUSAGE를 실행해야 합니다.

DBCC UPDATEUSAGE의 작동 원리는 다음과 같습니다. DBCC UPDATEUSAGE는 테이블 또는 인덱스에 있는 각 파티션의 행 수, 사용된 페이지 수, 예약된 페이지 수, 리프 페이지 수 및 데이터 페이지 수를 수정합니다. 시스템 테이블에 개수 오류가 없으면 DBCC UPDATEUSAGE는 데이터를 반환하지 않습니다. 개수 오류가 발견되고 수정되었으며 사용자가 WITH NO_INFOMSGS를 사용하지 않은 경우에는 DBCC UPDATEUSAGE는 시스템 테이블의 업데이트된 행과 열을 반환합니다.

DBCC UPDATEUSAGE는 공간 사용률 카운터를 동기화하는 데도 사용할 수 있습니다. 대용량 테이블이나 데이터베이스에 대해 DBCC UPDATEUSAGE를 실행하는 경우 시간이 많이 걸릴 수 있으므로 일반적으로 sp_spaceused가 잘못된 값을 반환한다고 의심되는 경우에만 DBCC UPDATEUSAGE를 사용하는 것이 좋습니다. 선택적 매개 변수를 사용하면 sp_spaceused에서 테이블이나 인덱스의 공간 정보를 반환하기 전에 DBCC UPDATEUSAGE를 실행하도록 할 수 있습니다.

SQL Server 2005의 DBCC CHECKDB는 페이지 또는 행 개수가 음수일 경우 이를 감지하도록 향상되었습니다. DBCC CHECKDB는 음수를 감지하면 DBCC UPDATEUSAGE를 실행하여 이 문제를 해결하라는 권장 메시지와 경고를 출력합니다. SQL Server 2005로 업그레이드했기 때문에 이 문제가 발생한 것처럼 보일 수도 있지만, 업그레이드 전부터 잘못된 개수가 있었는지 확인해야 합니다.

다음 예제는 현재 데이터베이스의 모든 개체에 대해 페이지나 행 개수 또는 둘 모두를 업데이트하는 방법을 보여 줍니다. 다음 명령에서는 데이터베이스 이름으로 0을 지정하고 DBCC UPDATEUSAGE는 현재 데이터베이스에 대해 업데이트된 정보를 보고합니다.

DBCC UPDATEUSAGE (0);
GO

예를 들어 AdventureWorks의 페이지나 행 개수 또는 둘 모두를 업데이트하되 정보 메시지를 표시하지 않으려면 다음과 같이 데이터베이스 이름으로 AdventureWorks를 지정하고 모든 정보 메시지를 표시하지 않도록 설정하는 다음과 유사한 명령을 실행하십시오.

USE AdventureWorks;
GO
DBCC UPDATEUSAGE (‘AdventureWorks’) WITH NO_INFOMSGS; GO

자세한 내용은 SQL Server 온라인 설명서의 DBCC UpdateUsage를 참조하십시오.


AND

출처 : http://msdn2.microsoft.com/ko-kr/library/ms178653.aspx


SQL Server 2005 온라인 설명서
sp_dbcmptlevel(Transact-SQL)

업데이트: 2006년 7월 17일

특정 데이터베이스 동작이 지정된 버전의 SQL Server와 호환되도록 설정합니다.

항목 링크 아이콘 Transact-SQL 구문 표기 규칙

구문구문
주의주의

SQL Server 2005의 모든 설치에서 기본 호환성 수준은 90입니다. model 데이터베이스의 호환성 수준이 낮은 경우가 아니면 SQL Server 2005에서 만든 데이터베이스는 이 수준으로 설정됩니다. 데이터베이스가 이전 버전의 SQL Server에서 SQL Server 2005로 업그레이드되면 데이터베이스는 기존 호환성 수준을 유지합니다. 이는 시스템 및 사용자 데이터베이스 모두에 적용됩니다. sp_dbcmptlevel을 사용하여 데이터베이스의 호환성 수준을 90으로 변경합니다. 데이터베이스의 현재 호환성 수준을 보려면 sys.databases 카탈로그 뷰의 compatibility_level 열을 쿼리합니다.

이전 버전과의 호환성을 위해 sp_dbcmptlevel 사용

sp_dbcmptlevel 저장 프로시저는 전체 서버가 아니라 지정한 데이터베이스의 동작에만 영향을 줍니다. sp_dbcmptlevel은 SQL Server 이전 버전과 부분적으로만 호환됩니다. 중간 마이그레이션 도구로 sp_dbcmptlevel을 사용하여 관련 호환성 수준 설정에서 제어하는 동작의 버전 차이를 해결할 수 있습니다. 기존 SQL Server 응용 프로그램이 SQL Server 2005의 동작 차이에 의해 영향을 받으면 응용 프로그램이 제대로 실행되도록 변환하십시오. 그런 다음 sp_dbcmptlevel을 사용하여 호환성 수준을 90으로 변경하십시오. 데이터베이스의 새로운 호환성 설정은 다음에 데이터베이스가 현재 데이터베이스로 사용될 때 적용됩니다. 이 때 데이터베이스가 로그온 시에 기본 데이터베이스로 사용되는지 또는 USE 문에서 지정한 경우에 기본 데이터베이스로 사용되는지 여부는 문제되지 않습니다.

인덱싱된 뷰를 포함하는 데이터베이스는 80보다 낮은 호환성 수준으로 변경할 수 없습니다.

최상의 방법

SET 옵션

새 기능이 이전 호환성 수준에서 작동하려면 SET 옵션을 조정해야 합니다. 예를 들어 호환성 수준 80에서 xml 데이터 형식을 사용하려면 ANSI SET 옵션을 적절하게 설정해야 합니다. 또한 데이터베이스 호환성 수준이 90으로 설정된 경우 ANSI_WARNINGS를 ON으로 설정하면 암시적으로 ARITHABORT가 ON으로 설정됩니다. 데이터베이스 호환성 수준이 80 이하로 설정된 경우에는 명시적으로 ARITHABORT 옵션을 ON으로 설정해야 합니다. 자세한 내용은 결과에 영향을 주는 SET 옵션을 참조하십시오.

호환성 수준 및 저장 프로시저

저장 프로시저가 실행될 때 저장 프로시저는 정의된 데이터베이스의 현재 호환성 수준을 사용합니다. 데이터베이스의 호환성 설정이 변경되면 모든 저장 프로시저도 그에 맞게 자동으로 다시 컴파일됩니다.

sp_dbcmptlevel 사용 시 환경 고려 사항

sp_dbcmptlevel 호출은 개별적으로 제출되어야 합니다. sp_dbcmptlevel은 다음과 같은 다른 컨텍스트 내에서 호출할 수 없습니다.

  • 저장 프로시저
  • EXEC(string) 구문으로 실행한 Transact-SQL 문자열
  • Transact-SQL 문의 일괄 처리

수준 60, 65와 수준 70, 80, 90 사이의 차이

호환성 수준을 60 또는 65으로 설정하면 많은 동작에 영향을 미칩니다. 이러한 동작들은 다음 표의 왼쪽 열에 나열되어 있습니다.

참고:
6.x 응용 프로그램에 영향을 주는 기타 차이점에 대한 자세한 내용은 이 항목의 뒷부분에 나오는 "낮은 호환성 수준과 수준 90 사이의 차이" 섹션, 그리고 주의 섹션에 있는 6.x 이후의 예약 키워드를 참조하십시오.

호환성 수준 설정 60 또는 65 호환성 수준 설정 70 이상

GROUP BY 절은 있고 ORDER BY 절은 없는 SELECT 문의 결과 집합이 GROUP BY 열별로 정렬됩니다.

GROUP BY 절은 그 자체로 정렬되지 않습니다. 결과 집합을 정렬하려면 SQL Server에 대해 ORDER BY 절을 명시적으로 지정해야 합니다. 자세한 내용은 SELECT(Transact-SQL)를 참조하십시오.

테이블 별칭을 접두사로 사용하는 열이 UPDATE 문의 SET 절에서 허용됩니다.

테이블 별칭이 UPDATE 문의 SET 절에서 허용되지 않습니다. SET 절에 지정된 테이블 또는 뷰는 UPDATE 키워드 바로 다음에 지정된 테이블 또는 뷰와 일치해야 합니다. 자세한 내용은 UPDATE(Transact-SQL)를 참조하십시오.

CREATE TABLE 또는 ALTER TABLE에서 명시적인 NULL 또는 NOT NULL 옵션을 사용하지 않고 만든 bit 열은 NOT NULL로 생성됩니다.

Null 허용 여부가 명시적이지 않은 bit 열의 Null 허용 여부는 SET ANSI_NULL_DFLT_ON / SET ANSI_NULL_DFLT_OFF의 세션 설정이나 SET ANSI NULL DEFAULT의 데이터베이스 설정에 의해 결정됩니다. 자세한 내용은 SET(Transact-SQL)를 참조하십시오.

ALTER COLUMN 절을 ALTER TABLE에서 사용할 수 없습니다.

ALTER COLUMN 절을 ALTER TABLE에서 사용할 수 있습니다. 자세한 내용은 ALTER TABLE(Transact-SQL)을 참조하십시오.

테이블에 대해 생성된 트리거가 같은 유형의 기존 트리거(INSERT, UPDATE, DELETE)를 대체합니다. CREATE TRIGGER의 WITH APPEND 옵션을 사용하여 같은 유형의 트리거를 여러 개 만들 수 있습니다.

같은 유형의 트리거가 추가됩니다. 트리거 이름은 고유해야 합니다. WITH APPEND 옵션으로 간주됩니다. 자세한 내용은 CREATE TRIGGER(Transact-SQL)를 참조하십시오.

일괄 처리 또는 프로시저에 잘못된 개체 이름이 있으면 일괄 처리가 구문 분석되거나 컴파일될 때 경고가 반환되고 일괄 처리가 실행될 때 오류 메시지가 반환됩니다.

잘못된 로컬 개체의 경우에는 일괄 처리가 구문 분석되거나 컴파일될 때 경고가 반환되지 않고 일괄 처리가 실행될 때 오류 메시지가 반환됩니다.

그러나 잘못된 원격 개체의 경우에는 DNR(지연된 이름 확인)이 지원되지 않습니다. 프로시저에서 잘못된 원격 테이블이 사용되는 경우에는 프로시저 생성이 실패하고 오류를 반환합니다.

참고:
DNR 지원(실행될 때까지는 존재하지 않는 개체를 컴파일 시에 참조하는 기능)은 테이블이나 뷰 이름에만 적용됩니다. 지연된 이름 확인에 대한 자세한 내용은 CREATE PROCEDURE(Transact-SQL)를 참조하십시오.

다음과 같은 형식의 쿼리는 Y 테이블를 무시하고 SELECT 문 결과를 X 테이블에 삽입함으로써 제대로 실행됩니다.

INSERT X
SELECT select_list INTO Y

Microsoft SQL Server 7.0 이상에서는 이와 동일한 쿼리를 실행하면 구문 오류가 반환됩니다.

빈 문자열 리터럴(' ')은 공백 하나로 간주됩니다.

빈 문자열 리터럴(' ')은 빈 문자열로 간주됩니다.

DATALENGTH('')는 1을 반환하고 ''는 공백 하나로 구문 분석됩니다.

DATALENGTH(N'')는 2를 반환하고 N''은 유니코드 공백 하나로 구문 분석됩니다.

DATALENGTH('')는 0을 반환합니다.

DATALENGTH(N'')는 0을 반환합니다.

LEFT('123', 0)는 NULL을 반환합니다.

LEFT(N'123', 0)는 NULL을 반환합니다.

LEFT('123', 0)는 빈 문자열을 반환합니다.

LEFT(N'123', 0)는 빈 문자열을 반환합니다.

LTRIM(' ')은 NULL을 반환합니다.

LTRIM(N' ')은 NULL을 반환합니다.

LTRIM(' ')은 빈 문자열을 반환합니다.

LTRIM(N' ')은 빈 문자열을 반환합니다.

REPLICATE('123', 0)는 NULL을 반환합니다.

REPLICATE(N'123', 0)는 NULL을 반환합니다.

REPLICATE('123', 0)는 빈 문자열을 반환합니다.

REPLICATE(N'123', 0)는 빈 문자열을 반환합니다.

RIGHT(N'123', 0)는 NULL을 반환합니다. RIGHT('123', 0)는 NULL을 반환합니다.

RIGHT('123', integer_expression)는 integer_expression이 음수이면 NULL을 반환합니다.

RIGHT(N'123', integer_expression)는 integer_expression이 음수이면 NULL을 반환합니다.

RIGHT('123', 0)는 빈 문자열을 반환합니다.

RIGHT(N'123', 0)는 빈 문자열을 반환합니다.

RIGHT('123', integer_expression)는 integer_expression이 음수이면 오류를 반환합니다. RIGHT(N'123', integer_expression)는 integer_expression이 음수이면 오류를 반환합니다.

RTRIM(' ')은 NULL을 반환합니다.

RTRIM(N' ')은 NULL을 반환합니다.

RTRIM(' ')은 빈 문자열을 반환합니다.

RTRIM(N' ')은 빈 문자열을 반환합니다.

SPACE(0)는 NULL을 반환합니다.

SPACE(0)는 빈 문자열을 반환합니다.

start 값으로 expression의 문자 수보다 큰 값을 지정하거나 length가 0과 같으면 SUBSTRING(expression, start, length) 함수에서 NULL을 반환합니다. 예를 들어 SUBSTRING(N'123', 4, 1)은 NULL을 반환합니다.

동일한 조건에서 SUBSTRING(expression, start, length)은 한 쌍의 작은따옴표로 구분된 빈 문자열을 반환합니다. 예를 들어 SUBSTRING(N'123', 4, 1)은 ''를 반환합니다.

UPDATETEXT table.textcolumn textpointer 0 NULL NULL은 Null 값을 반환합니다.

UPDATETEXT table.textcolumn textpointer 0 NULL NULL은 빈 텍스트를 반환합니다.

CHARINDEX와 PATINDEX 함수는 패턴과 식이 모두 NULL인 경우에만 NULL을 반환합니다.

CHARINDEX와 PATINDEX 함수는 모든 입력 매개 변수가 NULL인 경우 NULL을 반환합니다.

inserteddeleted 테이블의 text 또는 image 열에 대한 참조가 NULL로 표시됩니다.

inserteddeleted 테이블의 text 또는 image 열에 대한 참조가 허용되지 않습니다.

한 트리거 내의 inserteddeleted 테이블에서 textimage 열을 가져오면 textimage 열에 대해 NULL 값이 반환됩니다.

한 트리거 내의 inserteddeleted 테이블에서 textimage 열을 가져올 수 없으며 오류가 발생됩니다.

text 열을 NULL로 초기화하는 UPDATETEXT를 허용합니다.

UPDATETEXT는 text 열을 빈 문자열로 초기화합니다.

WRITETEXT는 text 열을 NULL로 초기화합니다.

sp_dboptionconcatenation of null yields null 설정이 off(사용 안 함)이므로 연결 연산의 피연산자가 NULL이면 빈 문자열을 반환합니다.

sp_dboptionconcatenation of null yields null 설정이 on(사용)이므로 연결 연산의 피연산자가 NULL이면 NULL을 반환합니다.

INSERT 문의 VALUES 절에서 스칼라 값을 반환하는 SELECT 문이 허용됩니다.

INSERT 문은 삽입할 값 중 하나로서 VALUES 절에 SELECT 문을 포함할 수 없습니다.

INSERT table EXEC procedure 문에서 참조되는 저장 프로시저의 ROLLBACK 문을 사용하면 INSERT 문은 롤백되지만 일괄 처리는 계속됩니다.

INSERT...EXEC 문에서 참조하는 저장 프로시저의 ROLLBACK 문을 사용하면 전체 트랜잭션이 롤백되고 일괄 처리 실행이 중지됩니다.

낮은 호환성 수준과 수준 90 사이의 차이

다음 하위 섹션에서는 호환성 수준 90으로 정의된 새로운 동작에 대해 설명합니다. 80 이하의 호환성 수준에 영향을 주는 추가적인 동작 차이에 대한 자세한 내용은 이 섹션의 뒷부분에 나오는 "예약 키워드" 섹션을 참조하십시오.

호환성 수준 90에서는 동작이 다음과 같이 변경되었습니다.

호환성 수준 설정 80 이하 호환성 수준 설정 90 영향력

FROM 절의 잠금 힌트에 대해 WITH 키워드는 항상 옵션입니다.

몇 가지 예외가 있지만 테이블 힌트는 WITH 키워드를 사용하여 힌트를 지정할 때만 FROM 절에서 지원됩니다. 자세한 내용은 FROM(Transact-SQL)을 참조하십시오.

높음

외부 조인에 대한 *= and =* 연산자가 지원되지만 경고 메시지가 표시됩니다.

이러한 연산자가 지원되지 않으므로 OUTER JOIN 키워드를 사용해야 합니다.

높음

ORDER BY 목록의 열 참조를 SELECT 목록에 정의된 열로 바인딩할 때 열 모호성이 무시되고 경우에 따라 열 접두사도 무시됩니다. 이로 인해 결과 집합이 예기치 않은 순서로 반환될 수 있습니다.

예를 들어 두 부분으로 이루어진 단일 열(<table_alias>.<column>)로 구성되고 SELECT 목록에서 열 참조로 사용되는 ORDER BY 절은 허용되지만 테이블 별칭은 무시됩니다. 다음 쿼리를 살펴보십시오.

SELECT c1 = -c1 FROM t_table AS x ORDER BY x.c1

이 쿼리를 실행하면 열 접두사가 ORDER BY에서 무시됩니다. 정렬 작업은 예상대로 지정한 원본 열(x.c1)에서 수행되지 않고 대신 쿼리에 정의된 파생된 c1 열에서 수행됩니다. 이 쿼리의 실행 계획은 파생된 열의 값이 먼저 계산된 다음 계산된 값이 정렬됨을 보여 줍니다.

열 모호성에서 오류가 발생됩니다. SELECT 목록에 정의된 열로 바인딩할 때 ORDER BY에 지정된 열 접두사는 무시되지 않습니다(있는 경우).

다음 쿼리를 살펴보십시오.

SELECT c1 = -c1 FROM t_table AS x ORDER BY x.c1

이 쿼리를 실행하면 ORDER BY 절의 열 접두사가 무시되지 않습니다. 정렬 작업은 예상대로 지정한 원본 열(x.c1)에서 수행됩니다. 이 쿼리의 실행 계획은 SORT 연산자가 t_table에서 반환된 행의 순서를 지정한 다음 SELECT 열에 정의된 파생된 c1 열의 값이 계산됨을 보여 줍니다.

보통

데이터 형식이 다른 UNION의 INSERT SELECT에서 각 UNION 분기는 INSERT 대상 열의 유형으로 직접 형변환됩니다. 호환되지 않는 유형 변환으로 인해 단독으로 사용되는 UNION이 실패하는 경우에도 UNION의 결과 유형에 대한 분기는 변환되지 않기 때문에 INSERT SELECT를 사용하면 UNION이 제대로 실행됩니다.

SQL Server 2005에서 UNION의 결과 유형은 INSERT SELECT와 별개로 파생됩니다. UNION의 각 분기는 UNION의 결과 유형으로 형변환된 다음 INSERT의 대상 열 유형으로 형변환됩니다. UNION에 호환되지 않는 유형이 있으면 첫 번째 형변환에서 오류가 발생할 수 있습니다. 호환성 수준 90으로 실행하려면 INSERT SELECT 내에서 사용된 호환되지 않는 모든 유형의 UNION을 수정해야 합니다.

보통

뷰 또는 참조된 뷰에서 TOP 절을 사용하는 경우 뷰를 통한 삽입 및 업데이트 작업은 WITH CHECK OPTION 절을 지정하는 뷰에서 제대로 지원되지 않습니다.

뷰 또는 참조된 뷰에서 TOP 절을 사용하는 경우 뷰를 통한 삽입 및 업데이트 작업은 WITH CHECK OPTION을 사용하는 뷰에서 지원되지 않습니다.

보통

가변 길이 열과 고정 길이 열의 UNION에서 고정 길이 열을 생성합니다.

가변 길이 열과 고정 길이 열의 UNION에서 가변 길이 열을 생성합니다.

보통

SET XACT_ABORT OFF가 한 트리거 내에서 허용됩니다.

SET XACT_ABORT OFF가 한 트리거 내에서 허용되지 않습니다.

보통

FOR BROWSE 절이 뷰에서 허용되고 무시됩니다.

FOR BROWSE 절이 뷰에서 허용되지 않습니다.

보통

도메인 오류가 ANSI_WARNINGS에 의해 제어되지 않습니다. ANSI_WARNINGS가 OFF로 설정되어 있고 ARITHABORT가 변경되지 않으면 ARITHABORT 설정이 적합한 값으로 인식됩니다.

도메인 오류는 ANSI_WARNINGS에 의해 제어되며 심각도가 16인 오류입니다. ANSI_WARNINGS나 ARITHABORT가 ON이면 NULL 값을 반환하는 대신 오류가 발생합니다. 이러한 변경으로 인해 OFF로 설정된 ARITHABORT에 종속되어 있는 사용자 스크립트의 연결이 끊어질 수 있습니다.

보통

원격 데이터 원본 [OpenRowset 또는 OpenQuery]에 대한 통과 쿼리가 이름이 중복된 열을 생성하는 경우 해당 열이 쿼리에서 명시적으로 명명되지 않는 한 이 중복된 열 이름은 무시됩니다.

원격 데이터 원본 [OpenRowset 또는 OpenQuery]에 대한 통과 쿼리가 이름이 중복된 열을 생성하면 오류가 발생합니다.

낮음

크기가 8000보다 큰 문자열 상수와 varbinary 상수는 text, ntext 또는 image로 처리됩니다.

크기가 8000보다 큰 문자열 상수와 varbinary 상수는 varchar(max)(또는 각각 nvarchar(max)varbinary(max)) 유형으로 처리됩니다. 따라서 SELECT 목록에 이러한 식이 있으면 SELECT … INTO를 사용하여 만든 테이블의 데이터 형식이 변경될 수 있습니다.

낮음

숫자 유형(smallint, tinyint, int, bigint, numeric, decimal, smallmoney, money) 간 비교는 유형 계층에서 우선 수위가 낮은 피비교수를 우선 순위가 높은 유형으로 변환하여 수행합니다.

변환하지 않고 숫자 유형 값이 비교됩니다. 따라서 성능이 향상됩니다. 그러나 이런 경우 동작이 약간 변경될 수 있습니다. 특히 변환으로 인해 오버플로 예외가 발생하는 경우에는 더욱 그렇습니다.

낮음

4000자를 초과하여 입력하면 문자열 인수를 사용하는 기본 제공 메타데이터 함수에서 입력을 잘라냅니다.

잘라내기로 인해 공백이 아닌 문자가 손실되면 기본 제공 메타데이터 함수에서 오류가 발생합니다.

낮음

따옴표가 없는 식별자에서 허용되지 않는 문자 집합이 변경되지 않고 그대로 유지됩니다.

Transact-SQL 파서는 유니코드 3.2 표준을 지원합니다. 이 표준은 구분 기호로 분리되지 않은 식별자에서 허용되지 않는 일부 국가별 문자에 대한 문자 분류를 변경합니다.

낮음

부동 소수점 도메인 오류[즉, log() 함수의 경우 음수 인수]가 발생하는 경우 SET ANSI_WARNINGS ON 설정은 SET ARITHABORT OFF 설정보다 우선 적용되지 않습니다. ANSI_WARNINGS는 ON이지만 ARITHABORT는 OFF인 경우에는 부동 소수점 도메인 오류로 인해 쿼리가 종료되지 않습니다.

SET ANSI_WARNINGS ON 설정이 ARITHABORT OFF 설정보다 우선 적용됩니다. 이런 경우 부동 소수점 도메인 오류로 인해 쿼리가 종료됩니다.

낮음

정수가 아닌 상수가 ORDER BY 절에서 허용되고 무시됩니다.

정수가 아닌 상수가 ORDER BY 절에서 허용되지 않습니다.

낮음

SET 옵션이 지정되지 않은 빈 SET 문이 허용됩니다.

빈 SET 절이 허용되지 않습니다.

낮음

파생 테이블에서 생성한 열에 대해 IDENTITY 특성이 제대로 파생되지 않습니다.

파생 테이블에서 생성한 열에 대해 IDENTITY 특성이 제대로 파생됩니다.

낮음

부동 소수점 데이터 형식에 대한 산술 연산자의 Null 허용 속성이 항상 Null을 허용합니다.

부동 소수점 데이터 형식에 대한 산술 연산자의 Null 허용 여부 속성은 입력이 Null을 허용하지 않고 ANSI_WARNINGS가 ON인 경우 Null 허용으로 변경됩니다.

낮음

UNION을 사용하는 INSERT .. SELECT 문에서 개별 결과 집합이 생성한 유형은 모두 대상 결과 유형으로 변환됩니다.

UNION을 사용하는 INSERT .. SELECT 문에서 다양한 분기의 지배적인 유형이 결정되고 그 결과는 대상 테이블 유형으로 변환되기 전에 해당 유형으로 변환됩니다.

낮음

SELECT .. FOR XML 문에서 필요 없는 경우에도 16진수(27)(' 문자)와 16진수(22)(")의 형식이 항상 올바르게 수정됩니다.

FOR XML은 필요한 경우에만 16진수(27)와 16진수(22)의 형식을 올바르게 수정합니다. 다음과 같은 경우에는 형식이 올바르게 수정되지 않습니다.

  • 특성 내용에서 16진수(27)(' 문자)는 특성 값이 "로 구분되는 경우에 형식이 올바로 수정되지 않으며 16진수(22)(" 문자)는 특성 값이 '로 구분되는 경우 형식이 올바로 수정되지 않습니다.
  • 요소 내용에서는 16진수(27)와 16진수(22)의 형식이 올바로 수정되지 않습니다.

낮음

FOR XML에서는 타임스탬프 값이 정수로 매핑됩니다.

FOR XML에서는 타임스탬프 값이 이진 값으로 매핑됩니다.

자세한 내용은 timestamp 데이터 형식에 대한 FOR XML 지원을 참조하십시오.

높음(timestamp 열이 사용된 경우), 그 외 경우는 낮음

FOR XML 및 OPENXML의 이름에서 3바이트 유니코드 문자는 8개의 위치에 걸쳐 표시됩니다.

예를 들어 8개의 위치에 표시되는 FOR XML은 유니코드 코드 포인트 U+10000을 다음과 같이 표시합니다.

<a_x00010000_ c1="1" />

FOR XML 및 OPENXML의 이름에서 3바이트 유니코드 문자는 6개의 위치에 걸쳐 표시됩니다.

예를 들어 6개의 위치에 표시되는 FOR XML은 유니코드 코드 포인트 U+10000을 다음과 같이 표시합니다.

<a_x010000_ c1="1" />

낮음

FOR XML에서 AUTO 모드의 파생 테이블 매핑은 투명하게 처리됩니다.

예를 들면 다음과 같습니다.

USE AdventureWorks
CREATE TABLE Test(id int);
INSERT INTO Test VALUES(1);
INSERT INTO Test VALUES(2);
SELECT * FROM (SELECT a.id AS a, 
b.id AS b FROM Test a 
JOIN Test b ON a.id=b.id) 
Test FOR XML AUTO;

AdventureWorks 의 호환성 수준을 80으로 설정하면 위 예에서는 다음이 생성됩니다.

<a a="1"><b b="1"/></a>

<a a="2"><b b="2"/></a>

FOR XML에서 AUTO 모드의 파생 테이블 매핑은 불투명하게 처리됩니다.

AdventureWorks 의 호환성 수준을 90으로 설정하면 앞의 예에서는 다음이 생성됩니다.

<Test a="1" b="1"/>

<Test a="2" b="2"/>

AUTO 모드로 변경하는 방법은 AUTO 모드의 향상된 기능을 참조하십시오.

높음(FOR XML AUTO 모드가 뷰에 적용된 경우), 그 외 경우는 낮음

money로 변환되는 문자열은 한국어와 일본어에서만 백슬래시 문자(\)를 통화 기호로 사용하도록 지원합니다.

백슬래시 문자(\)가 모든 언어에서 money로 변환되는 모든 문자열에 허용됩니다. ISNUMERIC은 \가 통화 기호로 사용되는 경우에 true를 반환합니다.

SQL Server 2005 이전 버전의 SQL Server에 있는 데이터베이스의 경우 이 새 기능은 한국어나 일본어가 아닌 경우에도 \를 포함하는 ISNUMERIC 반환 값에 종속되는 인덱스와 계산 열을 구분합니다.

낮음

피연산자가 Null을 허용하지 않고 ANSI_WARNINGS나 ARITHABORT가 ON으로 설정된 경우에도 산술 연산자의 결과는 항상 Null을 허용합니다.

ANSI_WARNINGS나 ARITHABORT가 ON으로 설정되어 있는 경우 두 피연산자가 Null을 허용하지 않으면 부동 소수점 산술 연산자의 결과는 Null을 허용하지 않습니다.

Null 허용 여부를 이렇게 변경하면 bcp를 사용하여 부동 소수점 산술 연산자를 사용하는 계산 열이 있는 SQL Server 2000 테이블에서 이진 형식을 사용하는 데이터를 대량으로 내보낸 다음 bcp나 BULK INSERT를 사용하여 정의가 동일한 SQL Server 2005 테이블로 해당 데이터를 대량으로 가져오는 경우 오류가 발생할 수 있습니다.

참고:
두 옵션 모두 OFF로 설정되어 있으면 데이터베이스 엔진은 결과를 Null 허용으로 표시합니다. 이 동작은 SQL Server 2000과 같습니다.

낮음

매개 변수로 nvarchar를 사용하는 기본 제공 함수의 경우 제공된 값이 varchar이면 그 값은 nvarchar(4000)로 변환됩니다. SQL Server 2000에서 더 큰 값이 전달되면 자동으로 잘립니다.

매개 변수로 nvarchar를 사용하는 기본 제공 함수의 경우 제공된 값이 varchar이면 그 값은 nvarchar(4000)로 변환됩니다. 그러나 더 큰 값이 전달되면 SQL Server 2005에서 오류가 발생합니다.

호환성 수준 90으로 실행하려면 잘림 기능을 사용하는 모든 사용자 지정 코드를 수정해야 합니다.

낮음

가변 길이(varchar, varbinary, nvarchar) 문자열과 고정 길이(char, binary 또는 nchar) 문자열의 UNION은 고정 길이 결과를 반환합니다.

가변 크기 문자열과 고정 크기 문자열의 UNION은 가변 크기 문자열을 반환합니다.

호환성 수준 90으로 실행하려면 가변 크기 유형과 고정 크기 유형의 UNION에서 발생하는 유형에 종속된 모든 위치(인덱스, 쿼리 및 계산 열)를 수정해야 합니다.

낮음

0xFFFF 문자를 포함하는 개체 이름은 잘못된 식별자입니다.

0xFFFF 문자를 포함하는 개체 이름은 잘못된 식별자이며 액세스할 수 없습니다.

호환성 수준 90으로 실행하려면 이 문자를 포함하는 개체의 이름을 변경해야 합니다.

낮음

SELECT ISNUMERIC('<string>')에서 <string> 내에 포함된 쉼표는 의미가 있습니다.

예를 들어 다음 SELECT ISNUMERIC('121212,12') 쿼리에서는 0을 반환하며 이는 문자열 121212,12가 숫자가 아님을 나타냅니다.

SELECT ISNUMERIC('<string>')에서 <string> 내에 포함된 쉼표는 무시됩니다.

예를 들어 다음 SELECT ISNUMERIC('121212,12') 쿼리에서는 1을 반환하며 이는 문자열 121212,12가 숫자임을 나타냅니다.

낮음

Transact-SQL 문에서 예약 키워드 뒤에 나오는 콜론(:)은 무시됩니다.

Transact-SQL 문에서 예약 키워드 뒤에 콜론(:)이 있으면 문이 실패합니다.

낮음

외부 쿼리의 열을 참조하는 하위 쿼리의 GROUP BY 절이 성공합니다.

외부 쿼리의 열을 참조하는 하위 쿼리의 GROUP BY 절이 SQL 표준에 따라 오류를 반환합니다.

낮음

예약 키워드

호환성 설정은 데이터베이스 엔진에 예약되어 있는 키워드도 결정합니다. 다음 표에서는 각 호환성 수준에 의해 정의된 예약 키워드를 보여 줍니다.

호환성 수준 설정 예약 키워드

90

EXTERNAL, PIVOT, UNPIVOT, REVERT, TABLESAMPLE

80

COLLATE, FUNCTION, OPENXML

70

BACKUP, CONTAINS, CONTAINSTABLE, DENY, FREETEXT, FREETEXTTABLE, PERCENT, RESTORE, ROWGUIDCOL, TOP

65

AUTHORIZATION, CASCADE, CROSS, DISTRIBUTED, ESCAPE, FULL, INNER, JOIN, LEFT, OUTER, PRIVILEGES, RESTRICT, RIGHT, SCHEMA, WORK

지정된 호환성 수준의 예약 키워드에는 해당 수준 또는 그 아래 수준에서 정의된 모든 키워드가 포함됩니다. 따라서 수준이 90인 응용 프로그램의 경우에는 위 표에 나열된 모든 키워드가 예약되어 있습니다. 더 낮은 호환성 수준에서 수준이 90인 키워드는 유효한 개체 이름으로 유지되지만 해당 키워드에 대한 수준이 90인 언어 기능은 사용할 수 없습니다.

정의된 키워드는 예약된 상태로 유지됩니다. 예를 들어 호환성 수준 70에서 정의된 예약 키워드 BACKUP은 수준 80과 90에서도 예약되어 있습니다.

응용 프로그램이 호환성 수준에 대한 키워드로 예약되어 있는 식별자를 사용할 경우 제대로 실행되지 않습니다. 이러한 문제를 해결하려면 식별자를 대괄호([ ])나 따옴표(" ")로 묶으십시오. 예를 들어 TABLESAMPLE 식별자를 사용하는 응용 프로그램을 호환성 수준 90으로 업그레이드하려면 식별자를 [TABLESAMPLE]이나 "TABLESAMPLE"로 변경할 수 있습니다.

사용 권한사용 권한
예

1. SQL Server 2000으로 호환성 수준 변경

2. ORDER BY에 호환성 수준이 미치는 결과(시나리오 1)

다음 예에서는 호환성 수준 80과 90에서 ORDER BY 바인딩의 차이를 보여 줍니다. 이 예에서는 tempdb 데이터베이스에 SampleTable 예제 테이블을 만듭니다.

USE tempdb;
CREATE TABLE SampleTable(c1 int, c2 int);
GO

기본 수준인 호환성 수준 90에서 다음 SELECT... ORDER BY 문은 AS 절의 열 이름인 c1이 모호하기 때문에 오류를 생성합니다.

SELECT c1, c2 AS c1
    FROM SampleTable
    ORDER BY c1;
GO

데이터베이스를 호환성 수준 80으로 다시 설정하면 동일한 SELECT... ORDER BY 문이 제대로 실행됩니다.

sp_dbcmptlevel tempdb, 80
SELECT c1, c2 AS c1
    FROM SampleTable
    ORDER BY c1;
GO

다음 SELECT... ORDER BY 문은 두 호환성 수준에서 모두 실행됩니다.

sp_dbcmptlevel tempdb, 80
SELECT c1, c2 AS c3
FROM SampleTable
ORDER BY c1;
GO

sp_dbcmptlevel tempdb, 90
SELECT c1, c2 AS c3
FROM SampleTable
ORDER BY c1;
GO

3. ORDER BY에 호환성 수준이 미치는 결과(시나리오 2)

기본 수준인 호환성 수준 90에서 다음 SELECT...ORDER BY 문은 ORDER BY 절에 추가 테이블 접두사가 있기 때문에 오류를 생성합니다.

SELECT c1 AS x
    FROM SampleTable
    ORDER BY SampleTable.x;
GO

데이터베이스를 호환성 수준 80으로 다시 설정하면 동일한 SELECT...ORDER BY 문이 제대로 실행됩니다.

sp_dbcmptlevel tempdb, 80
SELECT c1 AS x
    FROM SampleTable
    ORDER BY SampleTable.x;
GO

다음 SELECT...ORDER BY 문은 두 호환성 수준에서 모두 실행됩니다.

sp_dbcmptlevel tempdb, 80
SELECT c1 AS x
    FROM SampleTable
    ORDER BY x;
GO
sp_dbcmptlevel tempdb, 90
SELECT c1 AS x
    FROM SampleTable
    ORDER BY x;
GO
AND

back to blog index

Given the Orders table in the Northwind database, return the following:
- Individual orders and their freight values
- Daily total freight (in separate rows)
- Monthly total freight (in separate rows)
- Yearly total freight (in separate rows)
- Grand total freight (in a separate row)

The result set should include the following columns:
OrderYear, OrderMonth, OrderDay, OrderID , Freight.

Return the rows sorted such that:
- Orders will be sorted by OrderDate, OrderID
- The row with the daily total should be returned right after the corresponding day’s individual orders
- The row with the monthly total should be returned right after the corresponding month’s last daily total
- The row with the yearly total should be returned right after the corresponding year’s last monthly total
- The row with the grand total should appear last

Sorting needs to be deterministic.
You cannot rely on luck, optimization or anything else.

The output should look like this (in abbreviated form):

OrderYear   OrderMonth  OrderDay    OrderID     Freight
----------- ----------- ----------- ----------- ---------------------
1996        7           4           10248       32.38
1996        7           4           NULL        32.38
1996        7           5           10249       11.61
1996        7           5           NULL        11.61
1996        7           8           10250       65.83
1996        7           8           10251       41.34
1996        7           8           NULL        107.17
...
1996        7           31          10269       4.56
1996        7           31          NULL        4.56
1996        7           NULL        NULL        1288.18
...
1996        12          31          10399       27.36
1996        12          31          NULL        27.36
1996        12          NULL        NULL        2798.59
1996        NULL        NULL        NULL        10279.87
...
1998        5           6           11074       18.44
1998        5           6           11075       6.19
1998        5           6           11076       38.28
1998        5           6           11077       8.53
1998        5           6           NULL        71.44
1998        5           NULL        NULL        685.08
1998        NULL        NULL        NULL        22194.05
NULL        NULL        NULL        NULL        64942.69

(1337 row(s) affected)

Please post your solution as a comment in the blog
(make sure you don’t peek at others’ solutions before finishing yours).
Please also send me the solution directly as a .sql file to itzik@SolidQ.com.
The puzzle will be open for a week.
I’ll post a summary blog entry with the solutions next week.

Good Luck!

--
BG

End of Article



출처 : http://www.sqlmag.com/Articles/Index.cfm?ArticleID=96263&DisplayTab=Article#comment
AND

출처 : http://www.microsoft.com/technet/prodtechnol/sql/2000/maintain/sqlIObasics.mspx

SQL Server 2000 I/O Basics

Published: January 21, 2005

Author: Bob Dorr, Microsoft SQL Server Escalation

Note: You can also read more about I/O and SQL Server 2005 in "SQL Server I/O Basics Chapter 2".

SUMMARY: Learn the I/O requirements for Microsoft SQL Server database file operations. This will help you increase system performance and avoid I/O environment errors.

On This Page
Introduction Introduction
Terms Terms
Microsoft SQL Server I/O Design Microsoft SQL Server I/O Design
Microsoft SQL Server Core I/O Requirements Microsoft SQL Server Core I/O Requirements
Problems, Pitfalls, and Samples Problems, Pitfalls, and Samples
Utilities Utilities
Conclusion Conclusion
Other References Other References

Introduction

Because new devices and storage solutions continue to appear in the marketplace, the environments in which Microsoft® SQL Server™ runs have become extremely diverse. To ensure data integrity for our customers who are running SQL Server, it is important that I/O environments provide appropriate functionality.

The purpose of this paper is to explain the Input/Output (I/O) requirements for SQL Server database file operations so that vendors and customers can evaluate and adjust their environments to meet the needs of SQL Server.

Important When planning, deploying, and maintaining a Microsoft SQL Server installation, ensure that the I/O system supports all the factors outlined in this article.

Both Microsoft Knowledge Base and Microsoft SQL Server Books Online (BOL) contain many details related to SQL Server I/O operations. Links to information that is important to your understanding of the material covered in this paper are included where appropriate.

Important It is highly recommended that you fully review the referenced material before continuing with subsequent sections of this paper.

Books Online (BOL) References: All BOL references cited in this paper are taken from the Microsoft SQL Server 2000 Books Online site (updated to include SP3 functionality), which can be found at:

http://www.microsoft.com/sql/techinfo/productdoc/2000/books.asp

Click the Product Documentation link. Then follow the instructions to either download the BOL or browse online.

Terms

This section defines common terms that are used both in this paper and in documents that are referenced in this paper.

ACID Properties

The ACID (Atomicity, Consistency, Isolation, and Durability) properties are a core requirement for SQL Server and other transactional, reliable database products.

Atomicity

A transaction must be an atomic unit of work; either all of its data modifications are performed or none of them are performed.

Consistency

When completed, a transaction must leave all data in a consistent state. In a relational database, all rules must be applied to the transaction's modifications to maintain data integrity. All internal data structures, such as B-tree indexes or doubly linked lists, must be correct at the end of the transaction.

Isolation

Modifications made by concurrent transactions must be isolated from modifications made by all other concurrent transactions. A transaction either sees the data in the state it was in before another concurrent transaction modified it, or it sees the data after the second transaction has completed, but it does not see an intermediate state. This is referred to as serializability because it provides the system with the capability to reload the starting data and replay a series of transactions to end up with the data in the same state it was in after the original transactions were performed.

Durability

After a transaction has completed, its effects are permanently in place in the system. The modifications persist even in the event of a system failure.

Write-Ahead Logging (WAL) Protocol

Write-Ahead Logging is a key technique for providing the ACID properties. Briefly, WAL requires that all the transaction log records associated with a particular data page be flushed to stable media before the data page itself can be flushed to stable media. WAL will be described in more detail in this paper.

Point in Time

A time interval that can be captured as if time were frozen in that moment.

Stable Media

Stable media is often confused with physical storage. SQL Server defines stable media as storage that can survive system restart or common failure. Stable media is commonly physical disk storage, but other devices and certain caching facilities qualify as well.

Many high-end disk subsystems provide high-speed cache facilities to reduce the latency of read and write operations. This cache is often supported by a battery-powered backup facility. The battery backup provides the necessary power to maintain the data in the cache for several days, but implementations vary by manufacturer. Manufacturers can switch out batteries to increase the life of the cache when necessary.

The key is that after the system problem has been corrected, the pending writes in the cache are treated as if the failure or restart never occurred. Most manufacturers' implementations immediately flush pending writes to physical disk during the restart operations.

The following are examples of successful recovery situations actually encountered by Microsoft SQL Server Product Support Services personnel.

Example 1: Hardware failure (CPU board)

Battery backup on the caching controller maintained the data. A new computer was built and the controller and I/O subsystem were attached to the new computer. On restart, the caching controller flushed all cached writes to disk and DBCCs were clean.

Example 2: Power supply failure

Battery backup on the caching controller maintained the data for four days (with battery swaps) until the power supply could be properly updated. On restart, the caching controller flushed all cached writes to disk and DBCCs were clean.

Important Always consult with your hardware manufacturer for proper stable media strategies.

If you have a hardware or power failure, Microsoft strongly recommends the execution of a full DBCC CHECKDB suite and acquisition of the necessary backups to ensure data integrity.

For detailed information about the use of caching controllers and SQL Server, see the following articles on the Microsoft Support Web site.

SQL Server and Caching Disk Controllers
http://support.microsoft.com/default.aspx?scid=kb;en-us;86903

Using Disk Drive Caching with SQL Server
http://support.microsoft.com/default.aspx?scid=kb;en-us;234656

Using Hard Disk Controller Caching with SQL Server
http://support.microsoft.com/default.aspx?scid=kb;en-us;46091

Write Ordering

Write ordering (or write dependency) is the capability of the I/O subsystem to preserve the order of I/O operations. As described previously, stable media can include caching. If a point in time is studied, the stable media should reveal preserved I/O order characteristics.

The order of the I/O operations associated with SQL Server must be maintained. The system must maintain write ordering or it breaks the WAL protocol as described in this paper. (The log records must be written out in correct order and the log records must always be written to stable media before the data pages that the log records represent are written.) After a transaction log record is successfully flushed, the associated data page can then be flushed as well. If the subsystem allows the data page to reach stable media before the log record does, data integrity is breached.

For example, if a computer running SQL Server had to restart after the data page had reached stable media but before the log record, the database recovery may fail. Because the log record for a page modification does not exist, the recovery process cannot determine the proper transactional state of the page. Worse, the log record did not get flushed to stable media so the recovery process is not aware that the page requires rollback and it cannot attempt to correct the problem, thereby leaving the database in an unknown state.

Multichannel and Load-Balancing Systems

Many high-end media environments implement load-balanced systems that can have multiple channels to support I/O requests. These systems must maintain support for I/O ordering. Many of these systems support I/O ordering with a stable media cache and subsequently combine and/or split I/O requests across available subsystem resources to complete the storing to physical media.

For specific information on I/O tuning and balancing, you will find more details in the following document.

NT Server and Disk Subsystem Performance
http://www.microsoft.com/technet/prodtechnol/winntas/maintain/ntserv.mspx

Torn I/O

Torn I/O is often referred to as a torn page in SQL Server documentation. A torn I/O occurs when a partial write takes place, leaving the data in an invalid state. SQL Server 2000/7.0 data pages are 8 KB in size. A torn data page for SQL Server occurs when only a portion of the 8 KB is correctly written to or retrieved from stable media.

SQL Server always checks I/O completion status for any operating system error conditions and proper data transfer size and then handles errors appropriately. Torn pages generally arise after system outages where the subsystem does not complete the entire 8-KB I/O request.

Disk drive manufacturers generally limit data transfer guarantees to sector boundaries of 512 bytes, so if the stable media is a physical disk and the controller does not contain a cache with battery backup capabilities, the I/O request is limited to the final spin/transfer rate of the physical drive. Thus, if an I/O is issued to write 8 KB (for a total of sixteen 512-byte sectors), but only the first three sectors make it to stable media, then the page becomes torn resulting in data corruption. A subsequent read of the 8-KB page would bring in 3 sectors of the new version of the page and 13 sectors of an older version.

SQL Server can enable torn page detection on a per-database basis. A portion of the first 512-byte sector of the page contains the page header. When torn page detection is enabled, the header member contains information about each of the other 512-byte sectors or segments of the 8-KB page. When the page is read in, the torn page information is used to detect a torn page situation.

Torn page detection incurs minimal overhead and is a recommended practice for SQL Server installations.

To read more about torn page detection, see “Torn Page Detection” in SQL Server Books Online.

Log Parity

Hardware manufacturers guarantee sector-size writes so SQL Server 2000 transaction log files are always written with sector-size alignment. Each sector of the transaction log contains a parity flag. This flag can be used to determine the last sector that was correctly written.

During a recovery operation, the log file(s) are scanned for the final sector that was written; the log records can then be used to return the database to the appropriate transactional state.

Mirroring and Remote Mirroring

Mirroring is a common data redundancy and emergency recovery practice. Mirroring can be implemented at a software or hardware level. Mirroring installations have historically been physical implementations of locally attached hardware cabinets. Advances in remote mirroring have made it possible to maintain mirrors across long distances.

Several types of mirroring implementations are available on the market. Some implementations are cache-based; others ensure that the I/O takes place at all mirrored locations before the I/O request is considered complete. Whatever the implementation, write ordering must be maintained.

SQL Server considers a mirror to be a stable-media, point-in-time copy of the primary data. Point in time is an important aspect of this. Strict maintenance of the WAL requirements must occur on the mirrored subsystem to maintain the ACID properties of the data. The mirrored subsystem must mimic the exact points in time as experienced in the primary data.

For example, many high-end installations contain multiple I/O storage devices. If database log files are placed on one mirror set and data files on another mirror set, write ordering cannot be directly maintained across the separate hardware components. Without extended capabilities, the log and data page write order on the mirror devices cannot be maintained with point-in-time capabilities. Extended mirror capabilities are needed to ensure that write ordering can be maintained across multiple physical mirrored devices. These are often referred to as Mirror Groups or Consistency Groups.

The SQL Server 2000 High Availability Series expounds upon remote mirroring. For more information, see the following document.

Implementing Remote Mirroring and Stretch Clustering
http://www.microsoft.com/technet/prodtechnol/sql/2000/deploy/hasog05.mspx

Forced Unit Access (FUA)

Forced Unit Access (FUA) occurs when a file is opened (by using CreateFile) with the FILE_FLAG_WRITETHROUGH flag. SQL Server opens all database and log files with this flag.

The flag indicates that on any write request the FUA bit should be sent with the request to the subsystem. This bit indicates to the subsystem that data must reach stable media before the I/O is to be considered complete and the operating system signaled that the I/O is complete. No intermediate cache should be used that is not considered stable media. In other words, the write should go directly to the stable media, a process that is called writethrough.

This prevents problems that occur when a cache (such as an operating system cache that is not battery backed) accepts the I/O and informs SQL Server that the I/O is complete when in fact it has not yet been stored to stable media. Without this capability, SQL Server could not rely on the system to support WAL protocol needs.

Check with your manufacturer to determine their FUA handling. Some hardware treats the FUA status as an indication that the data must be stored on physical disk (even if a battery-backed cache is available). Others consider a battery-backed cache to be stable media and FUA-compliant. Different implementations can have profound effects on SQL Server performance. A subsystem that supports a stable media cache allows write operations to complete faster than a subsystem that requires that the data be written to the physical media.

Important IDE disk specifications and implementations do not have clear standards for how the FUA request is handled. SCSI disk specifications and implementations use the FUA request to disable physical disk caches and other caching mechanisms. In many IDE implementations, the FUA request is simply discarded by the IDE hardware, thereby making this type of subsystem unsafe to use with SQL Server or with any other product that relies on the FUA behavior. Because of the need to honor the FUA setting, some IDE drive manufacturers have utilities that allow IDE drive caches to be disabled, making them safe for use with SQL Server.

Important Some versions of Microsoft Windows® do not always propagate the FUA bit to the hardware. Corrections have been made starting with Windows 2000 Service Pack 3 (SP3) to always propagate the FUA bit. For backward compatibility, Microsoft has produced a utility to control the operating system behavior.

Use of the utility to disable FUA behavior for an SQL Server installation should be limited to stable media caches.

This utility is located on the Microsoft Web site. See the following:

Obtain the Dskcache.exe Tool to Configure the "Power Protected" Write Cache Option
http://support.microsoft.com/default.aspx?scid=kb;en-us;811392

Data Pages

The SQL Server database page size is 8 KB. Each page contains a header with fields such as Page Number, Object Id, LSN, Index Id, Torn bits, and Types. The actual row data is located on the remaining portion of the page. The internal database structures track the allocation state of the data pages in the database.

Data pages are also referred to as pages.

Page Number

A page number is a value from 0 through ((Max File Size/8 KB)-1). The page number multiplied by 8 KB provides the offset in the file to the first byte in the page.

When a page is read from disk, the page number is immediately checked to ensure that the proper offset was returned (the page number in the header is compared to the expected page number). If this is not the case, SQL Server will generate Error 823.

Object ID

This is the ID of the object to which the page is assigned within the schema of the database. A page can be assigned to only a single object. When the page is read from disk, the object ID is checked on the page. If the object ID does not match the expected object ID, SQL Server will generate Error 605.

SQL Server often performs its writes on page-sized, 8-KB, or larger boundaries.

Extents

SQL Server generally (except for nonmixed extents) allocates space an extent at a time. An extent is eight 8-KB pages, or 64 KB. SQL Server often performs reads in extent-sized (64 KB or 128 KB) boundaries as well.

Buffer Pool

The buffer pool is also referred to as the BPool. The BPool consumes the majority of the user mode address space leaving only a few 100 MB of the virtual address range free for thread stacks, DLLs, and other activities. The buffer pool is reserved in large chunks but the working page size of 8 KB is maintained to match the database page size.

Hardware Read Cache

The hardware read cache is commonly a read-ahead cache used by the controllers. Depending on the size of the available cache, the read-ahead cache is used to retrieve more data than the actual read request may have asked for.

The hardware read cache and read-ahead will be helpful to an application whose data is commonly of a contiguous nature and is retrieved in a reasonably contiguous manner, such as OLAP scans or a reporting application.

Because the hardware read cache removes some of the cache memory that could be used to support write requests, it can have a negative effect on transactional installations (OLTP) that require that data be written at high rates.

Important Some controllers will not do read-ahead if the size of the read request is larger than 16 KB. If the primary application is Microsoft SQL Server, the hardware read-ahead activity does not provide any benefit because I/O read requests can occur for sizes larger than 16 KB. Check with your hardware vendor for complete details and recommendations when running SQL Server.

Hardware Write Cache

The hardware write cache not only caches write requests but also fulfills read requests if the data is still available in the hardware write cache. This is a commonly used I/O caching mechanism.

Hardware write cache capabilities can be critical in maintaining OLTP performance goals. With the proper battery backup and algorithms, the hardware write cache can secure the data safely (on stable media) as well as increase the speed of an application like SQL Server by hiding much of the true physical I/O time.

Error 823

SQL Server error 832, "I/O error <error> detected during <operation> at offset <offset> in file '<file>'" occurs when:

A ReadFile, WriteFile, ReadFileScatter, WriteFileGather, or GetOverlappedResult operation results in any operating system error code.

The page number on the page read from disk is not the expected page ID.

The data transfer size is not valid.

A torn read is detected when torn page detection is enabled.

A stale read is detected when stale read detection is enabled.

For extended details on the 823 error, see the Microsoft Web site topic:

Error message 823 may indicate hardware problems or system problems
http://support.microsoft.com/default.aspx?scid=kb;en-us;828339

Error 605

SQL Server error 605, "Attempt to fetch logical page (x:yyy) in database 'dddd' belongs to object 'aaa', not to object 'tttt'." occurs when:

The object ID on the page does not match the object ID that is expected on the page.

SQL Server error 605 is detected each time a page is retrieved for a scan. The scan is associated with a specific object. If the scan ID does not match the object ID that is stored on the page, the error is encountered. This occurs the first time the page is used and may occur during subsequent in-memory lookups of the page.

Microsoft SQL Server I/O Design

To fully understand SQL Server I/O design, it is important to understand the basics of database file I/O operations, transaction log I/O operations, and transactional consistency maintenance.

The I/O and transactional design of SQL Server ensures that the ACID properties are fully maintained. This section focuses on the Durability property and its associations with the operating system and hardware environments.

Write-Ahead Logging (WAL) Protocol

A key to ACID property maintenance is the WAL protocol. The WAL protocol requires that all transaction log records associated with a particular data page be flushed to stable media before the data page can be flushed to stable media.

Microsoft SQL Server 2000 and Microsoft SQL Server 7.0 use 8-KB data pages and sector-aligned transaction log buffers. Earlier versions of SQL Server use 2-KB data and log pages.

The following example is a code example taken from the following Microsoft Knowledge Base article. See the article for more details.

SQL Server 7.0 and SQL Server 2000 Logging and Data Storage Algorithms Extend Data Reliability
http://support.microsoft.com/default.aspx?scid=kb;en-us;230785

Consider the following example that demonstrates how SQL Server upholds the WAL protocol for in INSERT statement. For this example, assume that there is no index and the page that is affected is page 150.

BEGIN TRANSACTION
   INSERT INTO tblTest VALUES (1)
COMMIT TRANSACTION
Statement Actions performed

BEGIN TRANSACTION

A BeginTran log record is written to the log cache but there is no need to flush to stable media because SQL Server has not made any physical changes.

INSERT INTO tblTest

1.

Page 150 is not currently present in the SQL Server cache so data page 150 is retrieved into the SQL Server data cache.

2.

Appropriate locks are obtained and the page is latched.

3.

An Insert log record is built and added to the log cache.

4.

A new row is added to the data page and the page is marked dirty.

5.

The latch is released.

6.

The log records associated with the transaction do not need to be flushed at this point because all changes remain in volatile storage.

COMMIT TRANSACTION

 7.   A Commit log record is generated. The log records associated with the transaction (and all previous log records) must be written to stable storage. The transaction is not considered committed until the log records are correctly flushed to stable media. (Log is hardened.)

 8.   Data page 150 remains in the SQL Server data cache and is not immediately flushed to stable media. Flushing the data page to stable media is not necessary because after the log records are properly secured, it is possible for recovery to redo the operation based on those log records.

 9.   Transactional locks are released and the batch is considered complete.

Locking and latching are separate issues when maintaining the WAL protocol. Locking maintains the transactional integrity of the data while latching maintains the physical integrity of the data. In the previous example, SQL Server 7.0 and SQL Server 2000 hold the latch on page 150 for only the time necessary to perform the physical changes on the page, not the entire time of the transaction. The appropriate lock type is established to protect the row, range, page, or table as necessary.

For more details on lock types, see the sections that cover locking in Microsoft SQL Server Books Online.

Looking at the previous WAL example in more detail, you might ask what happens when the lazy writer process or the checkpoint process runs before the COMMIT takes place but after the page has been modified.

Statement Actions performed

BEGIN TRANSACTION

A BeginTran log record is written to the log cache area but there is no need to flush to stable media because SQL Server has not made any physical changes.

INSERT INTO tblTest

1.

Page 150 is not currently present in the SQL Server data cache so data it is retrieved into the data cache.

2.

Appropriate locks are obtained and the page is latched.

3.

An Insert log record is built and added to the log cache.

4.

A new row is added to the data page and the page is marked dirty.

5.

The latch is released.

6.

The log records associated with the transaction do not need to be flushed at this point because all changes remain in volatile storage.

Lazy writer or checkpoint locates page 150 in the buffer pool

Page 150 is currently marked as dirty so both of the processes are aware that the database page should be flushed to stable storage.

1.

Latch page 150 to prevent further modifications.

2.

Issue a request to log manager to flush all log records up to and including the LSN value stored on page 150. (Log is hardened.)

3.

Wait for all log records to be flushed successfully to stable media.

Issue I/O request to flush page 150 to stable media.

Note that the example does not require a commit. If the page is dirty, the log records can be flushed and subsequently the page as the WAL protocol specifies. The locks protect the commit view of the data and if a rollback occurs, the compensating recovery activities will restore the page to the proper state. If this did not work in this way, SQL Server would be limited to a modification that was no larger than physical memory.

The lazy writer and checkpoint processes both issue all appropriate flushes to stable media for transaction log records associated with a dirty page. This maintains the WAL protocol rule that specifies that a data page can never be written to stable media until the associated transaction log records have been flushed.

To read more about the transaction log and write-ahead logging see the topic, “Write-Ahead Transaction Log” in SQL Server Books Online.

Additional information is located on the Microsoft Web site in the following document:

SQL Server 7.0 and SQL Server 2000 Logging and Data Storage Algorithms Extend Data Reliability
http://support.microsoft.com/default.aspx?scid=kb;en-us;230785

Log Sequence Number

The log sequence number (LSN) value is a three-part, uniquely incrementing value. It is used for maintaining the sequence of the transaction log records in the database. This allows SQL Server to maintain the ACID properties and to perform appropriate recovery actions.

When a modification occurs, a log record is generated with a new LSN value. The same LSN value is stored (replaces the previous LSN value in the page header) in the data page header so the last log record and matching data page can be associated with each other.

To learn more about the transaction log architecture, see “Transaction Log Logical Architecture” in SQL Server Books Online.

Latching

SQL Server uses latches to provide data synchronization. A latch is a user-mode reader-writer lock implemented by SQL Server. Each data page in memory has a buffer (BUF) tracking structure. The BUF structure contains status information (Dirty, On LRU, In I/O) as well as a latch structure.

Locking maintains the appropriate lock activity; latching controls physical access. For example, it is possible for a lock to be held on a page that is not in memory. The latch is only appropriate when the data page is in memory (associated with a BUF).

The following illustration shows a high-level view of the SQL Server 2000 buffer pool.

Figure 1

Figure 1

Scatter-Gather

Starting with Microsoft SQL Server 7.0, the Microsoft Win32 APIs WriteFileGather and ReadFileScatter are used. The WriteFileGather function gathers data from multiple discontinuous buffers and writes the data to a file. The ReadFileScatter function reads data from a file and distributes the data into multiple discontinuous buffers.

These APIs allow SQL Server to avoid multiple physical I/O requests. For example, during the checkpoint process up to sixteen 8-KB pages can be flushed with a single WriteFileGather invocation. Before using WriteFileGather, SQL Server had to issue an I/O request for each data page or it would have to sort and buffer a larger request itself.

Important Scatter-gather capabilities are hardware specific. When the hardware does not support scatter-gather capabilities, the operating system must intervene and issue separate I/O requests. To maximize Microsoft SQL Server I/O performance, ensure that your subsystem natively supports scatter-gather I/O operations.

To learn more about SQL Server’s use of scatter-gather to improve performance, see the following document.

Performance Enhancements for SQL Server Under Windows NT
http://support.microsoft.com/default.aspx?scid=kb;en-us;160606

Transaction Log I/O—WriteFile

For transaction log operations, SQL Server uses WriteFile instead of WriteFileGather. WriteFileGather requires I/O in operating system, page size boundaries. This requirement would mean that each log record would be at least 4 KB. WriteFile is used instead to allow smaller writes on sector boundaries.

Asynchronous I/O

All SQL Server transaction log and database file I/O is performed by using an OVERLAPPED structure, which facilitates the use of asynchronous I/O. The SQL Server buffer pool and file manager contain sophisticated I/O facilities. Appropriate reader/writer latches are used to maintain data integrity during asynchronous I/O operations.

SQL Server uses the Win32 API calls as follows.

API Common Usage

CreateFile

Used to create and open database and log files. The flags FILE_FLAG_OVERLAPPED, FILE_FLAG_WRITETHROUGH, and FILE_FLAG_NO_BUFFERING are specified to avoid nonstable media caching.

WriteFile

Primarily used by the log manager and backup manager to handle I/Os.

ReadFile

Primarily used by the log manager and backup manager to handle I/Os.

WriteFileGather

Primarily used by the buffer pool to write page groups (up to sixteen 8-KB pages in a group).

ReadFileScatter

Primarily used by the buffer pool to read pages into the buffer pool. Can be used for single page requests as well as read-ahead requests. Read-ahead requests are generally 128 pages for each group but can be as many as 1,024 pages when running Microsoft SQL Server Enterprise Edition.

HasOverlappedIoCompleted

Used to determine the status of I/O requests.

GetOverlappedResults

Used to determine success of the I/O requests.

Note Sort and spool operations share some mechanisms with the SQL Server buffer pool and file manager to perform necessary I/O operations.

Also, note that SQL Server does not always service the completion of the I/O on the same worker that posted the I/O request. Completion of an I/O in SQL Server is done by a yielding worker on the same User Mode Scheduler (UMS) in which the I/O was posted. Mechanisms in SQL Server establish callback routines that are invoked when the I/O completes. The callback is an SQL Server-specific mechanism and not alert-based like the ReadFileEx or WriteFileEx functions.

For example, if a data page read completes, the callback routine will check for an operating system return code of zero (GetLastError value), ensure that the bytes transferred are correct, check for torn page errors, ensure that the page number is correct, and perform other sanity checks.

Flushing a Data Page To Disk

Three primary mechanisms trigger the flush of a data page to disk. However, each mechanism uses the same internal routine in the buffer pool to achieve the transfer.

Lazy write (LRU and memory-pressure based)

Checkpoint (recovery-interval based)

Eager write (nonlogged I/O based)

To efficiently flush writes to disk, WriteFileGather is used. This allows SQL Server to bundle consecutive dirty pages into a single write request.

SQL Server uses the following steps to flush a single page.

1.

Latch the page to prevent further modifications.

2.

Ensure that log records up to and including the LSN on the page are flushed to stable media.

3.

Establish proper entries for the WriteFileGather invocation.

SQL Server uses the following steps to set up another page for flushing and repeats for up to 16 total pages inclusive of the first page.

1.

Do a hash lookup for the next contiguous page. For example, if the page to be flushed were page 100, SQL Server searches for page 101 in the buffer hash array.

2.

If the page is not located, then the end of contiguous I/O block is established and the I/O is posted.

3.

If the page is located, acquire latch to prevent further modifications if the page may be dirty.

4.

Check to ensure that the page is dirty and needs to be written. If not, release the latch and consider the end of contiguous I/O block as established and submit the asynchronous I/O request.

5.

If dirty, follow the steps preceding these that tell you how to flush a single page.

After the set of pages to be flushed is determined, the WriteFileGather function is invoked to post (Async / OVERLAPPED) the I/O request with the associated callback function to complete the I/O operation.

When SQL Server determines that HasOverlappedIoCompleted returns TRUE, GetOverlappedResults is used to gather completion information from the system and the callback function is invoked. The callback makes an appropriate determination as to the success of the I/O operation and releases the latch on each page.

Lazy Writer

The lazy writer for SQL Server 2000 and SQL Server 7.0 attempts to locate up to 16 unique pages for each sweep to return to the free list. If the page reference count has dropped to zero, the page is eligible for return to the free list. If the page is marked dirty, the log records and page date will be flushed.

Thus, it is possible for the lazy writer to flush 16 * 16 pages to disk in a single sweep. This is efficient because many of the pages will remain in the SQL Server buffer pool but are now in a clean state. I/O is done in the background from the primary SPID (server process ID). When the lazy writer needs additional buffers for the free list, the buffers may not need to be flushed to disk but are unhashed and returned to the free list.

Checkpoint

The SQL Server 2000 checkpoint process periodically sweeps the buffer pool for buffers that contain pages from a specified database and flushes all dirty buffers to stable media. This makes recovery shorter because roll forward operations have less physical work to complete.

As described earlier, the checkpoint process uses the same I/O approach to post up to 16 pages in a single I/O. Because the I/O is posted (OVERLAPPED), checkpoint does not wait for each I/O request to complete immediately. Checkpoint continues to track posted and completed I/Os but attempts to maintain a high level of outstanding I/Os (for example 100 write requests continuously outstanding). This maximizes I/O throughput and reduces checkpoint runtime.

Before the introduction of WriteFileGather, SQL Server sorted the buffers for a specified database in page order and issued I/O requests in page order. This required many physical I/O requests because the page order of the flush is not in contiguous memory location order. However, it often kept the physical subsystem mechanisms in physical locations that are in close proximity to make the I/O requests complete faster.

With the older design, an elevator seek can be a problem. Issuing many I/Os in page order generally results in a similar "on disk" order. By pushing the subsystem hard with many I/Os located at similar locations, the disk drive would service these I/Os before I/Os that might have been outstanding longer.

With WriteFileGather, SQL Server can sweep the buffer pool without requiring any physical ordering relationship to the pages on disk. By gathering 128 KB (sixteen 8-KB pages) in a group, SQL Server is able to transfer blocks of data with much fewer physical I/O requests. This allows the checkpoint process to maintain its speed while the random nature of the I/O requests deters any elevator seeking that could affect other I/O operations.

All databases, except for tempdb are checkpointed. Tempdb does not require recovery (it is recreated every time SQL Server starts) so flushing data pages to disk is not optimal for tempdb and SQL Server avoids doing so.

Checkpoint protects the system from I/O flooding by serializing checkpoint processes. Only one checkpoint at a time can run to completion. The checkpoint and lazy writer processes also communicate with each other to control I/O queue depths.

Eager Write

Microsoft SQL Server 2000 uses eager writes to post data pages associated with nonlogged operations (commonly bulk insert/select into). This allows the async capabilities of the I/O patterns to keep the dirty pages flowing to disk without dirtying large and unwanted portions of the buffer pool. The same mechanism as that used by the lazy writer and checkpoint processes to post I/O operations is used.

Microsoft SQL Server 7.0 does not implement the eager write actions but instead issues a checkpoint at commit-transaction time to flush all buffers for the database. This can cause multiple nonlogged operations to be serialized because only a single checkpoint can be active.

Important Lazy writer, checkpoint, and eager write do not wait for the I/O to immediately complete. They always post the I/O with WriteFileGather with the OVERLAPPED option and continue with other work, checking for I/O completion success at a later point in time. This allows SQL Server to maximize both CPU and I/O resources for the appropriate tasks.

Shutdown and Recovery Interval

An orderly shutdown action performs a checkpoint of all databases, closes out all internal database tracking structures, and exits the SQL Server process.

The recovery interval controls the checkpoint target. When the interval is elongated, more dirty pages are allowed in memory before checkpoint is triggered.

The current version of Microsoft Windows generally requires a successful, orderly shutdown of SQL Server in 60 to 120 seconds.

Clustering Implementations

Clustering implementations can be affected by the shutdown processing.

If this interval is exceeded for an instance in a failover cluster, the cluster processing may engage in a forced termination of the SQL Server resources and the system will engage in appropriate failover activities as well.

The SQL Server cluster resource marks the status of SQL Server as failed. In doing so under a "move group" scenario, the cluster process takes over and forces the resources to be physically controlled by the subsequent node.

Adjustment of the recovery interval can result in checkpoint requiring a lengthy time to complete, exceeding the provided interval, and resulting in aggressive failover activities. Aggressive failover scenarios do not pose any specific dangers.

Microsoft strongly recommends maintaining the default recovery interval to ensure optimal recovery metrics and to function cleanly within the current cluster resource constraints. If the recovery interval is extended beyond 60 seconds, it is possible that clustered instances will be forced offline in an aggressive manner. While the aggressive actions are not unreasonable, they are undesirable. If the recovery process seems to be having significant negative affects on transactional throughput, Microsoft recommends that the database layout, physical file placement, and physical I/O channel be adjusted instead of the recovery interval to facilitate throughput needs.

Recovery Interval Adjustments

Several specific conditions (side effects) can arise when the recovery interval is adjusted. Weigh these carefully before adjusting the recovery interval.

Dirty Page Latency – A page is considered dirty when data modifications have taken place. A dirty page cannot be removed from the SQL Server buffer pool until the associated log records have been written and the page itself written to stable media. Increasing the checkpoint interval (by increasing the recovery interval) on a busy system moves the pressure of handling dirty pages to the lazy writer code line. This can result in overall performance degradation because the lazy writer is not designed to perform checkpoint-like activities.

The lazy writer does perform proper activity on the dirty pages to ensure data integrity and free list maintenance but, unlike the checkpoint process, it is not designed to remove the dirty page I/O latency. Checkpoints allow dirty pages to be written more aggressively. Leaving the checkpointing actions to the lazy writer introduces latency because the lazy writer is forced to perform I/O to age a buffer instead of simple, in-memory operations to maintain the free list(s). If you have adjusted the recovery interval, you should watch the lazy writer performance counter(s) activity closely.

Longer Checkpoint – Increasing the recovery interval can result in more in-memory dirty pages. The more pages that are dirty, the more pages checkpoint will have to flush to disk during its sweep of the SQL Server buffer pool. Longer checkpoint duration is not a problem but exposes the potential for longer recovery intervals and drives the disk harder for a longer interval.

Longer Recovery – Increasing the recovery interval can result in increased recovery time. If SQL Server experiences an unorderly shutdown (the process terminates unexpectedly or a power outage occurs, for example), on startup, the recovery manager is responsible for ensuring that the database returns to the proper transactional state. If checkpoint is running less frequently, resulting in more active dirty pages, a nonorderly shutdown requires that the recovery manager perform more roll-forward and possibly rollback operations to return the database to the correct and consistent transactional state. A key factor affecting the performance of this work is the fact that the SQL Server buffer pool is cold (there are no pages in memory) at the time of recovery. Recovery has to read in the appropriate database pages and make modifications. This can add recovery latency, which is undesirable in a production environment. The increased recovery interval time is often counterproductive to the overall goal of maximized up time.

For example, assume that under a constant load, checkpoint needs to flush 250 MB of dirty buffers every minute. Based on the checkpoint algorithm, if you extend the recovery interval to 10 minutes, the amount of data to be flushed will be 2,500 MB if all other factors remain constant. If the checkpoint duration is longer, it drives the disk for a more pronounced interval but individual pages are handled in the same way, ensuring that overall concurrency is maintained. The 2,500 MB of dirty pages require a significant amount of more work from recovery as well.

Recovery Model Considerations

Microsoft SQL Server 2000 introduced updated database recovery models (the Full, Bulk-Logged, and Simple recovery models). The application workload and recovery models directly affect the types of I/O patterns. The application, hardware solution, and recovery model that maximizes recovery business requirements should be selected.

Flushing a Log Record To Disk

Log records are flushed to disk in much the same manner as data pages. The log manager is responsible for all writes for all transaction log records for all databases. You can select from sysprocesses to see the log manager SPID assignment.

When a request to flush all log records up to a certain LSN is requested by any worker on the system, the request is queued to the log manager. The worker then waits for a response from the log manager specifying that the I/O has completed successfully. The log manager retrieves from the queue and formats the request; it then posts the I/O on sector-aligned boundaries.

The I/O is posted with WriteFile using the OVERLAPPED (async) mechanisms. The log manager can then return to service other queued requests. When the I/O is completed, the completion routine is run to check the success of the write. If the write is successful, the waiting workers can be signaled to continue their operations.

Write ordering is critical at this stage. Because multiple log write requests can be posted for the same transaction log, the LSN order must be maintained.

For example, pages 50, 100, and 200 are modified by separate transactions. Page 50 was modified first, then 100, and then 200. LSN flush requests occurred for page 50, 100, and 200 and were put in motion in the same order. If the log record(s) for page 50 and 200 are flushed to stable media, only the flush to LSN for page 50 is considered done and SQL Server may only flush page 50. The LSN 100 must be flushed to stable media before 100 and then 200 can be considered flushed to the LSN. (Log is hardened.)

Write ordering is a key to data integrity and SQL Server design.

Read-Ahead

SQL Server 2000 uses ReadFileScatter to perform read-ahead operations. SQL Server uses sophisticated algorithms to retrieve data pages that are going to be used in the immediate future.

For example, if you run a query that can use an index to determine applicable rows, a read-ahead may occur on the actual data pages that are needed to complete the select list. As index entries are identified, SQL Server can post OVERLAPPED (async) I/O operations for the data pages that will be used in upcoming steps of the query plan. This is how a query using a bookmark lookup operator uses read-ahead.

This example is just one of many read-ahead situations that SQL Server can use. Allowing the index searching to continue while the data page I/O is in progress maximizes the CPU and I/O of the system. The I/O is often completed by the time it is needed so other steps in the plan have direct memory access to the needed data and do not have to stall while waiting on I/O.

When a read-ahead is posted, it can be from 1 to 1,024 pages. SQL Server limits a single read-ahead request depth to 128 pages on most editions. However, Microsoft SQL Server Enterprise Edition raises the limit to 1,024 pages.

SQL Server uses the following steps to set up read-ahead.

1.

Obtain the requested amount of buffers from the free list.

2.

For each page:

1.

Determine the in-memory status of the page by doing a hash search.

2.

If found to be already in memory, set up the read-ahead request to immediately return the buffer to the free list upon I/O completion.

3.

Establish the proper I/O request information for ReadFileScatter invocation.

4.

Acquire I/O latch to protect buffer from further access.

5.

If the page is not found in hash search then insert it into the hash table.

3.

Issue the ReadFileScatter operation to read the data.

When the I/O operation is complete, each page is sanity checked for a valid page number and torn page errors. In addition, various other data integrity and safety checks are performed. The I/O latch is then released so the page is available for use if it is located on the hash chain. If the page was determined to be already in memory, the page is immediately discarded to the free list.

This process shows the key factors of SQL Server I/O patterns. Read-ahead goes after pages that can already be in memory or not allocated. Because SQL Server maintains the in-memory buffers and hash chains, SQL Server tracks the page’s state. Importantly, read-ahead processing opens the door for overlapping read and write requests at the hardware level.

If a page is already in memory when the read-ahead request is posted, the contiguous read is still needed and is faster than breaking up read requests into multiple physical requests. SQL Server considers the read to be unusable for the page in question, but many of the pages around it may be usable. However, if a write operation is in progress when the read is posted, the subsystem has to determine which image of the read to return. Some implementations return the current version of the page before the write is complete; others make the read wait until the write completes; and yet others return a combination, showing partially new data and partially old data. The key is that SQL Server will discard the read as unusable but the subsystem needs to maintain the proper image for subsequent read operations. The in-progress write, when completed, must be the next read image returned to the server running SQL Server.

Do not confuse read-ahead with parallel query plans. Read-ahead occurs independently of the parallel query plan selection. The parallel plan may drive I/O harder because multiple workers are driving the load, but read-ahead occurs for serial and parallel plans. To ensure that parallel workers do not work on the same data sets, SQL Server implements the parallel page supplier to help segment the data requests.

SQL Server has added increased diagnostics to report previously unreported read failures. The Microsoft Web site contains the following Knowledge Base article that provides diagnostic installation and usage instructions.

Additional diagnostics added to SQL Server to detect unreported read failures
http://support.microsoft.com/default.aspx?scid=kb;en-us;841776

Microsoft SQL Server Core I/O Requirements

The SQL Server 2000 I/O subsystem has a core set of requirements for maintaining data integrity. If your system is fully compliant in the following areas, then SQL Server is able to maintain the ACID properties of your database(s).

Stable Media

Any system running SQL Server must provide stable media capabilities for the database log and data files. If the system has something like a nonbattery backed cache or perhaps caching enabled on disk, it is not safe for SQL Server installations.

Ensure that your system has proper caching attributes to secure the data to stable media.

Write Ordering

SQL Server is designed to maintain the WAL protocol as described earlier in this paper. The underlying environment plays a pivotal role in the maintenance of the protocol. Write ordering must be maintained.

With any system, but specifically for remote mirroring implementations, write ordering is critical to maintain a point-in-time view of the data. Many remote mirroring vendors implement generation logic to maintain physical write order even when the write operations are transmitted between remote caches with alternate protocols.

Torn I/O Prevention (Split I/Os)

For SQL Server, the 8-KB blocks need to be handled as a single block of data. Systems that split I/Os must be configured to avoid splitting I/O requests into smaller blocks. Some dynamic disk and volume managers can be configured with block and cluster sizes that are smaller than 8 KB or not on 8-KB boundaries. These systems may split the SQL Server I/O request across physical system components. In doing so, they can introduce the possibility of torn pages and they can destroy true write ordering precedence.

Ensure that your system does not allow data to be broken down in such a manner as to introduce torn page possibilities.

Problems, Pitfalls, and Samples

The problems, pitfalls, and samples described in this section are issues encountered by the Microsoft SQL Server Support and Development staff. Many of them have resulted in configuration changes and/or other changes such as firmware, driver, or other levels of correction outside SQL Server.

Because a wide variety of issues can arise and a number of manufacturers are involved in the field of stable media storage, Microsoft strongly recommends that you contact your hardware and software vendors and make sure that you are running an implementation that is compliant with SQL Server 2000.

Stale Reads and Lost Writes

What is a hardware-level stale read compared to a lost write?

Because a stale read can appear as a lost write or a lost write can appear as a stale read, explicit definition of the terms is appropriate.

The following definitions assume that all operating system calls are successful and that the API routines are used correctly by the user mode application.

Stale Read

Data returned through a ReadFile or ReadFileScatter call does not represent the last successful write operation.

Lost Write

Data sent through a WriteFile or WriteFileGather is never represented by stable media.

Examine the following set of diagrams closely. Assume that the ExpandFile image is what the stable media looks like.

A stale read is when the Write Image, shown in the diagram as "A" payload, is successfully written to disk to replace the initial "Z" payload. However, the next read of the same bytes (the offset) of the file still returns the "Z" payload Read Image.

It is a stale read if the stable media contains the "A" image but the hardware cache returns "Z" payload.

It is a lost write if the stable media contains the "Z" payload and the write of the actual "A" payload was lost.

Stale Read Example

This is an example of a stale read situation. Remember that read-ahead for SQL Server will read in a large block but it will disregard pages that are of unknown state. On completion of a read, it will return the buffer immediately to the free list when a page is deemed already in memory at the start of the read-ahead I/O request.

For the example, assume that pages 107 and 108 are in the SQL Server buffer pool and are dirty.

Write Page 107

Lazy writer posts write request.

Write Page 108

Lazy writer posts write request.

Page 107 write completes

I/O request completes and the lazy writer removes the page from the cache and places its buffer on the free list.

Read posted for 100 through 115

Read-ahead is used to read in the data. Only page 108 is found in memory. Read-ahead will steal the needed work buffer but will not hash it as it is already in memory.

Read completes

The read completes. KEY: The data for page 108 is unknown, as it has not completed at the hardware level. SQL Server does not need the duplicate, so the work buffer is returned directly to the free list at the completion of the read.

Note This is the version of page 108 stored in hardware read-ahead cache now.

Page 108 write completes

BUG: Read-ahead hardware cache is not invalidated

Lazy writer ejects page 108 from cache and places its buffer on the free list.

Read request for page 108

Requires that a physical read take place but the stale image of the page is returned from the hardware read-ahead cache, not the on-disk version.

Trace Flag 818

The instrumentation added with trace flag -T818 tracks the last 2,048 page write operations. During a successful write I/O completion (proper page ID, bytes transferred successfully, and the proper OS error codes), the DBID, Page ID, and LSN are recorded in a ring buffer. If a failure occurs, error 823 is raised.

When an 823 or 605 error is detected, SQL Server looks in the ring buffer for the LSN value that was on the page during the last write. If not correct, extra information is added to the SQL Server error log. The information indicates the type of error along with both the expected and the retrieved LSN.

The extended LSN information outlined here appears in the SQL Server error log. The LSN returned is from the read and is clearly older (stale) than the value used during the last write.

SQL Server has detected an unreported OS/hardware level read or write 
problem on Page (1:75007) of database 12 
LSN returned (63361:16876:181), LSN expected (63361:16876:500)
Contact the hardware vendor and consider disabling caching mechanisms to
correct the problem

SQL Server 2000 Service Pack 4 (SP4) refines the design of –T818 into a hash table implementation. A finite amount of hash bucket entries is allowed but more than 2,048 are allowed on 32-bit installations and even more entries are allowed on 64-bit installations.

Because it is implemented as a hash table, the stale read check can occur on every read, not just on those pages identified with a previous 823 or 605 error. This check occurs like other standard checks for object ID on the page (605) and page number (823) error conditions. Because it does the check on every read, it can catch situations where the page ID and object ID are correct but the rows on the page would have been damaged.

For example if a row were inserted, the page flushed, and a stale read occurred (row missing), the object ID and page ID would be valid so the older implementation may not have flagged the stale read condition. The new design will detect the LSN mismatch and flag it as a new 823 error condition.

Torn Pages

SQL Server database pages are 8 KB in size, whereas the typical transfer size for the hardware is 4 KB using 512-byte sectors. When you start adding alternate RAID configurations, the hole can show up as torn reads. The timing of the reads and writes can overlap on different drives so you may get partial old and partial new data. Again, the bug is that after the write, not all portions of the read-ahead cache are invalidated. The damaged image remains in the read-ahead hardware cache until it is forced out.

Flushing Hardware Cache Example

It is possible to perform operations that cause the hardware cache to be flushed. The flushing action can resolve error conditions if they are transient.

Some techniques to accomplish this can be triggered with SQL Server.

Issue dbcc dropcleanbuffers to remove all the buffers from the SQL Server buffer pool.

Issue dbcc checkdb on the database in question.

This can correct the problem of transient, repeated corruption behavior. The technique causes checkdb to do a large number of read requests, which forces the hardware cache to turn over. This turnover ejects the problem sectors from the hardware cache and forces the proper physical read. This obtains the correct image and SQL Server magically appears to correct the problem.

SQLIOStress.exe

The SQLIOStress test program (version 4.00.020 and later) contains special patterns to detect stale-read/lost-write problems quickly. The (-H) parameter was added to be more aggressive at the read-ahead logic simulation and quickly triggers the bad behavior.

The following is a sample of SQLIOStress output with the (-H) enabled on a controller that is exhibiting the problem.

When the problem is encountered, the write and the following read image are dumped to the log as well as the results of the API calls that were made.

10/02/03 16:56:26 00001832    ERROR: Stale read check failure. Page image returned does not match previous write. Check hardware and caches. Read size was 8192

10/02/03 16:56:26 00001832    

10/02/03 16:56:26 00001832    ---------------- Write Image

10/02/03 16:56:26 00001832    Overlapped: 0x0AA91000 Used: Y Complete: 1 Event: 0 Offset: 41951232 OffsetHigh: 0 Internal: 0 Internal High: 8192

10/02/03 16:56:26 00001832    Sector: 0      LSN: 8        Page: 5121  Address: 0x0D16DFA8

10/02/03 16:56:26 00001832     [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAA]

10/02/03 16:56:26 00001832    Sector: 15      LSN: 8        Page: 5121  Address: 0x0D16FDA8

10/02/03 16:56:26 00001832     [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA]

10/02/03 16:56:26 00001832    ---------------------------------------------------------------------------

10/02/03 16:56:26 00001832    ---------------- Read Image

10/02/03 16:56:26 00001832    Overlapped: 0x0D16DEEC Used: Y Complete: 1 Event: 868 Offset: 41951232 OffsetHigh: 0 Internal: 0 Internal High: 8192

10/02/03 16:56:26 00001832    Sector: 0      LSN: 0        Page: 5121  Address: 0x0AA81000

10/02/03 16:56:26 00001832     [ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZ]

10/02/03 16:56:26 00001832    Sector: 15      LSN: 0        Page: 5121  Address: 0x0AA82E00

10/02/03 16:56:26 00001832     [ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZ]

10/02/03 16:56:26 00001832    ---------------------------------------------------------------------------

10/02/03 16:56:26 00001832    

10/02/03 16:56:26 00001832    Dumping API Trace Information

10/02/03 16:56:26 00001832    ---------------------------------------------------------------------------

10/02/03 16:56:26 00001832    Slot     | TID      | Handle   | Enter Ticks          | Bytes Req| Exit Ticks           | Bytes Ret| API                       | Ret Code | OSError  | Internal | Int High | Offset   | Off High | Event

10/02/03 16:56:26 00001832    10083    | 1832     | 916      | 36747447522368       | 8192     | 36747447613236       | 0        | WriteFileGather           | 0        | 997      | 259      | 0        | 41951232 | 0        | 0

10/02/03 16:56:26 00001832    20088    | 1832     | 0        | 36747476369460       | 0        | 36747476369616       | 0        | HasOverlappedIoCompleted  | 0        | 0        | 259      | 0        | 41951232 | 0        | 0

10/02/03 16:56:26 00001832    50118    | 1832     | 0        | 36747589924652       | 0        | 36747589925212       | 0        | HasOverlappedIoCompleted  | 1        | 0        | 0        | 8192     | 41951232 | 0        | 0

10/02/03 16:56:26 00001832    50119    | 1832     | 916      | 36747589926084       | 0        | 36747589935944       | 8192     | GetOverlappedResult       | 1        | 0        | 0        | 8192     | 41951232 | 0        | 0

10/02/03 16:56:26 00001832    50120    | 1832     | 916      | 36747589955240       | 8192     | 36747590068768       | 0        | ReadFileScatter           | 0        | 997      | 259      | 0        | 41951232 | 0        | 868

10/02/03 16:56:26 00001832    50121    | 1832     | 0        | 36747590069764       | 0        | 36747590069956       | 0        | HasOverlappedIoCompleted  | 0        | 0        | 259      | 0        | 41951232 | 0        | 868

10/02/03 16:56:26 00001832    Duplicates: 459

10/02/03 16:56:26 00001832    50581    | 1832     | 0        | 36747590384800       | 0        | 36747590384928       | 0        | HasOverlappedIoCompleted  | 0        | 0        | 0        | 8192     | 41951232 | 0        | 868

10/02/03 16:56:26 00001832    50582    | 1832     | 0        | 36747590416768       | 0        | 36747590416900       | 0        | HasOverlappedIoCompleted  | 1        | 0        | 0        | 8192     | 41951232 | 0        | 868

10/02/03 16:56:26 00001832    50583    | 1832     | 916      | 36747590417460       | 0        | 36747590417764       | 8192     | GetOverlappedResult       | 1        | 0        | 0        | 8192     | 41951232 | 0        | 868

SQL Error Messages

SQL Server detects many flavors of I/O problems or data integrity damage at run time. An I/O problem or data integrity breach is detected and reported by SQL Server as an error message. The more common errors are 605, 823, 624, and log restore failures.

SQL Server cannot detect some situations. These situations appear as logical problems with the data and commonly generate unexpected application-level error conditions.

Run-Time Errors

Errors 605 and 823 are the results of straightforward run-time checks for the proper page and object IDs. These are easy to catch at run time without a performance penalty. The problem is that stale read data opens up a much larger window of potential error conditions.

Logical Errors

There are many cases (such as 6xx errors) where the data becomes logically inconsistent. (An example is error 624: Could not retrieve row from page by RID because the requested RID has a higher number than the last RID on the page. %S_RID.%S_PAGE, DBID %d.) For example, if you insert a new row into a table but the stale read takes place on the index page, the index insert is lost. It then looks like the index update never took place, so you have more data rows than index rows for this table. It could look like the index keys are improper. If part of a heap table, the RIDs (relative identifiers) could be incorrect because the actual page data is aligned differently.

You can take this scenario into other areas when you start looking at actual data relationships. If one of the pages becomes a stale-read victim, it could look like the insert never took place at all. This might appear as unexpected row counts or PK/FK violations. Perhaps this would appear as if a debit or credit to a user's account never took place.

When the data is suspect, the potential problems become very broad. The data can appear damaged during a checkdb. It could cause run-time problems because index RIDs point to unexpected data areas and it could cause many other problems such as exceptions or assertions.

Log Shipping Errors and Restore Failures

Data corruption or integrity problems can be exposed while attempting a restore operation. For example, stale reads can cause a transaction log restore to fail.

As outlined earlier, the LSN must be unique in one database. In the case of a stale read, it is possible to find two separate log records with the same previous page LSN. SQL Server recovery detects this as a problem and will stop the recovery operation. It is a clear sign that the page was changed, flushed to disk, and read back in; however, the change was not seen due to stale read. The second change uses the stale LSN and the capability to recover the page is lost.

Important This is important because a stale read can quickly invalidate the backup strategy and should be addressed aggressively.

Replication

Replication can use the transaction log as a data source. When something like a stale read condition damages the transaction log, it also damages the replication data source. The damaged source can lead to problems with logical consistency of the replicated data.

For example, when replication is involved, the problem can span multiple computers. In a merge replication scenario, if changes are lost because of a stale read situation on one computer, it could affect the way the merge is treated across the entire replication topology. This could manifest itself in many ways, including sync failures.

Filter Drivers

Many implementations of backup software, antivirus programs, and other applications are deployed as I/O system filter drivers. This allows interception of the I/O request and appropriate processing. Inappropriate processing by a filter driver may cause stale reads or lost writes.

Often these types of problems require reproductions and kernel-level debugging efforts to determine the root cause of the problem, which might be something like a stuck IRP. This can be time-consuming and invasive.

Microsoft recommends appropriate backup and security strategies but you should also ensure that the software manufacturer is Microsoft SQL Server I/O-compliant.

Stuck I/O

For SQL Server, the most common problem with filter drivers in use by the operating system, is that the I/O becomes stuck and the filter driver does not provide error messages or logging facilities.

For example, SQL Server Support staff encountered one such problem with a high-end disk subsystem, which was attempting to load balance I/O requests across multiple Host Bus Adapters (HBA). The software had a bug that lead to a lost I/O. SQL Server waited on I/O forever, producing I/O-based latch timeouts in the error log.

Important Microsoft recommends that you understand the logging capabilities of any filter driver installed on the system.

Synchronous I/O

SQL Server relies heavily on asynchronous I/O capabilities to maximize resource usage. SQL Server Support has debugged problems with some filter drivers that do not allow the I/O request to be completed asynchronously. Instead, the filter driver requires the I/O to complete before returning control to SQL Server.

This is easily observed by watching the disk queue lengths. When SQL Server is running, it commonly keeps more than one I/O posted. When I/Os become synchronous, the disk queue is often held at one outstanding I/O. This causes the SQL Server code to unnecessarily block.

Because the disk sec/transfer time may not be a fair statistic, use it with caution. When less I/O is outstanding on a drive, the disk sec/transfer is often fast. The longer the disk queue length, the more variations that can occur on disk sec/transfer. However, because SQL Server understands the asynchronous nature of the I/O patterns, longer disk queue lengths, and somewhat longer disk sec/transfer can result in overall better throughput and resource utilization.

Data Integrity

When filter drivers are installed on the system, they have direct access to the I/O data. Therefore, the integrity of the data can be compromised by a troublesome filter driver. Ensure that the filter driver is Microsoft SQL Server-compliant.

Important If you are experiencing problems with I/O stability or speed, Microsoft SQL Server Support may recommend disabling the filter driver to test results. Be aware that the only safe way to disable many filter drivers is to uninstall them.

Compression versus Encryption

Windows allows data file compression and/or encryption to be established on a per-file basis. The details about and support of each option by SQL Server 2000 are outlined in this section.

Compression

Windows allows files to be compressed on disk to save physical space. Compression is not supported in SQL Server 2000 or prior versions. The issue is that when compression is used, the actual file data is handled by the operating system in large chunks (64 KB for example). Therefore, when SQL Server updates an 8-KB data page, the system is really working on a large chunk of data and rewriting it.

The data rewrite breaks the WAL protocol because data written to disk will be rewritten, thereby breaking write ordering rules. The rewrite can lead to caching and other activities that are not appropriate for database ACID properties. The rewrite also destroys the design around sector boundary safety.

All SQL Server database log and data files should remain in an uncompressed state.

Speed Changes

The compression overhead also results in I/O performance bottlenecks. Microsoft SQL Server Support has diagnosed severe I/O bottleneck problems reported by customers attempting to use compression. In one specific case, the checkpoint timing for flushing only a few thousand buffers went from a few seconds to minutes. The work required to handle the compression not only resulted in extra system overhead, but increased the latch time needed to complete the I/O and negatively affected the overall SQL Server system.

Read-Only Databases

Microsoft SQL Server 2000 is not optimized to allow read-only, compressed databases.

Because the SQL Server 2000 optimizer does not account for compressed files when it builds a plan, the compressed files can add significant overhead. For example, if the plan requires single-page reads, each read requires that a chunk of the file be uncompressed. If the optimizer was aware of a compressed file, the plan might be changed to do more read-ahead or to revise data scan operations so the compression would occur fewer times.

Important Tempdb should never be placed on a compressed drive because even if a database is marked read-only, query support activities can occur in tempdb.

Future versions of Microsoft SQL Server may support read-only, compressed databases.

Encryption

Windows allows file encryption. SQL Server 2000 supports encrypted database log and data files. The operating system only encrypts and decrypts the data; it does not rewrite the actual data blocks or change sector boundary operations.

Warning Be sure to have a strong backup strategy for every SQL Server installation, but be aware that encryption can limit the types of disaster recovery options that are available.

Page Files and Paging

Microsoft SQL Server Support has uncovered hardware that is not resilient to paging and page file actions in various ways, such as write ordering not being preserved. SQL Server tries to prevent paging activities by reducing its committed footprint when possible. However, it is still possible for the process memory associated with SQL Server to be paged out. Like the standby and hibernate actions, paging involves other disk storage devices; these other devices, although they are not used by SQL Server directly, should also be Microsoft SQL Server I/O-compliant to ensure data integrity.

It is difficult to protect against the in-memory data corruption that is caused by the paging of a data page. Future versions of SQL Server may combine latch enforcement techniques with in-memory checksums to provide better protection against paging damage. However, checking the page for a checksum each time it is accessed by SQL Server adds significant overhead.

Important For installations of SQL Server, Microsoft recommends that the page file be placed on devices that are Microsoft SQL Server I/O-compliant.

Trace flag -T815

To help detect unwanted changes to in-memory SQL Server data pages, latch enforcement is enhanced with the –T815 trace flag. When a page is latched for modification, the VirtualProtect on the page is set to PAGE_READWRITE. At all other times the protection is PAGE_READONLY. This can help catch actions such as memory overwrites (scribblers).

Starting with Microsoft SQL Server 2000 build 8.00.0922, you can dynamically turn on or turn off trace flag -T815 by using the DBCC TRACEON Transact-SQL statement and the DBCC TRACEOFF Transact-SQL statement.

Important Latch enforcement is only valid for non-AWE (Address Windowing Extensions) environments.

Online File Copy (Snapshot)

Several backup and hardware vendors provide the capability to mirror or make a copy of a file while the file is still opened. Because SQL Server opens all database log and data files exclusively, this is only possible at a filter driver or hardware level.

A common problem with these vendor solutions is that they do not support a true snapshot—a point-in-time copy—of the entire file. The data is being copied while SQL Server is still executing. This breaks the write ordering and point-in-time semantics, and generally makes the copy of the database file(s) unrecoverable.

Some manufacturers have implemented true snapshot capabilities by using the documented SQL Server Virtual Device Interface (VDI) object model. This is the only safe way to freeze I/O to capture a point-in-time image of all the specific database files.

Read Retry

Microsoft SQL Server 2000 supports read retry only for sort operations. Future versions of SQL Server may include read retry for other I/O operations.

Microsoft SQL Server Support has diagnosed problems related to read retry. On some systems, invalid data is detected on a read. SQL Server sort logic can issue the same read (a retry of the read) and the subsequent data is valid. Because the data should have been returned correctly on the first read, this indicates a problem with the storage.

Warning If your system is showing symptoms of read retry success it should be considered a serious condition and addressed.

DBCC with REPAIR Options

When I/O operations are failing it is common practice to run database consistency checks more frequently. This can provide more detail about the extent of the failure and data points affected.

Warning It should not be common practice to use the REPAIR option of DBCC to correct corruption problems. Any corruption, especially persistent, recurring corruption, is symptomatic of a larger problem, one involving the supposedly stable media.

Utilities

Microsoft provides a few utilities for testing the general properties of your system.

SQLIOStress.exe

SQLIOStress.exe simulates various patterns of SQL Server 2000 I/O behavior to ensure rudimentary I/O safety.

The SQLIOStress utility can be downloaded from the Microsoft Web site. See the following article.

How to Use the SQLIOStress Utility to Stress a Disk Subsystem such as SQL Server
http://support.microsoft.com/default.aspx?scid=kb;en-us;231619

Important The download contains a complete white paper with extended details about the utility.

SQLIO.exe

SQLIO.exe is a SQL Server 2000 I/O utility used to establish basic benchmark testing results.

The SQLIO utility can be downloaded from the Microsoft Web site. See the following:

SQLIO Performance Testing Tool (SQL Development) – Customer Available
http://download.microsoft.com/download/f/3/f/f3f92f8b-b24e-4c2e-9e86-d66df1f6f83b/SQLIO.msi

Conclusion

The proper configuration and maintenance of the I/O subsystem is critical to a successful SQL Server deployment. Understanding how SQL Server performs I/O operations on database log and data files will help you fine-tune the I/O subsystem. Always ensure that the subsystem upholds the WAL protocol foundations so that SQL Server will maintain ACID properties properly.

Other References

iSCSI

Support for iSCSI technology components in Exchange Server
http://support.microsoft.com/default.aspx?scid=kb;en-us;839686

Support for SQL Server 2000 on iSCSI technology components:
http://support.microsoft.com/default.aspx?scid=kb;en-us;833770

Network / NAS Storage

Support for Network Database Files
http://support.microsoft.com/default.aspx?scid=kb;en-us;304261


© 2007 Microsoft Corporation. All rights reserved.  Terms of Use | Trademarks | Privacy Statement
 Microsoft
AND