我注意到在运行sql Server 2016 SP1 CU6的服务器上,有时扩展事件会话会显示导致写入的SELECT查询.
例如:
例如:
执行计划没有显示写入的明显原因,例如可能溢出到TempDB的哈希表,假脱机或排序:
对MAX类型或自动统计信息更新的变量赋值也可能导致这种情况,但在这种情况下写入的原因都不是.
写作还能从中得到什么?
解决方法
在某些情况下,Query Store可能导致写入作为select语句的效果发生,并且在同一会话中.
这可以复制如下:
USE master; GO CREATE DATABASE [Foo]; ALTER DATABASE [Foo] SET QUERY_STORE (OPERATION_MODE = READ_WRITE,CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30),DATA_FLUSH_INTERVAL_SECONDS = 900,INTERVAL_LENGTH_MINUTES = 60,MAX_STORAGE_SIZE_MB = 100,QUERY_CAPTURE_MODE = ALL,SIZE_BASED_CLEANUP_MODE = AUTO); USE Foo; CREATE TABLE Test (a int,b nvarchar(max)); INSERT INTO Test SELECT 1,'string';
创建用于监视的扩展事件会话:
CREATE EVENT SESSION [Foo] ON SERVER ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1) ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_name,sqlserver.is_system,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_server_principal_name,sqlserver.sql_text) WHERE ([writes]>(0))),ADD EVENT sqlserver.sql_batch_completed(SET collect_batch_text=(1) ACTION(sqlserver.client_app_name,sqlserver.sql_text) WHERE ([writes]>(0))) ADD TARGET package0.event_file(SET filename=N'C:\temp\FooActivity2016.xel',max_file_size=(11),max_rollover_files=(999999)) WITH (MAX_MEMORY=32768 KB,EVENT_RETENTION_MODE=ALLOW_MULTIPLE_EVENT_LOSS,MAX_disPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF);
接下来运行以下内容:
WHILE @@TRANCOUNT > 0 COMMIT SET IMPLICIT_TRANSACTIONS ON; SET NOCOUNT ON; GO DECLARE @b nvarchar(max); SELECT @b = b FROM dbo.Test WHERE a = 1; WAITFOR DELAY '00:00:01.000'; GO 86400
重现此事件可能需要或可能不需要隐式事务.
默认情况下,在下一个小时的顶部,Query Store的统计信息收集作业将写出数据.这似乎(有时?)作为一小时内执行的第一个用户查询的一部分发生.扩展事件会话将显示类似于以下内容:
事务日志显示已发生的写入:
USE Foo; SELECT [Transaction ID],[Begin Time],SPID,Operation,[Description],[Page ID],[Slot ID],[Parent Transaction ID] FROM sys.fn_dblog(null,null) /* Adjust based on contents of your transaction log */ WHERE [Transaction ID] IN ('0000:0000042c','0000:0000042d','0000:0000042e') OR [Parent Transaction ID] IN ('0000:0000042c','0000:0000042e') ORDER BY [Current LSN];
使用DBCC PAGE检查页面显示写入是sys.plan_persist_runtime_stats_interval.
USE Foo; DBCC TRACEON(3604); DBCC PAGE(5,1,344,1); SELECT OBJECT_NAME(229575856);
请注意,日志条目显示三个嵌套事务,但只显示两个提交记录.在生产中的类似情况下,这导致了一个可以说是错误的客户端库,该库使用意外启动写入事务的隐式事务,从而阻止事务日志清除.编写库只是在运行更新,插入或删除语句后才发出提交,因此它从不发出提交命令并使写入事务处于打开状态.