web-dev-qa-db-fra.com

Trouvez des transactions qui remplissent la version de la version

nous avons activé "Read_Committed_snapshot" pour certaines de nos bases de données SQL Server 2005.

Maintenant de temps en temps, nous voyons que notre tempdb remplit le disque dur et nous soupçonnons que le magasin de la version soit le coupable.

Nous surveillons l'utilisation de TEMPDB à travers sys.dm_db_file_space_usage Et une fois que nous voyons que la version de la version augmente (comme indiqué par version_store_reserved_page_count) Nous souhaitons identifier les transactions qui utilisent activement la version de la version.

J'utilise la déclaration suivante pour trouver des transactions en utilisant la version de la version:

SELECT db_name(spu.database_id) as database_name,
       at.transaction_begin_time as begin_time,
       case 
         when at.transaction_state in (0,1) then 'init'
         when at.transaction_state = 2 then 'active'
         when at.transaction_state = 3 then 'ended'
         when at.transaction_state = 4 then 'committing'
         when at.transaction_state = 6 then 'comitted'
         when at.transaction_state = 7 then 'rolling back'
         when at.transaction_state = 6 then 'rolled back'
         else 'other'
       end as transaction_state,
       ast.elapsed_time_seconds as elapsed_seconds,
       ses.program_name, 
       ses.row_count,
       (spu.user_objects_alloc_page_count * 8) AS user_objects_kb,
       (spu.user_objects_dealloc_page_count * 8) AS user_objects_deallocated_kb,
       (spu.internal_objects_alloc_page_count * 8) AS internal_objects_kb,
       (spu.internal_objects_dealloc_page_count * 8) AS internal_objects_deallocated_kb
FROM sys.dm_tran_active_snapshot_database_transactions ast
  JOIN sys.dm_tran_active_transactions at on at.transaction_id = ast.transaction_id
  JOIN sys.dm_exec_sessions ses ON ses.session_id = ast.session_id
  JOIN sys.dm_db_session_space_usage spu ON spu.session_id = ses.session_id
ORDER BY elapsed_time_seconds DESC
;

Mais cela ne m'aide pas à identifier la manière dont beaucoup espace chaque transaction utilise réellement dans la version de la version.

Existe-t-il un moyen d'obtenir les informations sur l'utilisation de l'espace dans la version de la version par transaction (ou même mieux: par déclaration)?

EDIT: Le "duplicate potentiel" ( Comment identifier quelle requête remplit le journal de transaction tempdb? ) ne prend pas le magasin de version en compte (uniquement des tables Temps, des variables de table et de l'espace utilisé pour trier et opérations de hachage).

En fait, la solution acceptée ne montrera rien aux transactions uniquement Utilisez la version de la version (au moins pas pour moi)

6

Il n'a pas vraiment de sens de suivre la version de la version par session ou par transaction ou par requête. Si deux utilisateurs différents utilisent la même version d'une rangée/table, qui le possède?

Vous pouvez suivre cela par objet, ce qui peut vous aider à réduire lesquels les modules causent la baratte. Jettes un coup d'oeil à sys.dm_tran_top_version_generators :

USE [your database];
GO
SELECT obj = 
  QUOTENAME(OBJECT_SCHEMA_NAME(p.object_id))
  + '.' + QUOTENAME(OBJECT_NAME(p.object_id)),
  vs.aggregated_record_length_in_bytes
FROM sys.dm_tran_top_version_generators AS vs
INNER JOIN sys.partitions AS p
ON vs.rowset_id = p.hobt_id
WHERE vs.database_id = DB_ID()
AND p.index_id IN (0,1);

Et sur SQL Server 2008+, vous pouvez également déterminer quels modules référennent ces tables en ajoutant sys.dm_sql_referencing_entities:

SELECT 
  obj = QUOTENAME(OBJECT_SCHEMA_NAME(p.object_id))
  + '.' + QUOTENAME(OBJECT_NAME(p.object_id)),
  referenced_by = QUOTENAME(r.referencing_schema_name)
  + '.' + QUOTENAME(r.referencing_entity_name),
  vs.aggregated_record_length_in_bytes AS size
FROM sys.dm_tran_top_version_generators AS vs
INNER JOIN sys.partitions AS p
ON vs.rowset_id = p.hobt_id
CROSS APPLY sys.dm_sql_referencing_entities
(
  QUOTENAME(OBJECT_SCHEMA_NAME(p.object_id))
  + '.' + QUOTENAME(OBJECT_NAME(p.object_id)), 'OBJECT'
) AS r
WHERE vs.database_id = DB_ID()
AND p.index_id IN (0,1)
ORDER BY size DESC, referenced_by;

Cela suppose qu'aucune des versions ne pourrait être créée par des requêtes ad hoc. Cependant, il ne vous dit pas lequel de ces modules pourrait le causer - espérons que le schéma de dénomination est logique et vous aide à la réduire un peu.

(En 2005, vous pourriez peut-être passer à travers sysdepends et d'autres vues de dépendance de style ancien mais je ne suis pas sûr à 100% à quel point cela serait fiable .)

10
Aaron Bertrand