如何查明谁将SQL Server 2017数据库设置为ReadOnly模式?
查找SQL Server 2017数据库设为ReadOnly的操作账户及自动触发机制
一、查明手动设置ReadOnly的操作账户
1. 查看SQL Server错误日志
SQL Server默认会记录数据库状态变更信息,可通过两种方式查询:
- 在SSMS中:展开实例节点 → 管理 → SQL Server日志,查找包含
Database '数据库名' changed to READ_ONLY.的条目,条目末尾会标注执行操作的登录账户。 - 执行T-SQL命令读取错误日志:
EXEC xp_readerrorlog 0, 1, N'Database', N'changed to READ_ONLY';
参数说明:0代表最新日志文件,1代表SQL Server日志类型,后两个参数为筛选关键词。
2. 检查审计日志(若已启用)
如果之前开启了服务器级审计或数据库级审计,且审计策略包含DATABASE_OPERATION类事件,审计日志会完整记录操作账户、时间、语句等细节。可通过SSMS的“安全性 → 审计”节点查看,或用T-SQL查询审计文件。
3. 扩展事件(仅能监控开启后的操作)
若未提前配置扩展事件,无法回溯历史操作,但可创建跟踪会话监控后续的数据库状态变更:
CREATE EVENT SESSION [TrackDBReadOnlyChanges] ON SERVER ADD EVENT sqlserver.database_option_change( WHERE (option_name = N'read only' AND option_value = N'true')) ADD TARGET package0.event_file(SET filename=N'TrackDBReadOnlyChanges.xel') WITH (STARTUP_STATE=ON); GO ALTER EVENT SESSION [TrackDBReadOnlyChanges] ON SERVER STATE=START; GO
后续可通过以下语句查询事件文件获取操作信息:
SELECT event_data.value('(event/@name)[1]', 'varchar(50)') AS EventName, event_data.value('(event/@timestamp)[1]', 'datetime2') AS EventTime, event_data.value('(event/data[@name="database_name"]/value)[1]', 'varchar(100)') AS DBName, event_data.value('(event/data[@name="server_principal_name"]/value)[1]', 'varchar(100)') AS LoginName FROM ( SELECT CAST(event_data AS XML) AS event_data FROM sys.fn_xe_file_target_read_file(N'TrackDBReadOnlyChanges*.xel', NULL, NULL, NULL) ) AS x;
二、自动将数据库设为ReadOnly的常见机制及对应账户
- 数据库恢复操作:执行
RESTORE DATABASE时若指定WITH READ_ONLY选项,恢复后的数据库会处于只读状态,执行恢复命令的账户(通常是拥有RESTORE DATABASE权限的登录名)即为操作主体。 - 数据库镜像/可用性组:
- 镜像会话中的镜像数据库默认是只读状态,由SQL Server服务账户自动维护;
- 可用性组的次要副本若配置了只读访问权限(如允许只读路由),次要副本数据库会处于只读状态,配置该权限的账户或SQL Server服务账户是相关操作主体。
- 数据库快照:数据库快照本身是只读的,创建快照的账户(需拥有
CREATE DATABASE权限)触发了这个状态,注意快照是独立于源数据库的对象,源数据库不会因此变为只读。 - 维护作业/第三方工具:部分备份、维护工具或SQL Server Agent作业可能会在执行任务时临时将数据库设为只读,这类操作的执行账户是作业配置的运行账户或工具使用的登录名。
内容的提问来源于stack exchange,提问作者StingyJack
相关产品推荐
相关产品推荐

