C # Dapper loader en MS-SQL 2012 deadlocks en inserción

c# dapper deadlock sql sql-server

Pregunta

Ejecutando el estándar Microsoft SQL 2012, sin compresión, sin particiones. Ejecutando en Windows Server 2008 R2. Mi programa de cargador es VS C # 2013, puro de 64 bits, .NET 4.5.2 Utilizo Dapper 1.42 para mi ORM. NO utilizo commit / rollback / transaction logic, estos son simples insertos.

En la parte superior del cargador, publico 'SET RECOVERY SIMPLE' (esto se hizo para tratar de resolver este problema).

El cargador lee un .csv, procesa los datos y luego inserta, realmente la forma más simple de un programa, son solo unas pocas líneas de código. El cargador nunca hace una selección. El cargador es el único proceso que se ejecuta en este servidor (servidor de prueba). El cargador no tiene múltiples hilos. Hago tiempo de comando = 0 en el inserto.

Continuamente obtengo 'Transacción (ID de proceso xx) estaba bloqueada en recursos de bloqueo con otro proceso y se ha elegido como la víctima de interbloqueo. Vuelva a ejecutar la transacción '.

El error parece obvio, dice que tengo 2 procesos en ejecución, y uno de ellos está bloqueando. Pero estoy en un servidor de prueba, soy el único usuario, no hay otro proceso ejecutándose.

No sé cómo depurar esto. En mi declaración 'catch', ejecuto este comando SQL para ver qué más está ejecutándose, pero no muestra NADA en ejecución cada vez que aparece el error. Entonces, si no se está ejecutando nada, ¿por qué sigo teniendo bloqueos en el inserto?

SELECT L.request_session_id AS SPID, DB_NAME(L.resource_database_id) AS DatabaseName, O.Name AS LockedObjectName, P.object_id AS LockedObjectId, L.resource_type AS LockedResource, L.request_mode AS LockType, ST.text AS SqlStatementText, ES.login_name AS LoginName, ES.host_name AS HostName, TST.is_user_transaction as IsUserTransaction, AT.name as TransactionName, CN.auth_scheme as AuthenticationMethod
FROM sys.dm_tran_locks L
LEFT JOIN sys.partitions P ON P.hobt_id = L.resource_associated_entity_id
LEFT JOIN sys.objects O ON O.object_id = P.object_id
LEFT JOIN sys.dm_exec_sessions ES ON ES.session_id = L.request_session_id
LEFT JOIN sys.dm_tran_session_transactions TST ON ES.session_id = TST.session_id
LEFT JOIN sys.dm_tran_active_transactions AT ON TST.transaction_id = AT.transaction_id
LEFT JOIN sys.dm_exec_connections CN ON CN.session_id = ES.session_id
CROSS APPLY sys.dm_exec_sql_text(CN.most_recent_sql_handle) AS ST
WHERE DB_NAME(L.resource_database_id) = DB_NAME()

Respuesta popular

En mi declaración 'catch', ejecuto este comando SQL para ver qué más está ejecutándose

Cuando se produce un punto muerto, la transacción de la víctima se revierte. Esto libera todos los bloqueos y, por lo tanto, permite que continúen las transacciones competidoras. Solo después de que se complete la reversión se devuelve el control a la sesión de la víctima y se genera una excepción. Para cuando tu catch ejecuta, los procesos simultáneos probablemente se hayan completado.

Lo que estás tratando de hacer es fundamentalmente incorrecto. Sin mencionar que ya tienes los medios para capturar la información del punto muerto:

Y, como último tema: permisos sys.dm_exec_sessions :

Si el usuario tiene el permiso VIEW SERVER STATE en el servidor, el usuario verá todas las sesiones en ejecución en la instancia de SQL Server; de lo contrario, el usuario verá solo la sesión actual .



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow