web-dev-qa-db-fra.com

Utilisation de SPID dans les tables de base de données (au lieu de la variable de table)

Base de données transactionnelle utilisée pour réserver des choses ...

Notre fournisseur a été invité à remplacer #temptables par @tablevariables (en raison de verrous de compilation importants), mais à la place, il a été remplacé par une table réelle qui ajoute SPID en tant que colonne pour garantir que la procédure stockée n'agit que sur les lignes applicables.

Voyez-vous un risque dans cette méthode de fonctionnement? Avant que toutes les transactions ne soient isolées au sein de leur propre transaction ... Je craignais que nous finissions par verrouiller cette table un tas, mais leur opinion est que SQL utilise le verrouillage au niveau des lignes et cela ne créera pas plus de verrous.

Version de SQL Server: 2016 Enterprise - 13.0.5216.0


CREATE TABLE dbo.qryTransactions (
    ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
    spid int NOT NULL,
    OrderID int,
    ItemID int,
    TimeTransactionStart datetime,
    TimeTransactionEnd datetime,
...other fields
    )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)

8
outjet

Un peu plus décousu que ce qui peut tenir dans un bloc de commentaires ... et je veux mettre en évidence un commentaire que l'OP a fait en réponse à la réponse de Ray:

  • proc parent (Common_InsertOrders_1) crée une table temporaire
  • un proc enfant (InsertOrders) interroge la table temporaire
  • des verrous de compilation sont vus pour le processus enfant (InsertOrders)

Partir sur une légère tangente pendant une minute ... sur ce qui se passerait avec ce scénario est Sybase ASE ...

  • chaque table temporaire obtient un identifiant d'objet unique (bien sûr, l'identifiant d'objet pourrait être réutilisé à un moment donné, mais cela est rare et ne se produira certainement pas pour les sessions simultanées)
  • Sybase ASE forcera normalement une recompilation à chaque exécution du proc enfant à cause de change dans l'ID d'objet pour la table temporaire
  • Sybase ASE forcera également une recompilation du proc enfant s'il voit que la structure de la table temporaire a changé (par exemple, un nombre différent de colonnes, différents noms de colonne/types de données/nullabilité) entre les appels de proc stockés
  • les versions plus récentes de Sybase ASE ont une configuration qui (effectivement) indique au compilateur d'ignorer les modifications des identifiants des objets de la table temporaire, éliminant ainsi la recompilation du proc enfant (REMARQUE: les recompilations se produiront toujours si la structure de la table change)

Retour au problème de l'OP (les verrous de compilation sur le proc enfant) ...

  • y a-t-il une chance que certains vestiges du comportement Sybase ASE puissent encore résider dans SQL Server (à partir du moment où les deux produits étaient des pois dans un pod)?
  • existe-t-il des configurations SQL Server qui pourraient réduire (éliminer?) les recompilations du processus enfant (si elles sont dues à des changements d'ID d'objet)?
  • l'OP peut-il vérifier que le proc parent crée la table temporaire avec la même structure/DDL exacte à chaque fois?

Quant à l'idée d'utiliser une seule table permanente avec @@ SPID pour différencier les lignes entre les sessions ... déjà là, vu que ... beurk; problèmes récurrents:

  • comment/quand nettoyer les lignes orphelines
  • la réutilisation du @@ SPID par le moteur de base de données pourrait entraîner des problèmes de précision des données si des données orphelines existent (ou pendant le nettoyage des données orphelines, par exemple, supprimer où @@ SPID = 10 mais il y a une session nouvelle/actuelle/active avec @ @ SPID = 10 => le nettoyage supprime trop de données)
  • possibilité d'escalade des verrous des verrous de ligne aux verrous de page/table
  • si la table a des index, alors potentiel (b) de verrouillage lors de la mise à jour des index
  • en fonction de la base de données dans laquelle se trouve la table, vous pourriez envisager beaucoup plus d'activité pour écrire sur le périphérique de journal (dans Sybase ASE, il est possible de désactiver efficacement la journalisation dans tempdb)
  • même les verrous (exclusifs) au niveau de la ligne peuvent bloquer d'autres sessions (selon le niveau d'isolement et si une session peut ou non passer/ignorer lesdits verrous exclusifs)

Je voudrais revenir en arrière et (re) enquêter sur le problème racine (verrous de recompilation sur le proc enfant) et voir s'il existe un moyen de réduire (éliminer?) Lesdits verrous de compilation. [Malheureusement, ma connaissance de SQL Server sur ces problèmes est ... NULL ... donc je serais intéressé par les commentaires de certains experts du compilateur SQL Server.]

5
markp-fuso

Il me semble utiliser le @@SPID comme ça demande des ennuis.

Les ID de session sont réutilisés fréquemment; dès qu'une connexion utilisateur se déconnecte, cet ID de session est disponible pour être réutilisé et est susceptible d'être utilisé par la prochaine session tentant de se connecter.

Pour le faire fonctionner au moins de manière semi-fiable, vous auriez besoin d'un déclencheur de connexion qui purge les lignes précédentes de la table avec le même @@SPID. Si vous faites cela, vous verrez probablement beaucoup de verrouillage sur la table en utilisant le @@SPID colonne.

SQL Server utilise en effet le verrouillage de ligne, mais il utilise également le verrouillage de page et le verrouillage de table. Bien sûr, vous pourrez peut-être atténuer cela via une bonne indexation, mais cela me semble toujours être un anti-modèle.

Si la procédure stockée est la méthode uniquement utilisée pour accéder aux tables affectées, vous pouvez rechercher l'utilisation d'un verrou d'application, via sp_getapplock pour sérialiser essentiellement l'accès aux parties concernées. Les documents pour sp_getapplock sont ici . Erik Darling a un article intéressant à ce sujet ici .

8
Max Vernon

Oui, je vois des risques. Il est naïf de compter sur SQL en utilisant le verrouillage de ligne. Par exemple, je suis presque sûr que les insertions et les suppressions utiliseront au moins les verrous de page. Le moteur SQL choisit le type de verrou en fonction de plusieurs facteurs et aucun de ces facteurs n'inclut "leur opinion". Les solutions générales comme le changement de tables temporaires en variables de table sont généralement aussi de mauvaises idées. Les variables de tableau sont très utiles dans certaines situations, mais elles présentent des limitations et des problèmes de performances. Je préfère les tables temporaires dans la plupart des circonstances. Particulièrement lorsque le tableau contiendra plus de quelques dizaines de lignes. Je demanderais au vendeur d'expliquer pourquoi le système a connu des "verrous de compilation lourds" et comment cela a dégradé les performances. Rappelez-vous, chaque fois que vous regardez, vous trouverez des "serrures lourdes" en quelque sorte. Cela ne signifie pas nécessairement que les serrures sont un problème. Les commentaires de Max sur @@ SPID sont également importants. De plus, le modèle de transaction et le traitement des erreurs pourraient être de gros problèmes. Si votre système rencontre des blocages ou des problèmes de qualité des données d'entrée, le traitement d'erreur standard peut entraîner la fin de la session sans que la table qryTransactions soit correctement réinitialisée. IMO la mauvaise approche de solution au problème d'origine.

4
Ray