2. SQL Server數據庫狀態監控 - 錯誤日誌

無論是操作系統 (Unix 或者Windows),還是應用程序 (Web 服務,數據庫系統等等) ,通常都有自身的日誌機制,以便故障時追溯現場及原因。Windows Event Log和 SQL Server Error Log就是這樣的日誌, PS: SQL Server 中的錯誤日誌 (Error Log) 類似於 Oracle中的alert 文件。

錯誤日誌簡介

1. Windows事件日誌與SQL Server 錯誤日誌

Windows事件日誌中,應用程序裏的SQL Server和SQL Server Agent服務,分別對應來源自MSSQLSERVER和SQLSERVERAGENT的日誌信息;

SQL Server錯誤日誌中信息,與Windows事件日誌裏來源自MSSQLSERVER的日誌信息基本一致,不同的是,Windows事件日誌裏信息爲應用程序級,較爲簡潔些,而SQL Server錯誤日誌裏通常有具體的數據庫錯誤信息。比如:

Windows事件日誌中錯誤信息:

Login failed for user 'sa'. Reason: Password did not match that for the login provided. [CLIENT: 10.213.20.8]

SQL Server錯誤日誌中錯誤信息:

Login failed for user 'sa'. Reason: Password did not match that for the login provided. [CLIENT: 10.213.20.8]

Error: 18456, Severity: 14, State: 8.

 

2. 如何理解SQL ServerError message

以上面的Error: 18456, Severity: 14, State: 8.爲例:

(1) Error,錯誤編號,可以在系統表裏查到對應的文本信息;

select * From sys.messages where message_id = 18456

(2) Severity,錯誤級別,表明這個錯誤的嚴重性,一共有25個等級,級別越高,就越需要我們去注意處理,20~25級別的錯誤會直接報錯並跳出執行,用SQL語句的TRY…CATCH是捕獲不到的;

(3) State,錯誤狀態,比如18456錯誤,幫助文檔記載瞭如下狀態,不同狀態代表不同錯誤原因:

1. Error information is not available. This state usually means you do not have permission to receive the error details. Contact your SQL Server administrator for more information.

2.  User ID is not valid.

5.  User ID is not valid.

6.  An attempt was made to use a Windows login name with SQL Server Authentication.

7.  Login is disabled, and the password is incorrect.

8.  The password is incorrect.

9.  Password is not valid.

11. Login is valid, but server access failed.

12. Login is valid login, but server access failed.

18. Password must be changed.

還有文檔未記載的State: 10, State: 16,通常是SQL Server啓動帳號權限問題,或者重啓SQL Server服務就好了。

 

3. SQL Server 錯誤日誌包含哪些信息

SQL Server錯誤日誌中包含SQL Server開啓、運行、終止整個過程的:運行環境信息、重要操作、級別比較高的錯誤等:

(1)  SQL Server/Windows基本信息,如:版本、進程號、IP/主機名、端口、CPU個數等;

(2) SQL Server啓動參數及認證模式、內存分配;

(3) SQL Server實例下每個數據打開狀態(包括系統和用戶數據庫);

(4) 數據庫或服務器配置選項變更,KILL操作,開關DBCC跟蹤,登錄失敗等等

(5) 數據庫備份/還原的記錄;

(6) 內存相關的錯誤和警告,可能會DUMP很多信息在錯誤日誌裏;

(7) SQL Server調度異常警告、IO操作延遲警告、內部訪問越界 (也就是下面說到的Error 0);

(8) 數據庫損壞的相關錯誤,以及DBCC CHECKDB的結果;

(9) 實例關閉時間;

另外,可以手動開關一些跟蹤標記(trace flags),來自定義錯誤日誌的內容,比如:記錄如用戶登入登出記錄(login auditing),查詢的編譯執行等信息,比較常用的可能是用於檢查死鎖時的1204/1222 跟蹤標記。

通常錯誤日誌不會記錄SQL語句的性能問題,如:阻塞、超時的信息,也不會記錄Windows層面的異常(這會在windows事件日誌中記載)。

SQL Server Agent錯誤日誌中同樣也包括:信息/警告/錯誤這幾類日誌,但要簡單很多。

 

4. SQL Server 錯誤日誌存放在哪裏

假設SQL Server被安裝在X:\Program Files\Microsoft SQL Server,則SQL Server 與SQL Server Agent的錯誤日誌文件默認被放在:

X:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\LOG\ ERRORLOG ~ ERRORLOG.n

X:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\LOG\SQLAGENT.n and SQLAGENT.out.

如果錯誤日誌路徑被管理員修改,可以通過以下某種方式找到:

(1) 操作系統的應用程序日誌裏,SQL Server啓動時會留下錯誤日誌文件的路徑;

(2) 通過SSMS/管理/錯誤日誌,SQL Server啓動時會留下錯誤日誌文件的路徑;

(3) SQL Server配置管理器裏,點擊SQL Server實例/屬性/高級/啓動參數 (Startup parameters) ;

(4) 通過一個未記載的SQL語句 (在SQL Server 2000中測試無效,2005及以後可以):

SELECT SERVERPROPERTY('ErrorLogFileName')

 

5. SQL Server 錯誤日誌目錄下的其他文件

在錯誤日誌目錄下除了SQL Server和SQL Server Agent的日誌,可能還會有以下文件:

(1) 維護計劃產生的report文件 (SQL Server 2000的時候,後來的維護計劃log記錄在msdb);

(2) 默認跟蹤(default trace) 生成的trace文件,PS: 審計(Audit) 產生的trace文件在\MSSQL\DATA下;

(3) 全文索引的錯誤、日誌文件;

(4) SQLDUMP文件,比如:exception.log/SQLDump0001.txt/SQLDump0001.mdmp,大多是發生Error 0時DUMP出來的,同時在錯誤日誌裏通常會有類似如下記錄:

Error: 0, Severity: 19, State: 0

SqlDumpExceptionHandler: Process 232 generated fatal exception c0000005 EXCEPTION_ACCESS_VIOLATION. SQL Server is terminating this process.

順便說下ERROR 0 的解釋:

You've hit a bug of some kind - an access violation is an unexpected condition. You need to contact Product Support (http://support.microsoft.com/sql) to help figure out what happened and whether there's a fix available.

Is your server up to date with service packs? If not, you might try updating to the latest build. This error is an internal error in sql server. If you are up to date, you should report it to MS.

 

錯誤日誌維護

1. 錯誤日誌文件個數

1.1 SQL Server錯誤日誌

SQL Server錯誤日誌文件數量默認爲7個:1個正在用的(ERRORLOG)和6個歸檔的(ERRORLOG.1 – ERRORLOG.6),可以配置以保留更多(最多99個);

(1) 打開到SSMS/管理/SQL Server Logs文件夾/右擊/配置;

(2) 通過未記載的擴展存儲過程,直接讀寫註冊表也行:

複製代碼

USE [master]
GO
EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'NumErrorLogs', REG_DWORD, 50
GO

--Check current errorlog amout
USE [master]
GO
DECLARE @i int
EXEC xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'NumErrorLogs', @i OUTPUT
SELECT @i

複製代碼

SQL Server作爲一個Windows下的應用程序,很多信息是寫在註冊表裏的,自然也可以手動打開註冊表編輯器或寫SHELL去修改註冊表來作配置。

最後,可以通過 如下SQL語句查看已存在的錯誤日誌編號、起止時間、當前大小。

EXEC master..xp_enumerrorlogs

 

1.2 SQL Server Agent錯誤日誌

SQL Server Agent錯誤日誌文件數量共爲10個:1個正在用的(SQLAGENT.OUT),9個歸檔的(SQLAGENT.1 - SQLAGENT.9),個數不可以修改,但可以配置日誌所記載的信息類型:信息、警告、錯誤。

