Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Exploration des options d'attente de verrouillage de faible priorité dans SQL Server 2014 CTP1

SQL Server 2014 CTP1 introduit des options d'attente de verrouillage de faible priorité à utiliser avec les opérations d'index en ligne et les commutateurs de partition.

Pour ceux qui utilisent la gestion d'index en ligne ou le partitionnement d'index et les opérations de changement de partition dans SQL Server 2012 Enterprise Edition, vous avez peut-être à un moment donné rencontré le blocage de votre opération DDL car ces opérations ont encore des exigences de verrouillage.

Pour illustrer, imaginez que j'exécute la reconstruction d'index en ligne à partition unique suivante dans SQL Server 2014 CTP1 :

ALTER INDEX [ClusteredIndex_on_ps_ShipDate]
ON [dbo].[FactInternetSales]
REBUILD PARTITION = (37)
WITH (ONLINE= ON);

Et examinons les verrous acquis et libérés lors de cette opération de reconstruction à l'aide d'événements étendus et de la définition de session suivante (il s'agit d'une session sans cible et j'ai regardé les résultats via le volet « Regarder les données en direct » dans SQL Server Management Studio) :

CREATE EVENT SESSION [Online_Index_Rebuild_Locks_Taken] ON SERVER 
ADD EVENT sqlserver.lock_acquired(
    WHERE ([object_id]=(309576141))),
ADD EVENT sqlserver.lock_released(
    WHERE ([object_id]=(309576141)))
WITH 
(
  MAX_MEMORY=4096 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
  MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 KB,
  MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=OFF, STARTUP_STATE=OFF
);
GO

La valeur 309576141 représente l'ID d'objet de la table FactInternetSales.

Ma reconstruction d'index en ligne d'une seule partition a pris 56 secondes et une fois terminée, j'ai vu l'activité d'acquisition et de libération de verrou suivante :


Activité de verrouillage pour la reconstruction en ligne d'une seule partition

Comme vous pouvez le voir dans la sortie, bien que la reconstruction soit une opération en ligne, elle implique l'acquisition de verrous dans différents modes tout au long du cycle de vie de l'opération. Idéalement, la durée du verrouillage est minimale (par exemple, l'horodatage est identique pour le premier SCH_S serrure acquise et libérée). Mais même avec une quantité minimale de verrouillage, vous pouvez certainement rencontrer des problèmes de concurrence en fonction des transactions exécutées sur l'index en cours de reconstruction ou de basculement.

J'ai mentionné au début de cet article que Microsoft avait introduit des options d'attente de verrouillage de faible priorité pour les opérations en ligne et les opérations de changement de partition dans SQL Server 2014 CTP1. Au sujet des changements de partition, imaginez que j'exécute l'opération suivante :

ALTER TABLE [AdventureWorksDW2012].[dbo].[FactInternetSales] 
SWITCH PARTITION 37 TO  [AdventureWorksDW2012].[dbo].[staging_FactInternetSales];

Pour voir les verrous acquis et libérés pour cette opération, j'ai modifié ma session d'événements étendus précédemment définie pour inclure les objets applicables (table source et cible). J'ai vu ce qui suit :


Activité de verrouillage pour une opération de changement de partition

L'opération de basculement vers une partition vide s'est produite en moins d'une seconde, mais nous voyons toujours que SCH_S et SCH_M des verrous étaient nécessaires pendant le cycle de vie de l'opération sur la source et la destination (309576141 étant FactInternetSales et 398624463 étant staging_FactInternetSales).

Encore une fois, alors que la durée du verrouillage peut être extrêmement brève lorsqu'il n'y a pas de transactions simultanées accédant aux objets en question, nous savons que ce n'est pas toujours possible et que nos opérations de reconstruction d'index en ligne et de changement de partition peuvent en effet être bloquées.

Donc avec cette réalité, SQL Server 2014 introduit le WAIT_AT_LOW_PRIORITY argument qui peut être ajusté avec MAX_DURATION et ABORT_AFTER_WAIT options pour ALTER INDEX et ALTER TABLE commandes que nous pouvons utiliser pour les opérations d'indexation en ligne et de changement de partition.

Qu'est-ce que cela nous permet de faire ? Tout d'abord, parlons du comportement avant SQL Server 2014. Par exemple, imaginons que j'ai la transaction suivante ouverte et non validée :

BEGIN TRANSACTION;
DELETE [dbo].[staging_FactInternetSales];

Si j'ai essayé d'effectuer un ALTER TABLE SWITCH à la table staging_FactInternetSales en tant que destination dans une session séparée, je vais être bloqué et la demande va juste attendre. Spécifiquement pour cet exemple, j'attendrais avec un LCK_M_SCH_M type d'attente. Une fois que j'ai annulé ou validé ma transaction, l'opération peut avancer et se terminer.

Maintenant, si j'utilise le WAIT_AT_LOW_PRIORITY de SQL Server 2014 avec MAX_DURATION et ABORT_AFTER_WAIT , je peux tirer parti de quelques options différentes en fonction des exigences de mon application.

MAX_DURATION me permet de spécifier le nombre de minutes d'attente de la reconstruction de l'index en ligne ou de l'opération de changement de partition. Si MAX_DURATION est atteinte, nous pouvons définir ce qui se passe ensuite en fonction du paramètre de ABORT_AFTER_WAIT , qui peut être une valeur de NONE , SELF ou BLOCKERS :

  • NONE signifie que l'opération d'indexation continuera à tenter l'opération.
  • SELF signifie que si MAX_DURATION est atteint, l'opération (la reconstruction d'index en ligne ou le changement de partition) sera annulée.
  • Si BLOCKERS est utilisé, il tuera toutes les transactions qui bloquent la reconstruction de l'index en ligne ou l'opération de changement de partition (ce n'est pas une option, à mon avis, à utiliser à la légère). BLOCKERS nécessite également ALTER ANY CONNECTION autorisation pour la requête émettant l'opération de reconstruction d'index en ligne ou de changement de partition.

Les exemples de code suivants illustrent différentes variantes de configuration.

    Comportement par défaut avant 2014 (attendre indéfiniment)

      L'exécution de ce qui suit entraînera le comportement auquel nous sommes habitués avant SQL Server 2014, et il se peut que ce soit toujours ce que vous souhaiterez ou attendez dans certains scénarios :

      ALTER TABLE [AdventureWorksDW2012].[dbo].[FactInternetSales] 
      SWITCH PARTITION 37 TO  [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] 
      WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 0 MINUTES, ABORT_AFTER_WAIT = NONE));

    Attendez 1 minute et annulez l'opération DDL

      L'exemple suivant attend 1 minute s'il y a une transaction bloquante et obtiendra un "délai de demande de verrouillage dépassé" pour le SWITCH opération si la durée maximale est atteinte :

      ALTER TABLE [AdventureWorksDW2012].[dbo].[FactInternetSales] 
      SWITCH PARTITION 37 TO  [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] 
      WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 1 MINUTES, ABORT_AFTER_WAIT = SELF));

    Attendez 1 minute et tuez le(s) bloqueur(s)

      Cet exemple attend 1 minute s'il y a une transaction bloquante, puis tue les transactions bloquantes (source ou destination incluses), autorisant le SWITCH opération à terminer.

      ALTER TABLE [AdventureWorksDW2012].[dbo].[staging_FactInternetSales] 
      SWITCH PARTITION 37 TO  [AdventureWorksDW2012].[dbo].[FactInternetSales] 
      WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 1 MINUTES, ABORT_AFTER_WAIT = BLOCKERS));

      Dans mon exemple de DELETE à l'intérieur d'une transaction non validée, il n'y avait pas d'erreur dans ma fenêtre SQL Server Management Studio car je n'avais pas d'instruction en cours d'exécution, mais la tentative d'une autre instruction dans cette session a renvoyé le message d'erreur suivant (car ma session avait été tuée):

      Msg 233, Niveau 20, État 0, Ligne 3
      Une erreur de niveau transport s'est produite lors de l'envoi de la requête au serveur. (fournisseur :fournisseur de mémoire partagée, erreur :0 - aucun processus n'est à l'autre bout du canal.)

    Tuez le(s) bloqueur(s) immédiatement (source ou destination pour SWITCH)

      Ce qui suit est un exemple de suppression immédiate du bloqueur - et dans mon exemple, le changement s'est produit en moins d'une seconde et, en effet, la session qui était le bloqueur a été supprimée :

      ALTER TABLE [AdventureWorksDW2012].[dbo].[FactInternetSales] 
      SWITCH PARTITION 37 TO  [AdventureWorksDW2012].[dbo].[staging_FactInternetSales]
      WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 0 MINUTES, ABORT_AFTER_WAIT = BLOCKERS));

