Beaucoup de «FETCH API_CURSOR0000…» sur sp_WhoIsActive (SQL Server 2008 R2)


9

J'ai une situation étrange. En utilisant sp_whoisactiveje peux voir ceci:

Étrange

Ok, avec cette requête, je peux voir ce qui se déclenche (ce mot existe-t-il en anglais?) Il:

SELECT c.session_id, c.properties, c.creation_time, c.is_open, t.text
FROM sys.dm_exec_cursors (SPID) c --0 for all cursors running
CROSS APPLY sys.dm_exec_sql_text (c.sql_handle) t

le résultat:

c'est juste un choix

c'est simple select. Pourquoi cela utilise-t-il f etch_cursor?

De plus, je vois aussi beaucoup de sql_texts "vides". Est-ce que cela a quelque chose avec ce "curseur"?

Vide

DBCC INPUTBUFFER (spid) me montre ceci:

impression

il y a cette question ici (faite par moi) mais je ne sais pas si c'est la même chose.


EDIT1:

En utilisant la requête fournie par kin, je vois ceci:

toujours pas de code.


EDIT2:

En utilisant Activity Monitor, je peux voir ceci:

Requête coûteuse

C'est la requête la plus chère (la première est intentionnelle, nous la connaissons).

Et encore une fois, je voudrais savoir pourquoi select * from...c'est la raison de FETCH CURSOR...


EDIT3:

Ce " select * from..." est exécuté depuis un autre serveur (via linked server).

Eh bien, j'ai maintenant des problèmes pour comprendre ce que @kin a dit.

Il s'agit execution plande la requête (exécutée sur le même serveur de la base de données):

même serveur de la base de données

c'est maintenant, le plan d'exécution, exécuté sur l'autre serveur, via un serveur lié:

entrez la description de l'image ici

Ok, pas trop de problème. Et maintenant! le plan d'exécution, via **activity monitor**(le même select * from):

Qu'est ce qui se passe ici?

Réponses:


3

C'est un simple choix. Pourquoi cela utilise-t-il fetch_cursor?

Le SELECTest généré par le système par le cadre de requête distribuée et est associé au que UPDATEvous avez trouvé.

L'opérateur du plan de requête de mise à jour à distance utilise le sp_cursormodèle pour extraire des lignes de la source de données distante. C'est la cause de tous les appels d'API de curseur.

Je crois que le plan du curseur que vous montrez dans votre question est le curseur interne ouvert par le moteur dans le cadre de ce processus, mais je n'ai pas encore eu le temps d'essayer de le reproduire.


1

Cela peut être un problème avec les appels OLEDB vers des serveurs distants (les serveurs liés et les configurations SSIS utilisent OLEDB).

Il s'agit d'un défaut de conception, bogue Microsoft SQL Server qui n'a pas été corrigé avant SQL Server 2012 SP1 d'après ce que je me souviens, où il ne permet pas d'utiliser des statistiques distantes pour optimiser la requête à distance.

Vous devrez également exécuter sp_WhoIsActive ( download | docs ) à partir du serveur REMOTE dans la requête pour voir le trafic, mais SQL Server qui n'est pas 2012 SP1 n'autorise pas l'utilisation de statistiques distantes pour une raison quelconque, même si la connexion a un datareader accès à toutes les tables du serveur distant.

La solution Microsoft consiste à accorder aux informations d'identification du serveur lié effectuant l'appel distant un accès SA, ddladmin ou DBO au serveur / aux tables distantes interrogées.

J'ai utilisé cela pour contourner ce problème dans certaines de nos configurations, ce qui est transparent pour la plupart des solutions sans autoriser des autorisations élevées aux bases de données ou aux serveurs SQL du côté distant. Vous devez essentiellement accorder le rôle ddladmin de connexion à distance sur la base de données SQL Server distante en question, puis créer un rôle avec des autorisations DENY explicites pour les modifications de niveau objet si vous avez uniquement l'intention d'autoriser l'accès SELECT.

