.NET führt eine SQL-Abfrage aus und Active Monitor zeigt mehrere Zeilen an, die sich gegenseitig blockieren

7

Ich verwende .NET, um SQL-Vorgänge unter SQL Server 2014 auszuführen. Hier ist der verwendete Code:

using(SqlConnection conn = new SqlConnection(connectionString)){
    ///programming/1880471/capture-stored-procedure-print-output-in-net
    conn.InfoMessage += new SqlInfoMessageEventHandler(logSqlMessages);
    conn.Open();
    using(SqlCommand stmt = new SqlCommand{
        Connection = conn,
        CommandText = sql,
        CommandTimeout = 30000 // The time in seconds to wait for the command to execute. The default is 30 seconds.
        //,CommandType = CommandType.StoredProcedure
    })
    {
        affectedRecords = stmt.ExecuteNonQuery();
    } // using stmt
} // using conn

Wenn ich mir Active Monitor anschaue, gibt es zehn Zeilen, die auf dieselbe Operation verweisen. Sie haben alle das gleiche session_id, einige von ihnen haben einen Task-Status und die meisten von ihnen sind suspendiert. Einige von ihnen haben LastWaitTime CXPACKETund die meisten sind PAGEIOLATCH_SH.

Ich habe auch eine Abfrage auf SQL Server ausgeführt und dasselbe Verhalten ist auf Active Monitor aufgetreten.

Vielleicht ist es ein normales Verhalten, aber es ist seltsam, dass eine SELECT-Operation mehrere Zeilen erstellt und sich so blockiert. Irgendeine Idee, was es verursachen könnte?

Hikari
quelle

Antworten:

15

Mehrere Zeilen im Aktivitätsmonitor für dieselbe SPID bedeuten, dass Ihre Abfrage so ausgewählt wurde, dass sie parallel über mehrere Threads ausgeführt wird.

NÜSSE

Jede Zeile im Aktivitätsmonitor repräsentiert tatsächlich eine ECID, nicht eine SPID.

Der Aktivitätsmonitor macht nur die SPIDSpalte ( session_id) verfügbar, in sys.sysprocesses wird jedoch eine zusätzliche Spalte mit dem Namen ECID( E xecution C ontext ID ) angezeigt. Dies ist eine eindeutige Kennung für jeden Thread, den die Abfrage verwendet.

Die sysprocessesSystemansicht ist veraltet, aber Sie können ECID unter einem anderen Namen ( exec_context_id) in der sys.dm_os_tasksAnsicht (sowie in anderen aufgabenbezogenen Ansichten) finden.

Hier ist eine Beispielabfrage, die alle Ausführungskontext-IDs erfasst, die mit Abfragen verknüpft sind, die in einer bestimmten Sitzung ausgeführt werden, und worauf sie gegebenenfalls warten:

SELECT 
    dot.session_id,
    dot.exec_context_id,
    dot.task_state,
    dowt.wait_type,
    dowt.wait_duration_ms,
    dowt.blocking_session_id,
    dowt.resource_description
FROM sys.dm_os_tasks dot
    LEFT JOIN sys.dm_os_waiting_tasks dowt
        ON  dowt.exec_context_id = dot.exec_context_id
            AND dowt.session_id = dot.session_id
WHERE dot.session_id = 51
ORDER BY exec_context_id;

In SQL 2016 wurden sys.dm_exec_requests zwei neue Spalten hinzugefügt - DOPund parallel_worker_count- diese können verwendet werden, um zu überprüfen, ob die Anforderung parallel ausgeführt wird oder nicht.

Ein weiterer wichtiger Punkt ist, dass das CXPACKETWarten von Natur aus ein Parallelitäts-Warten ist. Dies allein sagt uns, dass die Abfrage mehr als einen Thread verwendet.

Dies PAGEIOLATCH_SHist eine Wartezeit, die angibt, dass diese Threads Daten von der Festplatte in den Speicher lesen.

George.Palacios
quelle