Uno de nuestros sistemas de producción ha presentado un problema con una sola declaración de inserción en una tabla temporal de nuestra base de datos de usuarios. Cuando comento la inserción / selección, el proceso almacenado en cuestión se ejecuta de manera oportuna, por lo que confío en mi aislamiento del problema.
La serie de procesos almacenados invocados básicamente se detiene cuando descomento la inserción / selección en cuestión. No puedo ver nada en Top Transactions by Age en tempdb o en cualquiera de nuestras bases de datos de usuarios. No veo nada en el Monitor de actividad que se desvíe de la información del Monitor de actividad cuando la base de datos está "en reposo", aparte de que la CPU está plana en ~ 20%.
El comportamiento es el siguiente: cuando configuro y luego ejecuto el caso de reproducción, al llegar a la inserción / selección en cuestión, veo un SOS_SCHEDULER_YIELD y hay un ENCRYPTION_SCAN. Aproximadamente cinco horas después, veré el procesamiento de nuestro currículum vitae de procedimiento almacenado y la actividad se completará (pongo declaraciones de registro rápidas y sucias en cada operación distinta).
También reemplacé las variables en la porción de selección de la inserción con los valores ejecutados, y ejecuté la consulta de selección en sí, y regresó en cinco segundos.
La base de datos de usuarios en cuestión tiene FALSO como valor de cifrado habilitado, al igual que tempdb. La operación en cuestión ocurre en aproximadamente 65k filas de datos, y lo he intentado con solo 1k filas, y el comportamiento persistió, aunque el tiempo que tomó fue mucho menor.
Una única base de datos de usuario es la única instancia de este comportamiento. Lo he reproducido localmente a través de una copia de seguridad de la base de datos de ese usuario. Tenemos alrededor de otros 70 usuarios del software que no presentan este problema.
Dada la información anterior, mi pregunta es, ¿por qué se detiene el procesamiento de nuestros procedimientos almacenados? Como probablemente sea optimista esperar una respuesta precisa, ¿cuál es el paso correcto para depurar esto? Quizás haya algo en uno de los DMV como dm_tran_locks, dm_exec_requests, dm_tran_database_transactions, dm_os_schedulers, dm_exec_sessions que, si bien me han proporcionado información, no estoy interpretando o entendiendo el resultado de una manera que apunta a una solución.
A continuación se muestra la inserción / selección en cuestión:
INSERT INTO #TS_EVENT_DATA
( EVENT_FK,
EVENT_TYPE_CR_FK,
EVENT_ENTITY_CLASS_CR_FK,
userDatabase_ID,
DATA_NAME_FK,
IMPORT_JOB_FK,
PRODUCT_STRUCTURE_FK,
ORG_ENTITY_STRUCTURE_FK,
ENTITY_CLASS_CR_FK,
ENTITY_DATA_NAME_FK,
ENTITY_STRUCTURE_FK,
DATA_SET_FK,
DATA_TYPE_CR_FK,
ORG_IND,
TABLE_NAME,
NET_VALUE1_NEW,
NET_VALUE2_NEW,
NET_VALUE3_NEW,
NET_VALUE4_NEW,
NET_VALUE5_NEW,
NET_VALUE6_NEW,
NET_VALUE1_CUR,
NET_VALUE2_CUR,
NET_VALUE3_CUR,
NET_VALUE4_CUR,
NET_VALUE5_CUR,
NET_VALUE6_CUR,
PERCENT_CHANGE1,
PERCENT_CHANGE2,
PERCENT_CHANGE3,
PERCENT_CHANGE4,
PERCENT_CHANGE5,
PERCENT_CHANGE6,
VALUE_UOM_CODE_FK,
ASSOC_UOM_CODE_FK,
VALUES_SHEET_NAME,
UOM_CONVERSION_FACTOR,
END_DATE_CUR,
END_DATE_NEW,
EFFECTIVE_DATE_CUR,
EVENT_EFFECTIVE_DATE,
EVENT_ACTION_CR_FK,
EVENT_STATUS_CR_FK,
EVENT_CONDITION_CR_FK,
EVENT_SOURCE_CR_FK,
EVENT_PRIORITY_CR_FK,
RESULT_TYPE_CR_FK,
TABLE_ID_FK,
BATCH_NO,
IMPORT_BATCH_NO,
RULES_FK,
RECORD_STATUS_CR_FK,
UPDATE_TIMESTAMP
)
SELECT
A.EVENT_ID,
A.EVENT_TYPE_CR_FK,
A.EVENT_ENTITY_CLASS_CR_FK,
A.userDatabase_ID,
A.DATA_NAME_FK,
A.IMPORT_JOB_FK,
A.PRODUCT_STRUCTURE_FK,
A.ORG_ENTITY_STRUCTURE_FK,
A.ENTITY_CLASS_CR_FK,
A.ENTITY_DATA_NAME_FK,
A.ENTITY_STRUCTURE_FK,
A.DATA_SET_FK,
A.DATA_TYPE_CR_FK,
A.ORG_IND,
A.TABLE_NAME,
A.NET_VALUE1_NEW,
A.NET_VALUE2_NEW,
A.NET_VALUE3_NEW,
A.NET_VALUE4_NEW,
A.NET_VALUE5_NEW,
A.NET_VALUE6_NEW,
A.NET_VALUE1,
A.NET_VALUE2,
A.NET_VALUE3,
A.NET_VALUE4,
A.NET_VALUE5,
A.NET_VALUE6,
CASE ISNULL (A.NET_VALUE1, 0 )
WHEN 0 THEN 0
ELSE ( ( A.NET_VALUE1_NEW - A.NET_VALUE1) / A.NET_VALUE1 )
END,
CASE ISNULL (A.NET_VALUE2, 0 )
WHEN 0 THEN 0
ELSE ( ( A.NET_VALUE2_NEW - A.NET_VALUE2 ) / A.NET_VALUE2 )
END,
CASE ISNULL (A.NET_VALUE3, 0 )
WHEN 0 THEN 0
ELSE ( ( A.NET_VALUE3_NEW - A.NET_VALUE3 ) / A.NET_VALUE3 )
END,
CASE ISNULL (A.NET_VALUE4, 0 )
WHEN 0 THEN 0
ELSE ( ( A.NET_VALUE4_NEW - A.NET_VALUE4 ) / A.NET_VALUE4 )
END,
CASE ISNULL (A.NET_VALUE5, 0 )
WHEN 0 THEN 0
ELSE ( ( A.NET_VALUE5_NEW - A.NET_VALUE5 ) / A.NET_VALUE5 )
END,
CASE ISNULL (A.NET_VALUE6, 0 )
WHEN 0 THEN 0
ELSE ( ( A.NET_VALUE6_NEW - A.NET_VALUE6 ) / A.NET_VALUE6 )
END,
A.VALUE_UOM_CODE_FK,
A.ASSOC_UOM_CODE_FK,
A.VALUES_SHEET_NAME,
( SELECT CASE ISNULL ( A.VALUE_UOM_CODE_FK, 0 )
WHEN 0 THEN 1
ELSE
CASE ISNULL ( A.ASSOC_UOM_CODE_FK, 0 )
WHEN 0 THEN 1
ELSE
( ISNULL (
( SELECT
( SELECT ISNULL (
(SELECT uc.primary_qty
FROM userDatabase.UOM_CODE uc WITH (NOLOCK)
WHERE uc.UOM_CODE_ID = A.VALUE_UOM_CODE_FK ), 1 )
)
/
ISNULL ( (SELECT uc.primary_qty
FROM userDatabase.UOM_CODE uc WITH (NOLOCK)
WHERE uc.UOM_CODE_ID = A.ASSOC_UOM_CODE_FK )
, ISNULL ( (SELECT uc.primary_qty
FROM userDatabase.UOM_CODE uc WITH (NOLOCK)
WHERE uc.UOM_CODE_ID = A.VALUE_UOM_CODE_FK) , 1 )
)
) , 1 ) )
END END
) AS UOM_CONVERSION_FACTOR,
A.END_DATE,
A.END_DATE_NEW,
A.EFFECTIVE_DATE,
A.EVENT_EFFECTIVE_DATE,
A.EVENT_ACTION_CR_FK,
A.EVENT_STATUS_CR_FK,
A.EVENT_CONDITION_CR_FK,
A.EVENT_SOURCE_CR_FK,
A.EVENT_PRIORITY_CR_FK,
A.RESULT_TYPE_CR_FK,
A.SHEET_RESULTS_ID,
A.BATCH_NO,
A.IMPORT_BATCH_NO,
A.RULES_FK,
A.RECORD_STATUS_CR_FK,
@L_SYSDATE
FROM ( SELECT
ED.EVENT_ID,
DS.EVENT_TYPE_CR_FK,
DS.ENTITY_CLASS_CR_FK AS EVENT_ENTITY_CLASS_CR_FK,
ED.PRODUCT_STRUCTURE_FK AS userDatabase_ID,
ED.DATA_NAME_FK,
ED.IMPORT_JOB_FK,
ED.PRODUCT_STRUCTURE_FK,
CASE ISNULL ( DS.ORG_IND, 0 )
WHEN 0 THEN ISNULL ( ED.ORG_ENTITY_STRUCTURE_FK, 1 )
ELSE ED.ORG_ENTITY_STRUCTURE_FK
END AS ORG_ENTITY_STRUCTURE_FK,
DS.ENTITY_STRUCTURE_EC_CR_FK AS ENTITY_CLASS_CR_FK,
DN.ENTITY_DATA_NAME_FK,
ED.ENTITY_STRUCTURE_FK,
DN.DATA_SET_FK,
DS.DATA_TYPE_CR_FK,
DS.ORG_IND,
DS.TABLE_NAME,
ED.NET_VALUE1_NEW,
ED.NET_VALUE2_NEW,
ED.NET_VALUE3_NEW,
ED.NET_VALUE4_NEW,
ED.NET_VALUE5_NEW,
ED.NET_VALUE6_NEW,
SR.NET_VALUE1,
SR.NET_VALUE2,
SR.NET_VALUE3,
SR.NET_VALUE4,
SR.NET_VALUE5,
SR.NET_VALUE6,
ED.VALUE_UOM_CODE_FK,
( SELECT TOP 1 PUC.UOM_CODE_FK
FROM userDatabase.PRODUCT_UOM_CLASS PUC WITH (NOLOCK)
WHERE ( PUC.DATA_NAME_FK = DN.UOM_CLASS_DATA_NAME_FK
AND PUC.PRODUCT_STRUCTURE_FK = ED.PRODUCT_STRUCTURE_FK
AND ( ( DS.ORG_IND = 1
AND PUC.ORG_ENTITY_STRUCTURE_FK = ED.ORG_ENTITY_STRUCTURE_FK )
OR PUC.ORG_ENTITY_STRUCTURE_FK = 1 )
AND ISNULL ( PUC.ENTITY_STRUCTURE_FK, -999 ) = ISNULL ( ED.ENTITY_STRUCTURE_FK, -999 ) )
) AS ASSOC_UOM_CODE_FK,
ED.VALUES_SHEET_NAME,
SR.END_DATE,
ED.END_DATE_NEW,
SR.EFFECTIVE_DATE,
ED.EVENT_EFFECTIVE_DATE,
CASE WHEN ED.EVENT_ACTION_CR_FK = 59
THEN 59
ELSE
CASE WHEN SR.SHEET_RESULTS_ID IS NULL
THEN 51
ELSE 52
END
END AS EVENT_ACTION_CR_FK,
ED.EVENT_STATUS_CR_FK,
ED.EVENT_CONDITION_CR_FK,
ED.EVENT_SOURCE_CR_FK,
ED.EVENT_PRIORITY_CR_FK,
ISNULL ( ED.RESULT_TYPE_CR_FK, 711 ) AS RESULT_TYPE_CR_FK,
SR.SHEET_RESULTS_ID,
ED.BATCH_NO,
ED.IMPORT_BATCH_NO,
ED.RULES_FK,
ED.RECORD_STATUS_CR_FK
FROM SYNCHRONIZER.EVENT_DATA ED WITH (NOLOCK)
INNER JOIN userDatabase.DATA_NAME DN WITH (NOLOCK)
ON ( DN.DATA_NAME_ID = ED.DATA_NAME_FK )
INNER JOIN userDatabase.DATA_SET DS WITH (NOLOCK)
ON ( DS.DATA_SET_ID = DN.DATA_SET_FK )
LEFT JOIN marginmgr.SHEET_RESULTS SR WITH (NOLOCK)
ON ( SR.DATA_NAME_FK = ED.DATA_NAME_FK
AND ISNULL ( SR.PRODUCT_STRUCTURE_FK, 0 ) = ISNULL ( ED.PRODUCT_STRUCTURE_FK, 0 )
AND ISNULL ( SR.ORG_ENTITY_STRUCTURE_FK, 0 ) = ISNULL ( ED.ORG_ENTITY_STRUCTURE_FK, 1 )
AND ISNULL ( SR.ENTITY_STRUCTURE_FK, 0 ) = ISNULL ( ED.ENTITY_STRUCTURE_FK, 0 )
)
WHERE 1 = 1
AND EVENT_STATUS_CR_FK = 88
AND (
( ISNULL ( @in_event_fk, -999 ) = -999
AND ISNULL ( ED.BATCH_NO, -999 ) = ISNULL ( @in_batch_no, -999 )
AND ISNULL ( ED.import_job_fk, -999 ) = ISNULL (@in_import_job_fk, -999 )
AND isnull ( ED.event_priority_cr_fk, -999 ) = isnull (@in_event_priority_cr_fk, -999)
AND ISNULL ( ds.table_name, 'NULL DATA' ) = ISNULL ( @in_table_name, 'NULL DATA' ) )
OR ED.EVENT_ID = ISNULL (@in_event_fk, -999 )
)
AND ( @in_data_name_fk = -999
OR ED.data_name_fk = @in_data_name_fk )
) A
Resultados de sp_configure:
access check cache bucket count 0 65536 0 0
access check cache quota 0 2147483647 0 0
Ad Hoc Distributed Queries 0 1 0 0
affinity I/O mask -2147483648 2147483647 0 0
affinity mask -2147483648 2147483647 0 0
affinity64 I/O mask -2147483648 2147483647 0 0
affinity64 mask -2147483648 2147483647 0 0
Agent XPs 0 1 1 1
allow updates 0 1 0 0
backup compression default 0 1 0 0
blocked process threshold (s) 0 86400 0 0
c2 audit mode 0 1 0 0
clr enabled 0 1 1 1
common criteria compliance enabled 0 1 0 0
contained database authentication 0 1 0 0
cost threshold for parallelism 0 32767 5 5
cross db ownership chaining 0 1 0 0
cursor threshold -1 2147483647 -1 -1
Database Mail XPs 0 1 1 1
default full-text language 0 2147483647 1033 1033
default language 0 9999 0 0
default trace enabled 0 1 1 1
disallow results from triggers 0 1 0 0
EKM provider enabled 0 1 0 0
filestream access level 0 2 0 0
fill factor (%) 0 100 0 0
ft crawl bandwidth (max) 0 32767 100 100
ft crawl bandwidth (min) 0 32767 0 0
ft notify bandwidth (max) 0 32767 100 100
ft notify bandwidth (min) 0 32767 0 0
index create memory (KB) 704 2147483647 0 0
in-doubt xact resolution 0 2 0 0
lightweight pooling 0 1 0 0
locks 5000 2147483647 0 0
max degree of parallelism 0 32767 0 0
max full-text crawl range 0 256 4 4
max server memory (MB) 128 2147483647 5120 5120
max text repl size (B) -1 2147483647 65536 65536
max worker threads 128 65535 0 0
media retention 0 365 0 0
min memory per query (KB) 512 2147483647 1024 1024
min server memory (MB) 0 2147483647 128 128
nested triggers 0 1 1 1
network packet size (B) 512 32767 4096 4096
Ole Automation Procedures 0 1 0 0
open objects 0 2147483647 0 0
optimize for ad hoc workloads 0 1 0 0
PH timeout (s) 1 3600 60 60
precompute rank 0 1 0 0
priority boost 0 1 0 0
query governor cost limit 0 2147483647 0 0
query wait (s) -1 2147483647 -1 -1
recovery interval (min) 0 32767 0 0
remote access 0 1 1 1
remote admin connections 0 1 0 0
remote login timeout (s) 0 2147483647 10 10
remote proc trans 0 1 0 0
remote query timeout (s) 0 2147483647 600 600
Replication XPs 0 1 0 0
scan for startup procs 0 1 0 0
server trigger recursion 0 1 1 1
set working set size 0 1 0 0
show advanced options 0 1 1 1
SMO and DMO XPs 0 1 1 1
transform noise words 0 1 0 0
two digit year cutoff 1753 9999 2049 2049
user connections 0 32767 0 0
user options 0 32767 0 0
xp_cmdshell 0 1 1 1
Enlace al XML del plan Exec (demasiado grande para incrustar).
fuente
Respuestas:
No solo verá el recurso ENCRYPTION_SCAN en su lista de espera cuando se use Cifrado (como TDE).
Ciertas operaciones tomarán un bloqueo compartido en este recurso para asegurarse de que la base de datos no se cifre durante la operación.
En el momento en que cifraría una base de datos de usuario con TDE, tempdb también se cifrará (de lo contrario, correría un riesgo de seguridad cuando los datos de usuario se usen en temp db).
Por lo tanto, algunas operaciones tomarán un bloqueo compartido en ENCRYPTION_SCAN en Tempdb para evitar que Tempdb se cifre.
Aquí hay dos ejemplos:
INSERTAR A GRANEL
El código anterior generará 500k registros en una tabla temporal global, puede exportarlos con los siguientes comandos. Si ejecuta esto desde SSMS, asegúrese de estar en modo SQLCMD:
Asegúrese de elegir un directorio donde la cuenta de servicio de SQL Server tenga permisos de escritura y si ejecuta esto desde SSMS, ejecútelo localmente en SQL Server.
Lo siguiente es comenzar un ciclo de inserción masiva. Mientras se ejecuta el bucle, abra una segunda pantalla y comience a ejecutar sp_lock hasta que vea el bloqueo compartido ENCRYPTION_SCAN en DB_ID 2 (que es Tempdb).
El ciclo de importación masiva:
Vea el resultado de sp_lock en la segunda ventana:
CLASIFICAR EN TEMPDB
Con la misma tabla Temp en su lugar, comience este ciclo muy simple:
Producirá el siguiente plan de ejecución:
(Asegúrese de que #Import realmente esté poblado, ya que dependiendo de cuándo detuvo el ciclo de importación masiva anterior, ¡podría estar vacío!)
Nuevamente, ejecute sp_lock en una segunda ventana hasta que vea aparecer el recurso ENCRYPTION_SCAN:
Ahora ya sabe, por qué esta espera de recursos está apareciendo. Podría estar muy bien que este no sea tu problema. Solo quería señalar las otras razones que hacen que ENCRYPTION_SCAN aparezca. El motivo de la desaceleración de su consulta podría ser otra cosa. Dejaré mejorar su plan de consulta a los expertos en este sitio ;-) Sin embargo, ¿podría publicar también el plan de ejecución real en lugar de solo el plan estimado?
fuente
ENCRYPTION_SCAN
arenque es un poco rojo. Es unaS
cerradura. Entonces, la teoría es que durante el período de 5 horas donde el OP veENCRYPTION_SCAN
que, de hecho, solo está ocupado haciendo la inserción. ¿No está bloqueado por eso?