Vous trouverez ci-dessous la copie du rôle fixe de base de données personnalisé que je crée pour cela, mais vous souhaiterez peut-être tester et confirmer ou ajuster davantage, ainsi que des lectures et des recherches, mais résolu de manière transparente pour moi dans certains cas - le cache peut avoir besoin d'être effacé avant de fonctionner, donc gardez cela à l'esprit et une fois qu'il est effacé, exécutez-le deux fois et vérifiez à la fois l'activité locale et l'activité à distance pour les résultats.

Donc, autorisez les informations d'identification du rôle ddladmin sur la base de données distante, vous autorisez les autres autorisations habituelles sur la base de données distante, vous créez le rôle de base de données personnalisé comme indiqué ci-dessous sur ce même serveur, puis vous ajoutez ces mêmes informations d'identification à cette nouvelle correction personnalisée Rôle DB avec les refus explicites, effacez le cache, exécutez la requête deux fois ou plus après avoir effacé le cache pour voir s'il se résout.

Pour répondre spécifiquement à votre question, cependant, pour la raison pour laquelle vous voyez ces récupérations de curseur, si vous exécutez une version inférieure à SQL Server 2012 SP1 et que vous voyez cela et que vous exécutez une requête distante, car elle ne permet pas l'utilisation ou la télécommande statistiques dans cette configuration sans solution de contournement (comme indiqué ci-dessus), puis il effectue le traitement ligne par ligne comme Kin indiqué ci-dessus car la requête n'est pas optimisée en utilisant les statistiques pour le meilleur plan de requête et a le problème de cardinalité.

/* 
CREATE A NEW ROLE - Deny explicit DB object access for linked 
server credentials that the DDLAdmin role gives which is needed 
for DBCC SHOW_STATISTICS across linked servers  
*/
-- Database specific
CREATE ROLE db_LinkedServer_Restriction
DENY ALTER ANY ASSEMBLY                    TO db_LinkedServer_Restriction
DENY ALTER ANY ASYMMETRIC KEY              TO db_LinkedServer_Restriction
DENY ALTER ANY CERTIFICATE                 TO db_LinkedServer_Restriction
DENY ALTER ANY CONTRACT                    TO db_LinkedServer_Restriction
DENY ALTER ANY DATABASE DDL TRIGGER        TO db_LinkedServer_Restriction
DENY ALTER ANY DATABASE EVENT NOTIFICATION TO db_LinkedServer_Restriction
DENY ALTER ANY DATASPACE                   TO db_LinkedServer_Restriction
DENY ALTER ANY FULLTEXT CATALOG            TO db_LinkedServer_Restriction
DENY ALTER ANY MESSAGE TYPE                TO db_LinkedServer_Restriction
DENY ALTER ANY REMOTE SERVICE BINDING      TO db_LinkedServer_Restriction
DENY ALTER ANY ROUTE                       TO db_LinkedServer_Restriction
DENY ALTER ANY SCHEMA                      TO db_LinkedServer_Restriction
DENY ALTER ANY SERVICE                     TO db_LinkedServer_Restriction
DENY ALTER ANY SYMMETRIC KEY               TO db_LinkedServer_Restriction
DENY CHECKPOINT                            TO db_LinkedServer_Restriction
DENY CREATE AGGREGATE                      TO db_LinkedServer_Restriction
DENY CREATE DEFAULT                        TO db_LinkedServer_Restriction
DENY CREATE FUNCTION                       TO db_LinkedServer_Restriction
DENY CREATE PROCEDURE                      TO db_LinkedServer_Restriction
DENY CREATE QUEUE                          TO db_LinkedServer_Restriction
DENY CREATE RULE                           TO db_LinkedServer_Restriction
DENY CREATE SYNONYM                        TO db_LinkedServer_Restriction
DENY CREATE TABLE                          TO db_LinkedServer_Restriction
DENY CREATE TYPE                           TO db_LinkedServer_Restriction
DENY CREATE VIEW                           TO db_LinkedServer_Restriction
DENY CREATE XML SCHEMA COLLECTION          TO db_LinkedServer_Restriction
DENY REFERENCES                            TO db_LinkedServer_Restriction

GO

1

Eh bien ... Nous avons résolu le problème. Il y avait une mise à jour, dans la procédure en cours, qui "sélectionne * à partir de ...". J'ai commenté la mise à jour. plus de problèmes.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.