一、SQL Server on Linux日志概述
SQL Server在Linux环境下的日志系统与Windows版本保持一致,主要包括错误日志、代理日志和SQL Server日志(包含Windows应用程序日志)。这些日志文件对于故障排查、性能监控和安全审计至关重要。
SQL Server日志类型:
– 错误日志(Error Log):记录启动、关闭、严重错误信息
– SQL Server日志:记录数据库引擎运行事件
– 代理日志(Agent Log):记录作业执行、调度信息
– Windows事件日志:系统级日志和应用程序日志
– Windows应用程序日志:与SQL Server相关的Windows事件
日志默认位置:
– 错误日志:/var/opt/mssql/log/errorlog
– SQL Server日志:/var/opt/mssql/log/sqlservr.log
– 代理日志:/var/opt/mssql/log/sqlagent.log
– 备份日志:/var/opt/mssql/log/backup.log
二、查看SQL Server错误日志
2.1 使用系统命令查看
查看错误日志文件:
# 查看最新错误日志
cat /var/opt/mssql/log/errorlog
# 查看最近20行
tail -20 /var/opt/mssql/log/errorlog
# 实时跟踪日志
tail -f /var/opt/mssql/log/errorlog
# 统计日志行数
wc -l /var/opt/mssql/log/errorlog
错误日志格式示例:
2026-05-11 09:30:15.23 服务器 主题: 服务器进程 1934 已启动。
2026-05-11 09:30:15.24 服务器 主题: 服务器正在监听 [ 0.0.0.0 <IPv4> 1433]。
2026-05-11 09:30:15.24 服务器 主题: 服务器正在监听 [ :: <IPv6> 1433]。
2026-05-11 09:30:15.28 服务器 主题: SQL Server 正在按以下规范运行:
copyright (C) Microsoft Corporation. All rights reserved.
Server process ID is 1934.
2.2 使用sqlcmd查询日志
通过T-SQL查询日志:
sqlcmd -S localhost -U sa -P "YourStrong@Password" -Q "
EXEC sys.xp_readerrorlog;
" -C
查询特定类型日志:
-- 查询错误日志(参数0)
EXEC sys.xp_readerrorlog 0, 1;
-- 查询SQL Server日志(参数1)
EXEC sys.xp_readerrorlog 1, 1;
-- 搜索包含"error"的日志条目
EXEC sys.xp_readerrorlog 0, 1, 'error';
-- 搜索特定日期范围的日志
EXEC sys.xp_readerrorlog 0, 1, NULL, '2026-05-01', '2026-05-11';
查看日志文件列表:
-- 查看当前归档的日志文件
EXEC sys.sp_enumerrorlogs;
GO
-- 输出示例:
-- Archive # Date Log File Size(KB)
-- -------- ---------- ---------------
-- 0 2026-05-11 1024
-- 1 2026-05-10 2048
-- 2 2026-05-09 1536
2.3 常用日志查询示例
查询最近24小时的错误:
EXEC sys.xp_readerrorlog 0, 1, NULL, DATEADD(day, -1, GETDATE()), NULL;
查询登录失败记录:
EXEC sys.xp_readerrorlog 0, 1, '登录失败';
EXEC sys.xp_readerrorlog 0, 1, 'failed';
查询连接相关事件:
-- 查看成功连接
EXEC sys.xp_readerrorlog 0, 1, '连接已成功';
-- 查看断开连接
EXEC sys.xp_readerrorlog 0, 1, '连接已断开';
-- 查看超时
EXEC sys.xp_readerrorlog 0, 1, '超时';
三、SQL Server日志配置
3.1 配置日志轮换
# 查看当前日志配置
sudo /opt/mssql/bin/mssql-conf get log
# 设置错误日志轮换(每天一个新文件)
sudo /opt/mssql/bin/mssql-conf set log.sequencing 1
# 设置最大日志文件数量
sudo /opt/mssql/bin/mssql-conf set logfiles.maxsize 30
# 重启SQL Server生效
sudo systemctl restart mssql-server
手动轮换日志:
# 重命名当前错误日志
sudo mv /var/opt/mssql/log/errorlog /var/opt/mssql/log/errorlog.$(date +%Y%m%d_%H%M%S)
# 重启SQL Server创建新日志文件
sudo systemctl restart mssql-server
# 查看新日志文件
ls -la /var/opt/mssql/log/
3.2 配置日志详细程度
-- 查看当前错误日志级别
DBCC TRACESTATUS(3604);
-- 设置错误日志详细程度
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- 查看trace标志
EXEC sp_configure;
3.3 配置Windows事件日志
# 查看Windows应用程序日志
sudo journalctl -u mssql-server --since "1 hour ago"
# 实时跟踪日志
sudo journalctl -u mssql-server -f
# 保存日志到文件
sudo journalctl -u mssql-server > /tmp/mssql_journal.log
四、日志分析与故障排查
4.1 常见错误分析与解决方案
启动错误:
错误:SQL Server无法启动
原因:内存不足、端口被占用、配置文件损坏
解决方案:
1. 检查内存:free -h
2. 检查端口:ss -tlnp | grep 1433
3. 修复配置:sudo /opt/mssql/bin/mssql-conf setup
连接错误:
错误:无法连接到SQL Server
原因:防火墙未开放、服务未启动、网络问题
解决方案:
1. 检查服务状态:sudo systemctl status mssql-server
2. 开放防火墙:sudo firewall-cmd --add-port=1433/tcp --permanent
3. 测试连接:sqlcmd -S localhost -U sa -P "Password"
权限错误:
错误:无法访问日志文件
原因:文件权限不足、用户不属于mssql组
解决方案:
1. 添加用户到mssql组:sudo usermod -aG mssql $USER
2. 修改文件权限:sudo chmod 644 /var/opt/mssql/log/errorlog
3. 重新登录生效
4.2 日志分析脚本
自动化日志分析脚本:
#!/bin/bash
# analyze_sqlserver_logs.sh - SQL Server日志分析脚本
LOG_DIR="/var/opt/mssql/log"
REPORT_FILE="/tmp/mssql_log_report_$(date +%Y%m%d_%H%M%S).txt"
SA_PASSWORD="YourStrong@Password"
echo "=== SQL Server日志分析报告 ===" > $REPORT_FILE
echo "分析时间:$(date)" >> $REPORT_FILE
echo "" >> $REPORT_FILE
# 1. 错误统计
echo "【错误统计】" >> $REPORT_FILE
echo "错误日志文件大小:$(du -h $LOG_DIR/errorlog | cut -f1)" >> $REPORT_FILE
echo "最近错误数量:$(grep -c '错误\|Error\|error' $LOG_DIR/errorlog 2>/dev/null || echo 0)" >> $REPORT_FILE
echo "" >> $REPORT_FILE
# 2. 登录统计
echo "【登录统计】" >> $REPORT_FILE
echo "成功登录次数:$(grep -c '登录已成功\|Login succeeded' $LOG_DIR/errorlog 2>/dev/null || echo 0)" >> $REPORT_FILE
echo "失败登录次数:$(grep -c '登录失败\|Login failed' $LOG_DIR/errorlog 2>/dev/null || echo 0)" >> $REPORT_FILE
echo "" >> $REPORT_FILE
# 3. 连接统计
echo "【连接统计】" >> $REPORT_FILE
echo "当前连接数:$(sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -Q "SELECT COUNT(*) FROM sys.dm_exec_sessions WHERE is_user_process=1" -h -1 -C 2>/dev/null | head -2)" >> $REPORT_FILE
echo "" >> $REPORT_FILE
# 4. 最近错误
echo "【最近10条错误】" >> $REPORT_FILE
tail -50 $LOG_DIR/errorlog | grep -E '错误|Error' >> $REPORT_FILE 2>/dev/null || echo "无错误记录" >> $REPORT_FILE
echo ""
echo "报告已保存到:$REPORT_FILE"
cat $REPORT_FILE
4.3 实时监控脚本
实时错误监控脚本:
#!/bin/bash
# monitor_sqlserver_errors.sh - SQL Server实时错误监控
LOG_FILE="/var/opt/mssql/log/errorlog"
ALERT_EMAIL="admin@example.com"
KEYWORDS="错误|Error|严重|critical|警告|Warning"
# 记录上次检查位置
POSITION_FILE="/tmp/mssql_log_monitor_pos"
if [ -f $POSITION_FILE ]; then
LAST_POS=$(cat $POSITION_FILE)
else
LAST_POS=0
fi
# 获取当前文件大小
CURRENT_SIZE=$(stat -c%s $LOG_FILE)
# 如果日志文件被轮换,从头开始
if [ $CURRENT_SIZE -lt $LAST_POS ]; then
LAST_POS=0
fi
# 读取新内容
NEW_CONTENT=$(tail -c $(($CURRENT_SIZE - $LAST_POS)) $LOG_FILE 2>/dev/null)
# 检查关键词
if echo "$NEW_CONTENT" | grep -qE "$KEYWORDS"; then
echo "发现SQL Server错误或警告:" | mail -s "SQL Server监控告警" $ALERT_EMAIL
echo "$NEW_CONTENT" | grep -E "$KEYWORDS" | tail -20 | mail -s "SQL Server监控告警" $ALERT_EMAIL
fi
# 更新位置
echo $CURRENT_SIZE > $POSITION_FILE
echo "监控完成:$(date)"
五、日志备份与归档
5.1 日志备份脚本
#!/bin/bash
# backup_sqlserver_logs.sh - SQL Server日志备份脚本
BACKUP_DIR="/var/opt/mssql/backup/logs"
LOG_DIR="/var/opt/mssql/log"
DATE=$(date +%Y%m%d)
DAYS_KEEP=30
# 创建备份目录
mkdir -p $BACKUP_DIR
# 备份错误日志
tar -czf $BACKUP_DIR/errorlog_$DATE.tar.gz $LOG_DIR/errorlog* 2>/dev/null
# 备份SQL Server日志
tar -czf $BACKUP_DIR/sqlservr_$DATE.tar.gz $LOG_DIR/sqlservr*.log 2>/dev/null
# 备份代理日志
tar -czf $BACKUP_DIR/sqlagent_$DATE.tar.gz $LOG_DIR/sqlagent*.log 2>/dev/null
# 清理过期备份
find $BACKUP_DIR -name "*.tar.gz" -mtime +$DAYS_KEEP -delete
# 输出备份信息
echo "=== 日志备份完成 ==="
echo "备份时间:$(date)"
echo "备份目录:$BACKUP_DIR"
echo "备份文件:"
ls -lh $BACKUP_DIR | grep $DATE
5.2 日志归档策略
配置日志归档:
-- 创建日志归档存储过程
CREATE PROCEDURE sp_archive_old_logs
AS
BEGIN
DECLARE @old_date DATETIME = DATEADD(day, -30, GETDATE());
-- 删除30天前的归档日志文件
-- 注意:此操作需要谨慎执行
EXEC xp_delete_file 0, '/var/opt/mssql/log/archive', 'log', @old_date;
END;
GO
-- 创建每日归档作业
EXEC msdb.dbo.sp_add_job @job_name = N'归档旧日志',
@enabled = 1,
@description = N'归档SQL Server旧日志文件';
EXEC msdb.dbo.sp_add_jobstep @job_name = N'归档旧日志',
@step_name = N'执行归档',
@subsystem = N'TSQL',
@command = N'EXEC sp_archive_old_logs';
六、日志与安全审计
6.1 启用审计日志
# 创建审计目录
sudo mkdir -p /var/opt/mssql/audit
# 配置SQL Server审计
sqlcmd -S localhost -U sa -P "YourStrong@Password" -Q "
CREATE SERVER AUDIT [SecurityAudit]
TO FILE (FILEPATH = '/var/opt/mssql/audit/', MAXSIZE = 100 MB)
WITH (ON_FAILURE = CONTINUE);
CREATE SERVER AUDIT SPECIFICATION [LoginAudit]
FOR SERVER AUDIT [SecurityAudit]
ADD (SUCCESSFUL_LOGIN_GROUP),
ADD (FAILED_LOGIN_GROUP);
ALTER SERVER AUDIT [SecurityAudit] WITH (STATE = ON);
ALTER SERVER AUDIT SPECIFICATION [LoginAudit] WITH (STATE = ON);
" -C
6.2 查询审计日志
-- 查看登录成功记录
SELECT
event_time,
succeeded,
server_principal_name,
client_ip,
session_id
FROM sys.fn_get_audit_file ('/var/opt/mssql/audit/*.sqlaudit', NULL, NULL)
WHERE succeeded = 1
ORDER BY event_time DESC;
-- 查看登录失败记录
SELECT
event_time,
succeeded,
server_principal_name,
client_ip,
session_id
FROM sys.fn_get_audit_file ('/var/opt/mssql/audit/*.sqlaudit', NULL, NULL)
WHERE succeeded = 0
ORDER BY event_time DESC;
6.3 定期安全检查
-- 检查登录失败次数过多的账户
SELECT
server_principal_name,
COUNT(*) AS failure_count,
MIN(event_time) AS first_failure,
MAX(event_time) AS last_failure
FROM sys.fn_get_audit_file ('/var/opt/mssql/audit/*.sqlaudit', NULL, NULL)
WHERE succeeded = 0
GROUP BY server_principal_name
HAVING COUNT(*) > 10
ORDER BY failure_count DESC;
七、使用第三方工具分析日志
7.1 logstash配置
# 安装logstash
sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
cat << EOF | sudo tee /etc/yum.repos.d/logstash.repo
[logstash-7.x]
name=Elastic Logstash 7.x
baseurl=https://artifacts.elastic.co/downloads/logstash/logstash-7.x.rpm
enabled=1
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
EOF
sudo yum install -y logstash
# 配置logstash输入
cat << EOF | sudo tee /etc/logstash/conf.d/mssql-input.conf
input {
file {
path => "/var/opt/mssql/log/errorlog"
start_position => "beginning"
sincedb_path => "/var/lib/logstash/sincedb_mssql"
codec => plain {
charset => "UTF-8"
}
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "mssql-logs-%{+YYYY.MM.dd}"
}
}
EOF
7.2 Elasticsearch查询示例
# 查询最近1小时的错误
curl -X GET "localhost:9200/mssql-logs-*/_search?q=error&size=20"
# 查询特定时间范围的日志
curl -X POST "localhost:9200/mssql-logs-*/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"range": {
"@timestamp": {
"gte": "now-1h",
"lte": "now"
}
}
}
}'
八、性能相关日志分析
8.1 查询性能日志
-- 启用查询统计
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'query_store', 1;
RECONFIGURE;
-- 查看慢查询
SELECT
q.avg_duration,
q.avg_cpu_time,
q.avg_logical_io_reads,
q.query_text
FROM sys.query_store_runtime_stats r
JOIN sys.query_store_query q ON r.query_id = q.query_id
ORDER BY avg_duration DESC;
8.2 死锁日志分析
-- 查看最近死锁
SELECT
XEvent.query(XML)'
FROM sys.dm_xe_session_targets t
JOIN sys.dm_xe_sessions s ON t.event_session_address = s.address
WHERE t.target_name = 'event_file'
AND s.name = 'system_health';
8.3 等待统计日志
-- 记录等待统计到日志表
CREATE TABLE WaitStatsLog (
ID INT IDENTITY PRIMARY KEY,
CaptureTime DATETIME DEFAULT GETDATE(),
WaitType NVARCHAR(60),
WaitingTasks INT,
WaitTimeMs BIGINT,
SignalWaitMs BIGINT
);
-- 创建定期记录作业
CREATE PROCEDURE CaptureWaitStats
AS
BEGIN
INSERT INTO WaitStatsLog (WaitType, WaitingTasks, WaitTimeMs, SignalWaitMs)
SELECT
wait_type,
waiting_tasks_count,
wait_time_ms,
signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE waiting_tasks_count > 0;
END;
GO
九、常见问题与解决方案
Q1:日志文件过大占用磁盘空间?
解决方案:
1. 配置日志轮换
2. 定期归档和压缩旧日志
3. 删除不需要的历史日志
# 查看日志目录大小
du -sh /var/opt/mssql/log/*
# 压缩旧日志
find /var/opt/mssql/log -name "*.log.*" -mtime +7 -exec gzip {} \;
# 删除超过30天的日志归档
find /var/opt/mssql/log -name "errorlog.*" -mtime +30 -delete
Q2:无法读取日志文件权限不足?
解决方案:
1. 将用户添加到mssql组
2. 修改日志文件权限
3. 使用sudo运行sqlcmd
# 添加当前用户到mssql组
sudo usermod -aG mssql $USER
# 修改日志文件权限
sudo chmod 640 /var/opt/mssql/log/errorlog
sudo chmod 640 /var/opt/mssql/log/sqlservr.log
# 重新登录使组权限生效
newgrp mssql
Q3:日志中乱码或中文字符无法识别?
解决方案:
1. 设置正确的字符集
2. 使用UTF-8编码查看
# 查看当前编码
echo $LANG
# 设置UTF-8编码
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# 使用less查看(支持中文)
less /var/opt/mssql/log/errorlog
# 或使用iconv转换
iconv -f GBK -t UTF-8 errorlog.gbk > errorlog.utf8
Q4:日志查询很慢如何优化?
解决方案:
1. 使用索引优化日志查询
2. 定期清理历史日志
3. 使用筛选条件减少返回数据
-- 创建索引优化日期查询
CREATE INDEX IX_ErrorLog_Date ON ErrorLog(EventTime);
-- 使用筛选条件
EXEC sys.xp_readerrorlog 0, 1, NULL, '2026-05-01', '2026-05-11';
十、总结
CentOS上SQL Server日志查看与管理的关键要点:
- 日志位置:
/var/opt/mssql/log/目录下 - 查看方式:命令行工具、sqlcmd、T-SQL存储过程
- 配置管理:日志轮换、文件大小控制、定期归档
- 故障排查:错误分析、性能监控、安全审计
- 自动化:脚本监控、定期报告、告警通知
- 安全:审计日志、登录记录、权限控制
掌握这些日志管理技巧,可以快速定位和解决SQL Server在Linux环境下的各种问题。
本文基于SQL Server 2022和CentOS Stream 9编写,适用于CentOS 7+/RHEL 7+/CentOS Stream环境。