Un dernier aspect positif que je voulais souligner…

Le journal des erreurs SQL Server fournit un audit par défaut de l'utilisation de l'attente de verrouillage de faible priorité, y compris des informations sur le ABORT_AFTER_WAIT opération en ligne avec les informations de la victime :

Date 10/09/2013 13:37:15
Journal SQL Server (Actuel – 10/09/2013 12:03:00)
Source spid51
Message
Processus ID 57 a été tué par une instruction ABORT_AFTER_WAIT =BLOCKERS DDL sur database_id =5, object_id =309576141.

Et vous verrez également des entrées distinctes pour l'opération d'origine elle-même. Par exemple :

Une instruction ALTER TABLE SWITCH a été exécutée sur la base de données 'AdventureWorksDW2012', table 'staging_FactInternetSales' par le nom d'hôte 'WIN-4T7S36VMSD9', ID de processus hôte 1360 avec la table cible 'AdventureWorksDW2012.dbo.FactInternetSales' en utilisant les options WAIT_AT_LOW_PRIORITY avec MAX_DURATION =1 et ABORT_AFTER_WAIT =BLOQUEURS. Les sessions utilisateur bloquantes seront supprimées après la durée maximale du temps d'attente.

Ce type de journalisation est très utile à des fins de dépannage et d'audit et je suis ravi de le voir.