2005 年 8 月,美國國會通過能源政策法案 (Energy Policy Act)。這個法案變更了日光節約時間
(DST) 的開始日期和結束日期。當此法案在 2007 年生效時,DST 將會比傳統的開始日期提早三週開始,且結束日期將延後一週結束。具體的說,DST 將於
3 月第二個星期日的早上 2:00 開始,並於 11 月第一個星期日的早上 2:00 結束。
下表概述 2007 年的日光節約時間變更。
摺疊此表格展開此表格
| 以前的 DST 開始日期 | 2007 年的 DST 開始日期 | 以前的 DST
結束日期 | 2007 年的 DST 結束日期 |
|---|
| 4 月的第一個星期日 | 3 月的第二個星期日 | 10 月的最後一個星期日
| 11 月的第一個星期日 |
| 本來應該是 2007 年 4 月 1 日 | 2007 年 3 月 11 日 | 本來應該是
2007 年 10 月 28 日 | 2007 年 11 月 4 日 |
本文將告訴您如何準備 Microsoft SQL Server 2005 和 Microsoft SQL Server
2000,以配合 2007 年的 DST 變更。
您必須採取的動作
如果您的 SQL Server 是安裝在設定為自動針對 DST 進行調整的電腦上,而電腦的時區遵循 2007 年的 DST
變更,則您必須採取下列動作:
- 安裝「Microsoft 知識庫」文件 924840 中所述的 Windows 更新。
如需詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:
924840?
(http://support.microsoft.com/kb/924840/
)
A test version of the 2007 global time zone update for Windows is available
- 如果您的電腦上安裝的是 SQL Server Notification Services,請安裝「Microsoft
知識庫」文件 931815 中所述的更新。
如需詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:
931815?
(http://support.microsoft.com/kb/931815/
)
2007 年 SQL Server 2005 Notification Services 和 SQL Server 2000 Notification Services 的時區更新
- 即使您不套用任何特定的 SQL Server 更新,SQL Server
的功能也會正確運作。不過,您必須更新作業系統。此外,您還必須更新與 SQL Server 互動的產品和應用程式。這些產品和應用程式可能包括
Notification Services、Windows SharePoint Services、Microsoft CRM 等等。如需必須為其他
Microsoft 產品套用之更新的完整清單,請造訪下列 Microsoft 網站:
SQL Server 時間使用方式和報表
在 SQL Server 2005 和 SQL Server 2000 當中,SQL Server
資料庫引擎都會使用下列兩種形式的計時器,來產生時間資訊:
高階解析計時器的計時器解析方式,是以 CPU 的「讀取時間戳記計數器」(Read Time-Stamp
Counter,RDTSC) 指示為基礎。而低階解析計時器的計時器解析方式,則是以 Microsoft Windows API 中的
GetTickCount
函數為基礎。
各種計時器背景工作和關鍵系統元件的正常運作,都依賴這些計時器。由於這些計時器都會以特定時刻的相對時間為基礎,因此內部元件和活動都不會受到
2007 年 DST 變更的影響。
例如,您執行牽涉到下列計時器活動或元件的工作:
- 系統元件,例如延遲寫入器、鎖定監視器及排程器監視器
- 背景工作,例如準刪除清除和自動壓縮
- 逾時資源,例如鎖定和閂鎖
- 排程活動,例 SQL Server Agent 作業和維護計劃
- 系統陳述式,例如 WAITFOR 陳述式
SQL Server 也會產生可供外部元件和應用程式使用的時間資訊。此時間資訊是從 Windows
作業系統擷取。因此,只要作業系統傳回正確的時間值,時間資訊就會準確。
例如,若您執行牽涉到下列外部元件和應用程式的工作:
- SQL Server Profiler 或 SQL Profiler 事件資料行,例如各種事件的開始時間資料行、結束時間資料行及持續時間資料行
- 在各種記錄檔中報告的時間資訊,例如 SQL Server 錯誤記錄檔、事件記錄檔及系統資料表
- 系統函數,例如 GetDate 函數和 GetUtcDate 函數
試想下列案例。您使用 SQL Server Profiler 或 SQL Profiler 建立一個 SQL Server
追蹤。追蹤所記錄的查詢從 2007 年 3 月 DST 時間變更之前開始,然後在 2007 年 3 月 DST
時間變更之後結束。在此狀況下,時間資訊會保持準確,不受 DST 變更的影響。
以下是追蹤的範例輸出:
EventSequence EventClass TextData StartTime EndTime Duration
156 Sql:StmtStarting Select * From Table1 2007-03-11 01:59:57.187
157 Sql:StmtCompleted Select * From Table1 2007-03-11 01:59:57.187 2007-03-11 03:00:07.187 9987
同樣地,以下是另一個追蹤的範例輸出,其中所記錄的查詢跨越 2007 年 11 月的 DST 時間變更:
EventSequence EventClass TextData StartTime EndTime Duration
178 Sql:StmtStarting Select * From Table1 2007-11-04 01:59:54.967
179 Sql:StmtCompleted Select * From Table1 2007-11-04 01:59:54.967 2007-11-04 01:00:05.030 10055
已知的 DST 相關 SQL Server 問題 (並非 2007 年 DST 變更的特定問題)
DateDiff 和 DateAdd 日期與時間函數無法感知 DST
您使用 Transact-SQL
陳述式執行以系統提供之日期和時間函數為基礎的時間計算時,必須仔細檢查陳述式。尤其是,您若是在應用程式邏輯中以硬式編碼的方式編寫 DST 時間,因為
DateDiff 和
DateAdd 系統函數無法感知 DST。
例如,當應用程式執行下列陳述式以計算時間差時,計算過程會使用舊的 DST
時間。請注意,在 2007 年的新 DST 系統中,DST 的開始日期是 2007-03-11。但是在舊的 DST 系統中,DST 的開始日期是
2007-04-01。
DECLARE @starttime datetime
DECLARE @endtime datetime
SELECT @starttime = GetDate() -- returns '2007-03-11 1:59:50.000'
WAITFOR DELAY '00:00:30'
SELECT @endtime = GetDate() –- returns '2007-03-11 3:00:20.000'
If @starttime < '2007-04-01 3:00:00.000' And
@endtime > '2007-04-01 1:59:59.000'
SELECT (cast((DATEDIFF(s, @starttime, @endtime)) as int) - 3600) AS TimeDiffInSecs
Else
SELECT cast((DATEDIFF(s, @starttime, @endtime)) as int) AS TimeDiffInSecs
Go
當您執行陳述式時,會得到以下的結果:
TimeDiffInSecs
--------------
3,630
由於
DateDiff 系統函數無法感知 DST,因此陳述式會傳回 3,630 秒,而非 30
秒。
若要更正這類狀況中的時間計算,請使用
GetUtcDate 函數代替
GetDate 函數。
GetUtcDate 函數會傳回目前的 UTC 時間。目前的 UTC 時間是從目前的本地時間結合執行 SQL Server
之電腦上的作業系統時區設定所衍生。
以下是修改過、可正確運作的陳述式:
/*-------------------------------------------------------
GetDate() GetUtcDate()
datetime 2007-03-11 1:59:50.000 2007-03-11 09:59:50.000
datetime 2007-03-11 3:00:20.000 2007-03-11 10:00:20.000
-------------------------------------------------------*/
DECLARE @starttime datetime
DECLARE @endtime datetime
SELECT @starttime = GetUtcDate() -- returns '2007-03-11 9:59:50.000'
WAITFOR DELAY '00:00:30'
SELECT @endtime = GetUtcDate() –- returns '2007-03-11 10:00:20.000'
SELECT DATEDIFF (s, @starttime, @endtime) AS TimeDiffInSecs
Go
當您執行陳述式時,會得到以下的正確結果:
TimeDiffInSecs
--------------
30
DST 結束日期對排程之 SQL Server Agent 作業的影響
試想下列案例。您有一個會列印目前本地時間的排程 SQL Server Agent 作業。此作業每 15 分鐘會執行一次。DST 於
2007 年 11 月變更時,SQL Server Agent 會自動追蹤 DST 變更。SQL Server Agent
會追蹤作業系統的變更,並正確地更新作業的下次排程執行時間。
以下是作業的範例輸出:
Job 'Daylight Savings Job 1' : Step 1, 'step 1' : Began Executing 2007-03-11 01:30:00
CurrentTime 2007-03-11 01:30:00.343
Job 'Daylight Savings Job 1' : Step 1, 'step 1' : Began Executing 2007-03-11 01:45:00
CurrentTime 2007-03-11 01:45:00.343
Job 'Daylight Savings Job 1' : Step 1, 'step 1' : Began Executing 2007-03-11 03:00:00
CurrentTime 2007-03-11 03:00:00.357
Job 'Daylight Savings Job 1' : Step 1, 'step 1' : Began Executing 2007-03-11 03:15:00
CurrentTime 2007-03-11 03:15:00.357
在此範例中,於 2007-03-11 02:00:00 執行的作業與在 2007-03-11 03:00:00
執行的作業之間,會如同預期般有一小時的間距。
但是,有一個已知的問題,就是在 2007 年 11 月 DST 變更發生期間,排程的 SQL
Server Agent 作業將會有一個小時的空窗期無法執行。時鐘於 2007 年 11 月 4 日從 2:00 A.M. 變更回 1:00 A.M.
之後,SQL Server Agent 作業會略過下一個小時,等到 2:00 A.M. 才會開始下一次的執行。這是已知問題。即使在 2007 年之前的 DST
慣例之下,也會發生此問題。此問題並非 2007 年 DST 變更所造成的。
以下是作業的範例輸出:
Job 'Daylight Savings Job 1' : Step 1, 'step 1' : Began Executing 2007-11-04 01:30:00
CurrentTime 2007-11-04 01:30:00.343
Job 'Daylight Savings Job 1' : Step 1, 'step 1' : Began Executing 2007-11-04 01:45:00
CurrentTime 2007-11-04 01:45:00.343
one hour plus 15 minutes gap here */
Job 'Daylight Savings Job 1' : Step 1, 'step 1' : Began Executing 2007-11-04 02:00:00
CurrentTime 2007-11-04 02:00:00.357
Job 'Daylight Savings Job 1' : Step 1, 'step 1' : Began Executing 2007-11-04 02:15:00
CurrentTime 2007-11-04 02:15:00.357
請注意,在作業的範例輸出中,於 2007-11-04 01:45:00 執行的作業與在 2007-11-04 02:00:00
執行的作業之間,會有一小時又 15 分鐘的間距。這個行為會影響 SQL Server
中的複寫代理程式作業、備份作業、記錄傳送作業以及其他排程作業。