ALTER DATABASE a échoué car un verrou n'a pas pu être placé sur la base de données

124

J'ai besoin de redémarrer une base de données car certains processus ne fonctionnent pas. Mon plan est de le mettre hors ligne et de le remettre en ligne.

J'essaye de faire ceci dans Sql Server Management Studio 2008:

use master;
go
alter database qcvalues
set single_user
with rollback immediate;
alter database qcvalues
set multi_user;
go

J'obtiens ces erreurs:

Msg 5061, Level 16, State 1, Line 1
ALTER DATABASE failed because a lock could not be placed on database 'qcvalues'. Try again later.
Msg 5069, Level 16, State 1, Line 1
ALTER DATABASE statement failed.
Msg 5061, Level 16, State 1, Line 4
ALTER DATABASE failed because a lock could not be placed on database 'qcvalues'. Try again later.
Msg 5069, Level 16, State 1, Line 4
ALTER DATABASE statement failed.

Qu'est-ce que je fais mal?

JOE SKEET
la source
Quel est le problème qui a provoqué ce besoin en premier lieu? Avez-vous des transactions de restauration en ce moment? Avez-vous déjà exécuté cette commande dans une autre fenêtre SSMS qui pourrait encore être ouverte? Je me demande (pure spéculation) si cela pourrait prendre un verrou qui bloque d'autres tentatives, mais il attend toujours avant que la base de données puisse réellement être mise en mode single_user.
Martin Smith
1
@Martin - assez juste. Je dois penser à autre chose ou perdre la tête. l'un ou l'autre est tout à fait possible
codingbadger
@merci beaucoup à tous, j'ai redémarré SSMS et j'ai pu tuer tout le monde
JOE SKEET
Cela pourrait être intellisense. J'ai supprimé une requête incomplète qui avait des lignes ondulées essayant d'accéder à la base de données, puis cela a fonctionné.
Faahmed

Réponses:

293

Après avoir obtenu l'erreur, exécutez

EXEC sp_who2

Recherchez la base de données dans la liste. Il est possible qu'une connexion n'ait pas été interrompue. Si vous trouvez des connexions à la base de données, exécutez

KILL <SPID>

<SPID>est le SPID des sessions connectées à la base de données.

Essayez votre script une fois toutes les connexions à la base de données supprimées.

Malheureusement, je n'ai aucune raison pour laquelle vous voyez le problème, mais voici un lien qui montre que le problème s'est produit ailleurs.

http://www.geakeit.co.uk/2010/12/11/sql-take-offline-fails-alter-database-failed-because-a-lock-could-not-error-5061/

bobs
la source
Pouvez-vous expliquer pourquoi une connexion ne serait pas interrompue par la commande? La seule raison pour laquelle je peux penser serait qu'il est toujours en train de revenir en arrière ou qu'il s'agit d'une set single_usertentative qui est toujours en cours.
Martin Smith
@Martin, j'ai bien peur de ne pas avoir de raison à cela. Mais j'ajouterai un lien qui indique que d'autres ont vu le problème. Je suis d'accord qu'une annulation de transaction pourrait être le problème, mais KILLcela ne le résoudrait pas non plus.
bobs
Soyez gentil de comprendre pourquoi cela se produit, mais les commentaires sur votre lien semblent indiquer que cela fonctionnerait! (+1)
Martin Smith
KILL (87) résultats dans Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '('.erm ....
Tim Abell
2
@MartinSmith Je pense savoir pourquoi: j'ai juste eu le même problème, une connexion persistante apparaissant sous sp_who2 provoquant un blocage de la mise hors ligne. Il s'est avéré être une fenêtre d'édition de lignes ouverte dans ssms. Je pense que ce qui se passe ici est que la fenêtre d'édition des lignes est une requête maintenue ouverte avec un jeu de résultats modifiable. SQL Server propose une telle fonctionnalité comme alternative aux instructions de mise à jour. En fermant cette fenêtre ssms particulière, la mise hors ligne de la suspension s'est terminée immédiatement.
John
5

J'ai réussi à reproduire cette erreur en procédant comme suit.

Connexion 1 (laissez fonctionner pendant quelques minutes)

CREATE DATABASE TESTING123
GO

USE TESTING123;

SELECT NEWID() AS X INTO FOO
FROM sys.objects s1,sys.objects s2,sys.objects s3,sys.objects s4 ,sys.objects s5 ,sys.objects s6

Connexions 2 et 3

set lock_timeout 5;

ALTER DATABASE TESTING123 SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
Martin Smith
la source
2

Essayez ceci s'il est "en transition" ...

http://learnmysql.blogspot.com/2012/05/database-is-in-transition-try-statement.html

USE master
GO

ALTER DATABASE <db_name>

SET OFFLINE WITH ROLLBACK IMMEDIATE
...
...
ALTER DATABASE <db_name> SET ONLINE
Watki02
la source
Ne fonctionnera pas lorsque la base de données est en transition, vous obtiendrez la même erreur avec la SET OFFLINEdéclaration que celle mentionnée par l'OP (peut-être qu'il y a des scénarios où cela fonctionne, mais ce n'est pas le cas pour moi)
Abel
1

J'ajouterai ceci ici au cas où quelqu'un serait aussi chanceux que moi.

Lorsque vous examinez la liste des processus sp_who2 , notez les processus qui s'exécutent non seulement pour la base de données concernée mais également pour le maître . Dans mon cas, le problème qui bloquait la base de données était lié à une procédure stockée qui a démarré un xp_cmdshell.

Vérifiez si vous avez des processus à l'état KILL / RollBack pour la base de données master

SELECT *
FROM sys.sysprocesses
WHERE cmd = 'KILLED/ROLLBACK'

Si vous rencontrez le même problème, seule la commande KILL ne vous aidera probablement pas. Vous pouvez redémarrer le serveur SQL, ou mieux est de trouver le cmd.exe sous les processus Windows sur le système d'exploitation du serveur SQL et de le tuer.

Alina
la source
0

Dans SQL Management Studio, accédez à Sécurité -> Connexions et double-cliquez sur votre connexion. Choisissez Rôles du serveur dans la colonne de gauche et vérifiez que sysadmin est coché.

Dans mon cas, j'étais connecté sur un compte sans ce privilège.

HTH!

Marty
la source
1
L'erreur dans la question d'origine se produit également lorsque vous êtes SA, cela n'a rien à voir avec vos droits. Si vous ne disposez pas de suffisamment de droits, vous ne pourrez pas exécuter la commande hors ligne.
Abel
0

Tuer l'ID de processus a bien fonctionné pour moi. Lors de l'exécution de la commande "EXEC sp_who2" sur une nouvelle fenêtre de requête ... et filtrer les résultats pour la base de données "occupée", Tuer les processus avec la commande "KILL" a réussi à faire l'affaire. Après cela, tout a fonctionné à nouveau.

user3749524
la source
0

Juste pour ajouter mes deux cents. Je me suis mis dans la même situation, tout en recherchant les privilèges minimum requis d'une connexion à la base de données pour exécuter avec succès l'instruction:

ALTER DATABASE ... SET SINGLE_USER WITH ROLLBACK IMMEDIATE

Il semble que l'instruction ALTER se termine avec succès , lorsqu'elle est exécutée avec une connexion sysadmin , mais elle nécessite la partie nettoyage des connexions, lorsqu'elle est exécutée sous une connexion qui n'a "que" des autorisations limitées comme:

ALTER ANY DATABASE

PS J'ai passé des heures à essayer de comprendre pourquoi "ALTER DATABASE .." ne fonctionne pas lorsqu'il est exécuté sous un login qui a le rôle dbcreator + les privilèges ALTER ANY DATABASE . Voici mon fil MSDN !

Veselin Z.
la source
0

Je sais que c'est un ancien message, mais j'ai récemment rencontré un problème très similaire. Malheureusement, je n'ai pas pu utiliser les commandes alter database car un verrou exclusif n'a pas pu être placé. Mais je n'ai jamais pu trouver une connexion ouverte à la base de données. J'ai finalement dû supprimer de force l'état de santé de la base de données pour la forcer dans un état de restauration au lieu de restauration.

Geoff Dawdy
la source
0

Dans de rares cas (par exemple, après qu'une transaction lourde est validée), un processus système CHECKPOINT en cours d'exécution tenant un verrou FILE sur le fichier de base de données empêche la transition vers le mode MULTI_USER.

Mitix
la source
0

Dans mon scénario, aucun processus ne bloquait la base de données sous sp_who2. Cependant, nous avons découvert parce que la base de données est beaucoup plus volumineuse que nos autres bases de données que les processus en attente étaient toujours en cours d'exécution.C'est pourquoi la base de données sous le groupe de disponibilité s'affiche toujours en rouge / hors ligne après avoir essayé de `` reprendre les données '' en cliquant avec le bouton droit sur la base de données en pause.

Pour vérifier si des processus sont toujours en cours d'exécution, exécutez simplement cette commande: sélectionnez percent complete dans sys.dm_exec_requests où percent_complete> 0

user123456789
la source