加入收藏 | 设为首页 | 会员中心 | 我要投稿 东莞站长网 (https://www.0769zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

sql-server – 为什么SELECT查询会导致写入?

发布时间:2021-03-14 07:01:10 所属栏目:MsSql教程 来源:网络整理
导读:我注意到在运行SQL Server 2016 SP1 CU6的服务器上,有时扩展事件会话会显示导致写入的SELECT查询. 例如: 执行计划没有显示写入的明显原因,例如可能溢出到TempDB的哈希表,假脱机或排序: 对MAX类型或自动统计信息更新的变量赋值也可能导致这种情况,但在这种情

我注意到在运行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:tempFooActivity2016.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);

请注意,日志条目显示三个嵌套事务,但只显示两个提交记录.在生产中的类似情况下,这导致了一个可以说是错误的客户端库,该库使用意外启动写入事务的隐式事务,从而阻止事务日志清除.编写库只是在运行更新,插入或删除语句后才发出提交,因此它从不发出提交命令并使写入事务处于打开状态.

(编辑:东莞站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读