Automated Restores

  • On a regular basis, we restore production database to testing servers. To do this we must have no connections to the target database. There are GUI applications and Management Studio connections that can exist when the restores are scheduled. A Stored Procedure was created to KILL all SPIDs that are connected to the database. Since we have moved to SQL Server 2008 SP1 CU9 this process sometimes does not work. It was originally created on SQL Server 2000 SP3a. Are there any known issues with the Kill command? Is there a better way to do this?

    The code is below to create a Dynamic SQL Statement to KILL the SPIDS.

    SELECT @spidstr=coalesce(@spidstr,',' )+'kill '+convert(varchar, spid)+ '; '

    FROM master..sysprocesses WHERE dbid=db_id(@DBName)

    and status <>'background'

    It results in this statement that is then executed.

    kill 58; kill 59; kill 60; kill 69;

    We have tried moving the execution of the stored procedure closer to the RESTORE command and have run sp_who2 to see if there are any connections. There are ususally none. Sometimes the application re-connects.

    Thanks for any help,

    Steve

  • Are you doing the kill and the restore in a single script with a single connection? If so, you could set the database to single-user mode as part of that. That'll prevent new connections and reconnections.

    - Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
    Property of The Thread

    "Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon

  • Well we tried the single user mode. We are using Lite Speed and it tries to open another connects and fails. So we abandon that method.

    Steve

  • You might try restricted_user mode, which only lets Db_owner/sysadmin in. That might work for you.

  • It is an old app and the main user id that connects is sysadmin (I know bad design).

  • Sorry its not sa. It is another user id that has SYSADMIN rights.

  • In this case, you have no choice unless you stop the app explicitly. (Otherwise, the app will keep trying to connect the database.)

  • Well we tried the single user mode. We are using Lite Speed and it tries to open another connects and fails. So we abandon that method.

    Steve

    I use Litespeed and restore a copy of live to our report server every night. What I found that works very well is:

    ALTER DATABASE {database} SET OFFLINE WITH ROLLBACK IMMEDIATE;

    Execute master.dbo.xp_restore_database

    @database = '{database}'

    ,@filename = '{file name}'

    ,@with = 'MOVE "logical name" TO "new location"'

    ,@with = 'MOVE "logical name" TO "new location"'

    ,@with = 'REPLACE'

    ,@with = 'STATS = 10'

    ,@with = 'NORECOVERY';

    RESTORE DATABASE {database} WITH RECOVERY;

    Jeffrey Williams
    “We are all faced with a series of great opportunities brilliantly disguised as impossible situations.”

    ― Charles R. Swindoll

    How to post questions to get better answers faster
    Managing Transaction Logs

  • I used this in a job step prior to the lightspeed restore and it works fine restoring from prod to dev.

    DECLARE @DatabaseName nvarchar(50)

    DECLARE @SPId int

    DECLARE @userid varchar(100)

    declare @command varchar(200)

    SET @DatabaseName = N'DBName'

    SET @userid = N'UserName'

    --SET @DatabaseName = DB_NAME()

    DECLARE my_cursor CURSOR FAST_FORWARD FOR

    SELECT SPId FROM MASTER..SysProcesses

    WHERE DBId = DB_ID(@DatabaseName) AND SPId <> @@SPId

    and loginame = @userid

    OPEN my_cursor

    FETCH NEXT FROM my_cursor INTO @SPId

    WHILE @@FETCH_STATUS = 0

    BEGIN

    SET @Command = 'KILL '+CAST(@SPId AS VARCHAR)+'; '

    exec (@Command)

    FETCH NEXT FROM my_cursor INTO @SPId

    END

    CLOSE my_cursor

    DEALLOCATE my_cursor

    SELECT * FROM MASTER..SysProcesses

  • willtwc (1/3/2011)


    I used this in a job step prior to the lightspeed restore and it works fine restoring from prod to dev.

    DECLARE @DatabaseName nvarchar(50)

    DECLARE @SPId int

    DECLARE @userid varchar(100)

    declare @command varchar(200)

    SET @DatabaseName = N'DBName'

    SET @userid = N'UserName'

    --SET @DatabaseName = DB_NAME()

    DECLARE my_cursor CURSOR FAST_FORWARD FOR

    SELECT SPId FROM MASTER..SysProcesses

    WHERE DBId = DB_ID(@DatabaseName) AND SPId <> @@SPId

    and loginame = @userid

    OPEN my_cursor

    FETCH NEXT FROM my_cursor INTO @SPId

    WHILE @@FETCH_STATUS = 0

    BEGIN

    SET @Command = 'KILL '+CAST(@SPId AS VARCHAR)+'; '

    exec (@Command)

    FETCH NEXT FROM my_cursor INTO @SPId

    END

    CLOSE my_cursor

    DEALLOCATE my_cursor

    SELECT * FROM MASTER..SysProcesses

    Note, this method has the potential of allowing another process to connect while you are killing the SPID's. I prefer using a method that will not allow that to happen - which setting the database offline does.

    Jeffrey Williams
    “We are all faced with a series of great opportunities brilliantly disguised as impossible situations.”

    ― Charles R. Swindoll

    How to post questions to get better answers faster
    Managing Transaction Logs

Viewing 10 posts - 1 through 9 (of 9 total)

You must be logged in to reply to this topic. Login to reply