Tag: administration

  • Test Your Situation

    I gave a talk on Transparent Data Encryption (TDE) recently and a number of people in the audience were using the feature. However when I asked how many of them had restored a TDE database, not all hands remained up. When I asked how many people had restored their TDE encrypted backup  to a different server, one that didn’t have TDE enabled, very few hands remained in the air.

    That’s not good, and I certainly hope those people don’t experience a disaster from which they cannot recover. I’m sure they are not alone. I suspect that many of the people managing a TDE database have restored a database this year, and are confident they can do so. However what they don’t know is if they can restore those TDE databases on any other instance, including a newly installed one.

    They’re not alone. I see many, many people implement features they don’t really understand. Microsoft has made it easy to set up replication, clustering, and more in your environment, but without providing some of the robustness and reliability that many people need. The ease of setting up a feature is one thing. The ease of ongoing management and recovery when issues occur is something else entirely.

    I really wish that Microsoft would go further than making implementation easier and include direction for ongoing tasks. When databases are created, ask the user to set up backups and help them create the jobs. When encryption is implemented, do more than display a warning message. Help adminstrators prepare for recovery with templates or jobs that automatically build certificate or key backups. When replication is set up, include a script to rebuild the environment for when it breaks.

    I doubt we’ll get this, and many companies and employees will continue to implement features they don’t understand. You can only help your own situation, and you should be ensuring you understand and can rebuild all the extra features you’ve installed in the event of a disaster.

    Steve Jones

    The Voice of the DBA Podcast

    Listen to the MP3 Audio ( 2.3MB) podcast or subscribe to the feed at iTunes and LibSyn.

  • Recovering from Bad Deployments

    Someone asked me recently if I stored backups of my database in version control. This person wanted to recover from a bad deployment and use a backup to do so. They felt that keeping a copy of the backup in a VCS, alongside the code being deployed, would be important. It might be, but I said that recovering from a bad deployment isn’t something I want to do with a restore if I can avoid it. Then I was asked how to recover from a bad deployment if you have a busy, 24×7 environment.

    I, of course, answered, “it depends.”

    It does depend on the deployment, but it also depends on your preparation. There are ways in which you can work to minimize the problems that might occur during a deployment. Obviously testing your scripts and deployment process is important, but it’s also good for you to understand how your scripts work and what techniques you can use to rollback problematic deployments.

    There’s a switch in SQL Compare that lets you build a deployment script, and then immediately generate a rollback script. It’s handy, but it’s also not going to always work. If you’ve added a column during deployment, you might not want to just remove it on rollback. 

    However you can prepare for issues, like having a script that might save data in the new column before you remove it. You might choose to copy the table as part of a pre-deployment process (or during deployment), having this copy of the table used in a rollback scenario. You might even bring up a warm copy of your database and prepare to swap entire databases if problems arise. This would allow you time to save and move data that was changed after your deployment, but before your rollback.

    There are lots of possibilities in how you might recover from a failed deployment, but as with many of the solutions that we build in technology, a well thought out plan makes everything run smoother.

    Steve Jones

    The Voice of the DBA Podcast

    Listen to the MP3 Audio ( 2.1MB) podcast or subscribe to the feed at iTunes and LibSyn.

  • Beware of Login Issues for Privileged Accounts

    In a recent post, I described an attack against a privileged account using a simple SQL Injection technique of updating data in a table. One of the things showed was an administrator using their user and password credentials, but being unable to log on.

    pwd6

    In this case, the administrator might easily assume there are mistyping their password, try again, and at some point reset their password.

    NEVER DO THAT.

    I mean, you might need to reset your password, but don’t take this lightly. If you are logging in with a privileged account, and you should do this sparingly,

  • Powershell – Copy the Latest Backup

    I got an email recently where someone asked me how they can refresh a dev environment with Powershell. I guess I’d written something about this in 2009, though that would have been for testing as Red Gate had already banned me from development on SQLServerCentral by that time.

    I dug around and came up with a few partial scripts and cleaned them up for these posts. This post will look at getting the backup and a later one will examine the restore.

    Finding the Latest Backup

    I’ll assume that you make backups on a known path somewhere. My philosophy is that I want the machines to stand alone as much as possible. That means that I don’t want the source machine (the one making the backup) to be working on refreshing the backup elsewhere. I want a pull system.

    For a high level overview, this process looks like this:

    • Search the backup path for files matching a pattern.
    • Find the most recent one, based on date.
    • Copy that most recent file to another location.

    For the sake of consistency and easy, I want to copy the file with the same destination name every time. That will simplify my restore process, which I could easily then do in T-SQL.

    Let’s examine how to do this. I’ve got a folder with a few backups in it.

    backuplatest

    For my PoSh, I’ll start by setting a variable to the path.

    $backuppath = "D:\SQLServer\MSSQL11.MSSQLSERVER\MSSQL\Backup" 

    Once I have this, I can now look for the files in this path. To do that, I’ll use Get-Children.

    get-childitem -path $backuppath

    This will return to me a list of the files. That’s what I want, but I want to limit the files to a pattern. In this case, I’m looking for .bak files, from the EncryptionPrimer database. All of these

    There’s nothing special about what I do that’s not contained in plenty of places. I don’t have this running on an environment currently as someone else manages that process, but here’s the process I’ve followed in the past:

    • Find the latest backup (whatever the date) in the source folder.
    • Copy this with a set name to the destination folder, overwriting previous backups with the same name.
    • Restore the known name to the development database, moving files as needed.

    I’ll go through each of these steps in my PoSh script.

    Find the Latest Backup

    This is fairly easy. I’ll use the Get-ChildItem method, which I found in a StackOverflow post. I’ll use a variable for the path I need, and then check the path.

    $backuppath = "D:\SQLServer\MSSQL11.MSSQLSERVER\MSSQL\Backup"

    get-childitem -path $backuppath

    That works well, but since I’m building a process for a specific backup type, I’ll add a filter.

    $backuppath = "D:\SQLServer\MSSQL11.MSSQLSERVER\MSSQL\Backup"

    get-childitem -path $backuppath -Filter "EncryptionPrimer*.bak"

     

    To find the latest backup, we’ll pipe the output through the Where-object filter, removing folders. Then we use sort-object to order things by creation date and select-object to get just the one file.

    $backuppath = "D:\SQLServer\MSSQL11.MSSQLSERVER\MSSQL\Backup"

    get-childitem -path $backuppath -Filter "EncryptionPrimer*.bak" |

        where-object { -not $_.PSIsContainer } |

        sort-object -Property $_.CreationTime |

        select-object -last 1

     

    The last part of the script is the copy-item command, which is again the recipient of piped output. We give a standard name, and path (another variable).

    $backuppath = "D:\SQLServer\MSSQL11.MSSQLSERVER\MSSQL\Backup"

    $destpath = "d:\SQLServer\Backup"

    get-childitem -path $backuppath -Filter "EncryptionPrimer*.bak" |

        where-object { -not $_.PSIsContainer } |

        sort-object -Property $_.CreationTime |

        select-object -last 1 | copy-item -Destination (join-path $destpath "EncryptionPrimer.BAK")

    Once this is done we can restore things. I learned how to do this from PoSh using this post: http://stuart-moore.com/day-11-31-days-sql-server-backup-restore-using-powershell-basic-restore/

    However, since I have a standard backup file name, I’d probably do this in T-SQL and set a job that I can just run anytime. It’s simpler and easier, and since most of the time I’d want to do this from SSMS, a job works well.

    Here’s the PoSh script.

    Import-Module "SQLPS" -DisableNameChecking

    $sqlsvr = New-Object -TypeName  Microsoft.SQLServer.Management.Smo.Server("JollyGreenGiant\SQL2012")

    $BackupFile = "D:\SQLServer\Backup\EncryptionPrimer.BAK"

    #

    #echo ""

    #echo "Databases"

    #echo "———"

    #foreach ( $db in $sqlsvr.Databases) { write-host $db.name }

    echo " "

    echo "Begin Restore"

    echo "============="

    $Restore = New-Object "Microsoft.SqlServer.Management.Smo.Restore"

    $Restore.NoRecovery = $false

    $Restore.ReplaceDatabase = $true

    $Restore.Action = "Database"

    $Restore.PercentCompleteNotification = 10

    $BackupDevice = New-Object ("Microsoft.SqlServer.Management.Smo.BackupDeviceItem") ($BackupFile, "File")

    $Restore.Devices.Add($BackupDevice)

    $RestoreDetails = $Restore.ReadBackupHeader($sqlsvr)

    $logicalFileNameList = $Restore.ReadFileList($sqlsvr)

    $Restore.Database = $RestoreDetails.Rows[0]["DatabaseName"]

    foreach($row in $logicalFileNameList) {

        $RestoreDBFile = new-object("Microsoft.SqlServer.Management.Smo.RelocateFile")

        $RestoreDBFile.LogicalFileName = $row["LogicalName"]

        $RestoreDBFile.PhysicalFileName = $row["PhysicalName"]

        $Restore.RelocateFiles.Add($RestoreDBFile)

            }

    $Restore.SqlRestore($sqlsvr)

    write-host ("Completed the Database Restore operation on server for Database " +  $RestoreDetails.Rows[0]["DatabaseName"] + " on server $server")

     

    That’s it. I ran this a few times, and it worked well. A handy script to get the last backup and have it ready in a dev/test environment.