Lesson Learned #118: Having ALTER DATABASE failed because a lock could..after creating a MI database

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Tech Community.

Today, we worked on a new service request where our customer tried to modify a parameter of a new database, just a couple minutes after that they have created it. 

 

During aprox. 5-10 minutes they were not able to modify this parameter after the database was created and our customer asked why.

Every time that they tried to change the value of this parameter they got the following error message:

 

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

 

Why? 

  • Please, remember that the creation of the database is an asynchronous process and even when SQL SERVER Management Studio returned the message that the database has been created, other process may take place in the background for example, enabling TDE, running a backup, etc.. for this new database. If any of this parameter needs to have an exclusive lock during this period of time you could see this error message. 
  • Also, we need to know that just only a few parameters are enabled at the moment of the execution of CREATE DATABASE as TSQL or using SQL Server Management Studio - https://docs.microsoft.com/en-us/sql/t-sql/statements/create-database-transact-sql?view=azuresqldb-mi-current 

 

How we found it:

 

 

If you want to automate this process using a script, for example, to change the containment parameter:

 

  • We suggested to use the following script as an example:
    • First, create a store procedure to change the parameter of the database. You could parametrized as you wish. 

CREATE OR ALTER PROCEDURE ChangeStatus
AS
BEGIN
BEGIN TRY
        ALTER DATABASE <databasename> set containment =partial
END TRY
BEGIN CATCH
     PRINT @@ERROR
END CATCH
END

 

  • Second, create a script to retry the operation until this operation has been finished.  

DECLARE @VALUE AS INT = -1
DECLARE @nTimes as INT = 0

WHILE(@nTimes <=10)
BEGIN
SELECT @Value = (SELECT Containment FROM sys.databases WHERE name='databasename')
  IF @VALUE <> 0 BREAK;
  SET @nTimes = @ntimes +1
  IF @Value = 0
BEGIN
   PRINT 'Doing #'
   EXEC ChangeStatus
    WAITFOR DELAY '00:02:00'
END
END

 

Enjoy!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.