En la foto hay una escena de la vieja comedia "Airplane": los boomers lo recuerdan.
Ella no está aquí por casualidad. Pero útil después.A dba no le gusta perfmon
No es en absoluto porque la interfaz PerfMon no ha cambiado con Windows NT 3.1 (?) Y devuelve el calor de dos milésimas. Por cierto, tal vez alguien sepa la explicación de este hecho extraño. El panel de control se reescribe varias veces al año. Incluso la calculadora fue reescrita. Pero no perfMon.DBA piensa con palabras de tapa. Cuando un buen médico de DBA llega a un servidor SQL enfermo, abre su maletín, y en el maletín hay una gran cantidad de cuartos que le sirven fielmente. Él toma el más corto de ellos de memoria. A veces, un DBA puede analizar las métricas de PerfMon: disco físico o longitud de la cola de disco. Sin embargo, un DBA real obtendrá sus propias métricas del servidor SQL, no a través de PerfMon, sino con un parche, por ejemplo, como este:select * from sys.dm_os_performance_counters
where object_name='SQLServer:Buffer Manager'
and counter_name like 'Page life expectancy%'
and instance_name=''
Cuando los representantes de TI, divorciados de la esfera de DBA, le preguntan, "¿qué métricas quieres que recopilemos?" (bueno, hay todo tipo de splunk, cuadrado, etc.), luego el DBA comienza a pensar en los scripts y el resto en las métricas de perfmon. Al mismo tiempo, como regla, intentan volcar todas las métricas en el DBA. Cuando esto sucede, la imagen es inútil en su congestión. Y luego un video corto de la película "Avión" me ayudará .Como resultado, DBA escribe keri, que escribe estadísticas cada N minutos en alguna placa de la base de datos DBAtasks. ¿Te reconoces a ti mismo?Abogado Diablo (perfmon)
Sin embargo, los contadores de perfmon son una herramienta estándar. Se pueden registrar, establecer alertas, pero lo más importante es que hay una gran cantidad de sistemas que "fusionan" estas métricas de muchas máquinas en un repositorio centralizado, le permiten analizarlas y crear gráficos hermosos (y no como perfmon).¡Resulta que podemos hacer amigos con el mundo SQL y el mundo PerfMon!A continuación les mostraré cómo.Ahora los detalles irán
Como ejemplo, mostraremos cómo exportar métricas que el SQL mismo no publica en PerfMon. Por ejemplo, la consulta a continuación:select
convert(numeric(10,2),round(((sum(version_store_reserved_page_count)*1.0)/128.00),2)),
convert(numeric(10,2),round(((sum(user_object_reserved_page_count)*1.0)/128.00),2)),
convert(numeric(10,2),round(((sum(internal_object_reserved_page_count)*1.0)/128.00),2))
from
tempdb.sys.dm_db_file_space_usage;
devuelve la cantidad de espacio tempdb utilizado por el almacén de versiones (para la instantánea), los objetos de usuario (#tab y ## pestaña) y el espacio de almacenamiento ordenado / temporal. Creemos métricas para ellos (mayores de 18 años, los equipos no están documentados)dbcc addinstance ('SQLServer:User Settable', 'TempDB version store KB')
dbcc addinstance ('SQLServer:User Settable', 'TempDB user store KB')
dbcc addinstance ('SQLServer:User Settable', 'TempDB sort store KB')
Esto creará tres métricas en SQLServer -> UserSettable -> Query. Las métricas son enteros: int (no bigint). Además, su significado se interpreta como es. Es decir, si necesita un delta del valor anterior, entonces esta es su preocupación. Pero en este caso, solo necesitamos asignar valores a las métricas:declare @TEMPDBver int, @TEMPDBuser int, @TEMPDBsort int
select
@TEMPDBver = convert(numeric(10,2),round(((sum(version_store_reserved_page_count) *1.0)/128.00),2)),
@TEMPDBuser = convert(numeric(10,2),round(((sum(user_object_reserved_page_count) *1.0)/128.00),2)),
@TEMPDBsort = convert(numeric(10,2),round(((sum(internal_object_reserved_page_count) *1.0)/128.00),2))
from tempdb.sys.dm_db_file_space_usage;
if @TEMPDBver is not null
dbcc setinstance ('SQLServer:User Settable', 'Query',
'TempDB version store KB', @TEMPDBver)
if @TEMPDBuser is not null
dbcc setinstance ('SQLServer:User Settable', 'Query',
'TempDB user store KB', @TEMPDBuser)
if @TEMPDBsort is not null
dbcc setinstance ('SQLServer:User Settable', 'Query',
'TempDB sort store KB', @TEMPDBsort)
En realidad, eso es todo. Ahora solo llame a este código regularmente y todo funcionará.Contadores Delta
Ahora hagamos un contador delta. Este será el tiempo de espera de bloqueo en ms.dbcc addinstance ('SQLServer:User Settable', 'LOCK ms per s')
Aquí puede objetarme que tal métrica ya existe:select * from sys.dm_os_performance_counters
where counter_name like 'Lock Wait Time (ms)%'
and instance_name='_Total'
and object_name='SQLServer:Locks'
Pero esta métrica solo es eventualmente consistente. Como recordarán, si los protones son inestables, cualquier base de datos en el universo es eventualmente consistente. Es decir, si crea un bloqueo y observa el valor de esta métrica, ¡entonces no crecerá! Y solo al final del bloqueo, su valor saltará bruscamente durante todo el tiempo de espera. En el gráfico, en lugar de la 'meseta' esperada, obtendrá un pico agudo, que también estropea su escala a lo largo del eje Y.El mismo problema es con kvery:select sum(wait_time_ms)
from sys.dm_os_wait_stats
where wait_type like 'LCK_%'
Por lo tanto, debemos agregar el tiempo de los actuales al tiempo de los bloqueos 'completados':declare @NEWlock bigint
select @NEWlock=sum(wait_time_ms)
from sys.dm_os_wait_stats
where wait_type like 'LCK_%'
select @NEWlock=@NEWlock+isnull(sum(waittime),0)
from master.dbo.sysprocesses
where blocked>0 and lastwaittype like 'LCK_%'
Esta consulta ya da la meseta correcta en el gráfico.Ahora debemos considerar el delta del valor anterior. Hay dos maneras:- Diseñe un proceso como un trabajo que se llama con frecuencia (por ejemplo, una vez por minuto). Cree una etiqueta para almacenar valores anteriores. De hecho, a menudo es malo llamar al trabajo (gastos generales + competencia por el historial de ejecución de los trabajos), y puede prescindir de una placa adicional:
- Cree un proceso que se ejecute en un bucle sin fin con waitfor. El proceso recuerda el valor anterior en la variable. Procesaremos el proceso como un trabajo con dos horarios: al inicio y una vez por hora (en caso de que el trabajo caiga, entonces se reiniciará)
En el segundo caso, es bastante posible hacer un ciclo cada cinco segundos o incluso con más frecuencia. Entonces, obtenemos:declare @OLDlock bigint, @NEWlock bigint
declare @lock int, @seconds int = 5
loop:
set @OLDlock=@NEWlock
select @NEWlock=sum(wait_time_ms)
from sys.dm_os_wait_stats
where wait_type like 'LCK_%'
select @NEWlock=@NEWlock+isnull(sum(waittime),0)
from master.dbo.sysprocesses
where blocked>0 and lastwaittype like 'LCK_%'
set @lock=(@NEWlock-@OLDlock)/@seconds
if @lock is not null
dbcc setinstance ('SQLServer:User Settable', 'Query',
'LOCK ms per s', @lock)
waitfor delay '00:00:05'
goto loop
Tenga en cuenta que la primera vez que ejecute un bucle DBCC, se omitirá (lo cual es correcto), ya que @OLDlock (y bloquear) será nulo.