(1) 打開到SSMS/SQL Server Agent/Error Logs文件夾/右擊/配置;

(2) 未記載的擴展存儲過程:

USE [msdb]
GO
EXEC msdb.dbo.sp_set_sqlagent_properties@errorlogging_level=7
GO

至於@errorlogging_level各個值的意思,由於沒有文檔記載,需要自己測試並推算下。

 

2. 錯誤日誌文件歸檔

2.1 爲什麼要歸檔錯誤日誌?

假設SQL Server實例從來沒被重啓過,也沒有手動歸檔過錯誤日誌,那麼錯誤日誌文件可能會變得很大,尤其是有內部錯誤時會DUMP很多信息,一來佔空間,更重要的是:想要查看分析也會不太方便。

SQL Server/SQL Server Agent 錯誤日誌有2種歸檔方式,即:創建一個新的日誌文件,並將最老的日誌刪除。

(1) 自動歸檔:在SQL Server/ SQL Server Agent服務重啓時;

(2) 手動歸檔:定期運行如下系統存儲過程

EXEC master..sp_cycle_errorlog; --DBCC ERRORLOG 亦可
EXEC msdb.dbo.sp_cycle_agent_errorlog; --SQL Agent 服務需在啓動狀態下才有效


2.2 可不可以根據文件大小來歸檔?

可能有人會覺得,雖然很久沒歸檔,但是錯誤日誌確實不大,沒必要定期歸檔,最好可以根據文件大小來判斷。有以下幾種方法:

(1) 有些監控工具,比如:SQL Diagnostic manager,就有檢測錯誤日誌文件大小,並根據大小來決定是否歸檔的功能;

(2) 自定義腳本也可以,比如:powershell, xp_enumerrorlogs 都可以檢查錯誤日誌大小;

(3) SQL Server 2012支持一個註冊表選項,以下語句限制每個錯誤日誌文件爲5M,到了5M就會自動歸檔,在2008/2008 R2測試無效:

USE [master]
GO
EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'ErrorLogSizeInKb', REG_DWORD, 5120;

 

錯誤日誌查看及告警

錯誤日誌以文本方式記錄,記事本就可以查看,如果錯誤日誌很大,可以選擇Gvim/UltraEdit /DOS窗口type errorlog等,這些方式都會“分頁”加載,不會卡住。

1. 錯誤日誌查看

SQL Server提供了以下2種方式查看:

(1) 日誌查看器 (log viewer),除了可以查看SQL Server 與SQL Server Agent的錯誤日誌,還可以查看操作系統日誌、數據庫郵件日誌。不過當日誌文件太大時,圖形界面非常慢;

(2) 未記載的擴展存儲過程xp_readerrorlog,另外還有一個名爲sp_readerrorlog的存儲過程,它是對xp_readerrorlog的簡單封裝,並且只提供了4個參數,直接使用xp_readerrorlog即可:

在SQL Server 2000裏,僅支持一個參數,即錯誤日誌號,默認爲0~6:

exec dbo.xp_readerrorlog   --寫0或null都會報錯,直接運行即可
exec dbo.xp_readerrorlog1 
exec dbo.xp_readerrorlog6

 

複製代碼

--sql server 2000 read error log
if OBJECT_ID('tempdb..#tmp_error_log_all') is not null
    drop table #tmp_error_log_all
 
create table #tmp_error_log_all
(
infovarchar(8000),--datetime + processinfo+ text
num  int
)
 
insert into #tmp_error_log_all
exec dbo.xp_readerrorlog
 
 
--split error text
if OBJECT_ID('tempdb..#tmp_error_log_split') is not null
    drop table #tmp_error_log_split
 
create table #tmp_error_log_split
(
logdate      datetime,--datetime
processinfo  varchar(100),--processinfo
info         varchar(7900)--text
)
 
insert into #tmp_error_log_split
select CONVERT(DATETIME,LEFT(info,22),120), 
       LEFT(STUFF(info,1,23,''),CHARINDEX(' ',STUFF(info,1,23,'')) - 1), 
       LTRIM(STUFF(info,1,23 + CHARINDEX(' ',STUFF(info,1,23,'')),''))
  from #tmp_error_log_all
 where ISNUMERIC(LEFT(info,4)) = 1
   and info <> '.'
   and substring(info,11,1) = ' ' 
 
select *
  from #tmp_error_log_split
 where info like '%18456%'

複製代碼

 

在SQL Server 2005及以後版本里,支持多達7個參數,說明如下:

exec dbo.xp_readerrorlog 1,1,N'string1',N'string2',null,null,N'desc'

參數1.日誌文件號: 0 = 當前, 1 = Archive #1, 2 = Archive #2, etc...

參數2.日誌文件類型:  1 or NULL = SQL Server 錯誤日誌, 2 = SQL Agent 錯誤日誌

參數3.檢索字符串1: 用來檢索的字符串

參數4.檢索字符串2:  在檢索字符串1的返回結果之上再做過濾

參數5.日誌開始時間

參數6.日誌結束時間

參數7.結果排序: N'asc' = 升序, N'desc' = 降序

複製代碼

--sql server 2005 read error log
if OBJECT_ID('tempdb..#tmp_error_log') is not null
    drop table #tmp_error_log
 
create table #tmp_error_log
(
logdate      datetime,
processinfo  varchar(100),
info         varchar(8000)
)
 
insert into #tmp_error_log
exec dbo.xp_readerrorlog
 
select *
  from #tmp_error_log
 where info like '%18456%'

複製代碼

 

2. 錯誤日誌告警

可以通過對某些關鍵字做檢索:錯誤(Error),警告(Warn),失敗(Fail),停止(Stop),而進行告警 (database mail),以下腳本檢索24小時內的錯誤日誌:

複製代碼

declare 
      @start_time    datetime
     ,@end_time      datetime

set @start_time = CONVERT(char(10),GETDATE() - 1,120)
set @end_time = GETDATE()

if OBJECT_ID('tempdb..#tmp_error_log') is not null
	drop table #tmp_error_log

create table #tmp_error_log
(
logdate      datetime,
processinfo  varchar(100),
info         varchar(8000)
)

insert into #tmp_error_log
exec dbo.xp_readerrorlog 0,1,NULL,NULL,@start_time,@end_time,N'desc'

select COUNT(1) as num, MAX(logdate) as logdate,info 
  from #tmp_error_log
 where (info like '%ERROR%'
    or info like '%WARN%'
    or info like '%FAIL%'
    or info like '%STOP%')
   and info not like '%CHECKDB%'
   and info not like '%Registry startup parameters%'
   and info not like '%Logging SQL Server messages in file%'
   and info not like '%previous log for older entries%'
 group by info

複製代碼

當然,還可以添加更多關鍵字:kill, dead, victim, cannot, could, not, terminate, bypass, roll, truncate, upgrade, recover, IO requests taking longer than,但當中有個例外,就是DBCC CHECKDB,它的運行結果中必然包括Error字樣,如下:

DBCC CHECKDB (xxxx) executed by sqladmin found 0 errors and repaired 0 errors.

所以對0 errors要跳過,只有在發現非0 errors時才作告警。

 

小結

如果沒有監控工具,那麼可選擇擴展存儲過程,結合數據庫郵件的方式,作自動檢查及告警,並定期歸檔錯誤日誌文件以避免文件太大。大致步驟如下 :

(1) 部署數據庫郵件;

(2) 部署作業:定時檢查日誌文件,如檢索到關鍵字,發郵件告警;

(3) 部署作業:定期歸檔錯誤日誌,可與步驟(2) 合併作爲兩個step放在一個作業裏。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章