Solucionar problemas de espacio en disco insuficiente en tempdb
Este tema contiene procedimientos y recomendaciones para ayudarle a diagnosticar y solucionar problemas que se producen porque no hay espacio de disco suficiente en la base de datos tempdb. Si se agota el espacio de disco de tempdb, se pueden producir interrupciones importantes en el entorno de producción de SQL Server y es posible que las aplicaciones en ejecución no puedan finalizar sus operaciones.
Requisitos de espacio de tempdb
La base de datos del sistema tempdb es un recurso global a disposición de todos los usuarios conectados a una instancia de SQL Server. La base de datos tempdb se utiliza para almacenar los objetos siguientes: objetos de usuarios, objetos internos y almacenes de versiones.
Puede utilizar la vista de administración dinámica sys.dm_db_file_space_usage para supervisar el espacio en disco que utilizan los objetos de usuario, los objetos internos y los almacenes de versiones en los archivos de tempdb. Asimismo, para supervisar la actividad de asignación o desasignación de páginas en tempdb en el nivel de sesión o tarea, se pueden utilizar las vistas de administración dinámica sys.dm_db_session_space_usage y sys.dm_db_task_space_usage. Estas vistas pueden utilizarse para identificar consultas grandes, tablas temporales o variables de tabla que utilizan mucho espacio de disco de tempdb.
Diagnosticar problemas de espacio de disco de tempdb
En la tabla siguiente se muestran los mensajes de error que indican que no hay espacio de disco suficiente en la base de datos tempdb. Estos errores se pueden encontrar en el registro de errores de SQL Server y también pueden ser devueltos por cualquier aplicación que se esté ejecutando.
Error |
Se produce cuando |
---|---|
1101 ó 1105 |
Cualquier sesión debe asignar espacio en tempdb. |
3959 |
El almacén de versiones está lleno. Normalmente, este error aparece después de un error 1105 ó 1101 en el registro. |
3967 |
El almacén de versiones debe reducirse porque tempdb está llena. |
3958 ó 3966 |
Una transacción no encuentra el registro de versión necesario en tempdb. |
Los problemas de espacio de disco de tempdb también se indican cuando se establece la opción de crecimiento automático de la base de datos y su tamaño aumenta rápidamente.
Supervisar el espacio de disco de tempdb
En los ejemplos siguientes se muestra cómo determinar la cantidad de espacio disponible en tempdb y el espacio utilizado por el almacén de versiones y los objetos internos y de usuario.
Determinar la cantidad de espacio disponible en tempdb
La consulta siguiente devuelve el número total de páginas libres y el espacio disponible total, en megabytes (MB), que están disponibles en todos los archivos de tempdb.
SELECT SUM(unallocated_extent_page_count) AS [free pages],
(SUM(unallocated_extent_page_count)*1.0/128) AS [free space in MB]
FROM sys.dm_db_file_space_usage;
Determinar la cantidad de espacio utilizado por el almacén de versiones
La consulta siguiente devuelve el número total de páginas utilizadas por el almacén de versiones y el espacio total, en MB, utilizado por el almacén de versiones en tempdb.
SELECT SUM(version_store_reserved_page_count) AS [version store pages used],
(SUM(version_store_reserved_page_count)*1.0/128) AS [version store space in MB]
FROM sys.dm_db_file_space_usage;
Determinar la transacción que más tarda en ejecutarse
Si el almacén de versiones utiliza mucho espacio de tempdb, será necesario determinar cuál es la transacción que más tarda en ejecutarse. Utilice esta consulta para mostrar las transacciones activas ordenadas por transacción de mayor duración.
SELECT transaction_id
FROM sys.dm_tran_active_snapshot_database_transactions
ORDER BY elapsed_time_seconds DESC;
Una transacción de larga duración que no está relacionada con una operación de índices en línea requiere un almacén de versiones grande. Este almacén de versiones mantiene todas las versiones generadas desde que se inició la transacción. Las transacciones de generación de índices en línea pueden tardar mucho en finalizar, pero se utiliza un almacén de versiones independiente, dedicado a las operaciones de índices en línea. Por tanto, estas operaciones no impiden que se quiten las versiones de otras transacciones. Para obtener más información, vea Uso de recursos del control de versiones de filas.
Determinar la cantidad de espacio utilizado por objetos internos
La consulta siguiente devuelve el número total de páginas utilizadas por los objetos internos y el espacio total, en MB, utilizado por los objetos internos en tempdb.
SELECT SUM(internal_object_reserved_page_count) AS [internal object pages used],
(SUM(internal_object_reserved_page_count)*1.0/128) AS [internal object space in MB]
FROM sys.dm_db_file_space_usage;
Determinar la cantidad de espacio utilizado por objetos de usuario
La consulta siguiente devuelve el número total de páginas utilizadas por los objetos de usuario y el espacio total utilizado por los objetos de usuario en tempdb.
SELECT SUM(user_object_reserved_page_count) AS [user object pages used],
(SUM(user_object_reserved_page_count)*1.0/128) AS [user object space in MB]
FROM sys.dm_db_file_space_usage;
Determinar la cantidad total de espacio (libre y utilizado)
La consulta siguiente devuelve la cantidad total de espacio de disco utilizado por todos los archivos de tempdb.
SELECT SUM(size)*1.0/128 AS [size in MB]
FROM tempdb.sys.database_files
Supervisar el espacio utilizado por las consultas
Uno de los problemas más habituales relacionados con el uso del espacio de tempdb tiene que ver con las consultas grandes, que utilizan una gran cantidad de espacio. Por lo general, este espacio se utiliza para los objetos internos, como las tablas o archivos de trabajo. Aunque la supervisión del espacio utilizado por los objetos internos indica cuánto espacio se utiliza, no identifica directamente la consulta que utiliza ese espacio.
Los métodos siguientes ayudan a identificar las consultas que utilizan la mayor parte del espacio de tempdb. El primer método examina los datos de nivel de lote y hace un uso menos intensivo de los datos que el segundo método. El segundo método se puede utilizar para identificar la consulta, la tabla temporal o la variable de tabla específica que está utilizando el espacio del disco, pero deben recopilarse más datos para obtener la respuesta.
Método 1: Información de nivel de lote
Si la solicitud de lote contiene pocas consultas y sólo una de ellas es una consulta compleja, esta información suele ser suficiente para saber qué lote, y no qué consulta específica, está utilizando el espacio.
Para continuar con este método, es necesario configurar un trabajo del Agente SQL Server para el sondeo de las vistas de administración dinámica sys.dm_db_session_space_usage y sys.dm_db_task_space_usage utilizando un intervalo de sondeo de pocos minutos. En el ejemplo siguiente se emplea un intervalo de sondeo de tres minutos. Es necesario sondear ambas vistas porque sys.dm_db_session_space_usage no incluye la actividad de asignación de la tarea activa actual. Al comparar la diferencia entre las páginas asignadas en dos intervalos de tiempo se puede calcular cuántas páginas se asignan entre un intervalo y otro.
En los ejemplos siguientes se proporcionan las consultas necesarias para el trabajo del Agente SQL Server.
A. Obtener el espacio utilizado por los objetos internos en todas las tareas que actualmente se ejecutan en cada sesión.
En el ejemplo siguiente se crea la vista all_task_usage. Cuando se consulta, la vista devuelve el espacio total utilizado por los objetos internos en todas las tareas que actualmente se ejecutan en tempdb.
CREATE VIEW all_task_usage
AS
SELECT session_id,
SUM(internal_objects_alloc_page_count) AS task_internal_objects_alloc_page_count,
SUM(internal_objects_dealloc_page_count) AS task_internal_objects_dealloc_page_count
FROM sys.dm_db_task_space_usage
GROUP BY session_id;
GO
B. Obtener el espacio utilizado por los objetos internos para las tareas que actualmente se ejecutan y las tareas finalizadas en la sesión actual.
En el ejemplo siguiente se crea la vista all_session_usage. Cuando se consulta, la vista devuelve el espacio utilizado por los objetos internos para las tareas finalizadas y en ejecución en tempdb.
CREATE VIEW all_session_usage
AS
SELECT R1.session_id,
R1.internal_objects_alloc_page_count
+ R2.task_internal_objects_alloc_page_count AS session_internal_objects_alloc_page_count,
R1.internal_objects_dealloc_page_count
+ R2.task_internal_objects_dealloc_page_count AS session_internal_objects_dealloc_page_count
FROM sys.dm_db_session_space_usage AS R1
INNER JOIN all_task_usage AS R2 ON R1.session_id = R2.session_id;
GO
Se asume que, cuando se consultan estas vistas en un intervalo de tres minutos, los conjuntos de resultados proporcionan la información siguiente.
A las 5:00 p.m., la sesión 71 asignó 100 páginas y canceló la asignación de 100 páginas desde el comienzo de la sesión.
A las 5:03 p.m., la sesión 71 asignó 20100 páginas y canceló la asignación de 100 páginas desde el comienzo de la sesión.
Al analizar esta información, puede indicar que entre las dos mediciones: la sesión asignó 20.000 páginas para los objetos internos y no desasignó ninguna página. Esto es indicativo de un posible problema.
Nota
Como administrador de la base de datos, puede decidir sondear con mayor frecuencia que tres minutos. Sin embargo, si una consulta se ejecuta durante menos de tres minutos, posiblemente no utilizará una cantidad de espacio de tempdb importante.
Para determinar el lote que se está ejecutando en ese momento, utilice el Analizador de SQL Server para capturar las clases de eventos RPC:Completed y SQL:BatchCompleted.
Una alternativa a utilizar el SQL Server Profiler es ejecutar DBCC INPUTBUFFER una vez cada tres minutos para todas las sesiones, como se muestra en el ejemplo siguiente.
DECLARE @max int;
DECLARE @i int;
SELECT @max = max (session_id)
FROM sys.dm_exec_sessions
SET @i = 51
WHILE @i <= @max BEGIN
IF EXISTS (SELECT session_id FROM sys.dm_exec_sessions
WHERE session_id=@i)
DBCC INPUTBUFFER (@i)
SET @i=@i+1
END;
Método 2: Información de nivel de consulta
En ocasiones, no basta ver el búfer de entrada o el evento SQL:BatchCompleted del SQL Server Profiler para saber qué consulta está utilizando la mayor parte del espacio de disco de tempdb. Puede utilizar los métodos siguientes para obtener esta respuesta, pero éstos requieren la recopilación de un número mayor de datos que los procedimientos descritos en el método 1.
Para continuar con este método, configure un trabajo del Agente SQL Server que sondee la vista de administración dinámica sys.dm_db_task_space_usage. El intervalo de sondeo debería ser más corto que el del método 1 (por ejemplo, una vez cada minuto), ya que sys.dm_db_task_space_usage no devuelve datos si la consulta (tarea) no se está ejecutando en ese momento.
En la consulta de sondeo, la vista definida en la vista de administración dinámica sys.dm_db_task_space_usage se combina con sys.dm_exec_requests para devolver las columnas sql_handle, statement_start_offset, statement_end_offset y plan_handle.
CREATE VIEW all_request_usage
AS
SELECT session_id, request_id,
SUM(internal_objects_alloc_page_count) AS request_internal_objects_alloc_page_count,
SUM(internal_objects_dealloc_page_count)AS request_internal_objects_dealloc_page_count
FROM sys.dm_db_task_space_usage
GROUP BY session_id, request_id;
GO
CREATE VIEW all_query_usage
AS
SELECT R1.session_id, R1.request_id,
R1.request_internal_objects_alloc_page_count, R1.request_internal_objects_dealloc_page_count,
R2.sql_handle, R2.statement_start_offset, R2.statement_end_offset, R2.plan_handle
FROM all_request_usage R1
INNER JOIN sys.dm_exec_requests R2 ON R1.session_id = R2.session_id and R1.request_id = R2.request_id;
GO
Si el plan de consulta está almacenado en caché, se puede recuperar el texto de Transact-SQL de la consulta y el plan de ejecución de consultas en el formato de los planes de presentación XML cuando se desee. Para obtener el texto de Transact-SQL de la consulta que se ejecuta, utilice el valor sql_handle y la función de administración dinámica sys.dm_exec_sql_text. Para obtener el plan de ejecución de consultas, use el valor plan_handle y la función de administración dinámica sys.dm_exec_query_plan.
SELECT * FROM sys.dm_exec_sql_text(@sql_handle);
SELECT * FROM sys.dm_exec_query_plan(@plan_handle);
Si el plan de consulta no está almacenado en caché, puede utilizar uno de los métodos siguientes para obtener el texto de Transact-SQL de la consulta y el plan de ejecución de consultas.
A. Utilizar el método de sondeo
Sondee la vista all_query_usage y ejecute la consulta siguiente para obtener el texto de la consulta:
SELECT R1.sql_handle, R2.text
FROM all_query_usage AS R1
OUTER APPLY sys.dm_exec_sql_text(R1.sql_handle) AS R2;
Dado que sql_handle debería ser único para cada lote único, no es necesario guardar entradas duplicadas de sql_handle.
Para guardar el identificador del plan y el plan XML, ejecute la consulta siguiente.
SELECT R1.plan_handle, R2.query_plan
FROM all_query_usage AS R1
OUTER APPLY sys.dm_exec_query_plan(R1.plan_handle) AS R2;
B. Utilizar los eventos del Analizador de SQL Server
Como alternativa a sondear las funciones sys.dm_exec_sql_text y sys.dm_exec_query_plan, puede utilizar los eventos del SQL Server Profiler. Algunos eventos del analizador se pueden utilizar para capturar el plan de consulta y el texto de la consulta que se genera. Por ejemplo, el evento 165 devuelve estadísticas de rendimiento de traza, texto SQL, planes de consulta y estadísticas de consulta.
Supervisar el espacio utilizado por tablas temporales y variables de tabla
Para supervisar el espacio utilizado por las tablas temporales y las variables temporales se puede utilizar un método similar al sondeo de consultas. Las aplicaciones que adquieren una gran cantidad de datos de usuario de tablas o variables temporales pueden generar problemas con el uso del espacio de tempdb. Estas tablas o variables pertenecen a los objetos de usuario. Puede utilizar las columnas user_objects_alloc_page_count y user_objects_dealloc_page_count de la vista de administración dinámica sys.dm_db_session_space_usage y realizar los métodos descritos anteriormente.
Supervisar la asignación y desasignación de páginas por sesión
En la tabla siguiente se muestran los resultados devueltos por las vistas de administración dinámica sys.dm_db_file_space_usage, sys.dm_db_session_space_usage y sys.dm_db_task_space_usage para una sesión específica. Cada fila representa una actividad de asignación o desasignación en tempdb para una sesión específica. La actividad se muestra en la columna Evento. Las demás columnas muestran los valores que se devolverían en las columnas de las vistas de administración dinámica.
En este escenario se asume que la base de datos tempdb comienza con 872 páginas de extensiones sin asignar y 100 páginas de extensiones reservadas para objetos de usuario. La sesión asigna 10 páginas para una tabla de usuario y, después, cancela la asignación de todas ellas. Las 8 primeras páginas se encuentran en una extensión mixta. Las 2 páginas restantes se encuentran en una extensión uniforme.
Evento |
dm_db_file_space_usage unallocated_extent_page_count column |
dm_db_file_space_usage user_object_reserved_page_count column |
dm_db_session_space_usage and dm_db_task_space_usage user_object_alloc_page_count column |
dm_db_session_space_usage and dm_db_task_space_usage user_object_dealloc_page_count column |
---|---|---|---|---|
Inicio |
872 |
100 |
0 |
0 |
Asignar la página 1 de la extensión mixta existente |
872 |
100 |
1 |
0 |
Asignar las páginas 2 a 8: consumir una extensión mixta nueva |
864 |
80 |
8 |
0 |
Asignar la página 9: consumir una extensión uniforme nueva |
856 |
108 |
16 |
0 |
Se asigna la página 10 de la extensión uniforme existente |
856 |
108 |
16 |
0 |
Se cancela la asignación de la página 10 de la extensión uniforme existente |
856 |
108 |
16 |
0 |
Se cancela la asignación de la página 9 y la extensión uniforme |
864 |
100 |
16 |
8 |
Se cancela la asignación de la página 8 |
864 |
100 |
16 |
9 |
Se cancela la asignación de las páginas 7 a 1, y se cancela la asignación en la extensión mixta |
872 |
100 |
16 |
16 |
Vea también