In einigen Fällen kann der Abfragespeicher Schreibvorgänge als Auswirkung einer select-Anweisung und in derselben Sitzung verursachen.
Dies kann wie folgt reproduziert werden:
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';
Erstellen Sie eine erweiterte Ereignissitzung zur Überwachung:
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.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 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);
Führen Sie als Nächstes Folgendes aus:
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
Eine implizite Transaktion kann erforderlich sein oder auch nicht, um dies zu reproduzieren.
Standardmäßig schreibt der Statistiksammlungsjob von Query Store in der nächsten Stunde Daten aus. Dies scheint (manchmal?) Im Rahmen der ersten Benutzerabfrage zu geschehen, die innerhalb einer Stunde ausgeführt wird. In der Sitzung für erweiterte Ereignisse wird Folgendes angezeigt:
Das Transaktionsprotokoll zeigt die aufgetretenen Schreibvorgänge an:
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:0000042d', '0000:0000042e')
ORDER BY [Current LSN];
Das Betrachten der Seite mit DBCC PAGE
zeigt, dass die Schreibvorgänge ausgeführt werden sollen sys.plan_persist_runtime_stats_interval
.
USE Foo;
DBCC TRACEON(3604);
DBCC PAGE(5,1,344,1); SELECT
OBJECT_NAME(229575856);
Beachten Sie, dass in den Protokolleinträgen drei verschachtelte Transaktionen, aber nur zwei Festschreibungsdatensätze angezeigt werden. In einer ähnlichen Situation in der Produktion führte dies zu einer möglicherweise fehlerhaften Clientbibliothek, die implizite Transaktionen verwendete, die unerwartet eine Schreibtransaktion starteten, wodurch das Löschen des Transaktionsprotokolls verhindert wurde. Die Bibliothek wurde so geschrieben, dass sie nur nach dem Ausführen einer Aktualisierungs-, Einfüge- oder Löschanweisung ein Commit ausführt. Sie hat also nie einen Commit-Befehl ausgegeben und eine Schreibtransaktion offen gelassen.