Author Archives: nakulvachhrajani

Unknown's avatar

About nakulvachhrajani

Nakul Vachhrajani is a SQL Server MCTS, TOGAF certified Technical Architect with Capgemini having a total IT experience of more than 16 years. Nakul is an active blogger, and has been a guest columnist for SQLAuthority.com and SQLServerCentral.com. Nakul presented a webcast on the “Underappreciated Features of Microsoft SQL Server” at the Microsoft Virtual Tech Days Exclusive Webcast series (May 02-06, 2011) on May 06, 2011. He is also the author of a research paper on Database upgrade methodologies, which was published in a CSI journal, published nationwide. In addition to his passion about SQL Server, Nakul also contributes to the academia out of personal interest. He visits various colleges and universities as an external faculty to judge project activities being carried out by the students. Disclaimer: The opinions expressed herein are his own personal opinions and do not represent his employer’s view in anyway.

#0253-SQL Server-HASHBYTES-String or binary data would be truncated: Msg 8152


Most enterprise products require that they be able to audit data modifications being made within the application. An important aspect of auditing is to be able to identify changes made outside of the application too, i.e. updates directly made on the data using a direct connection to the SQL Server instance. I recently authored a series of articles on SQLServerCentral.com around data change and tamper detection mechanisms available in Microsoft SQL Server. These are:

  • An in-depth look at change detection in SQL Server – Part 01 [Link]
  • An in-depth look at change detection in SQL Server – Part 02 [Link]
  • HASHBYTES: Is CHECKSUM really required? [Link]

Soon after the publication of these articles, a coincidence at work prompted me to write this post.

One of our application modules used HASHBYTES for detecting data change. We were receiving random reports that the quality assurance engineers were receiving auditing errors. As we tracked the issue down through the SQL Server Profiler, we noticed that the underlying error was a “simple” string truncation error:

Msg 8152, Level 16, State 10, Line 5
String or binary data would be truncated.

Root Cause

The following line from the Books-On-Line help for HASHBYTES [Link] caught our attention:

Allowed input values are limited to 8000 bytes.

As soon as we read it, things became very clear to us. Taking a quick look at the schema showed us that the underlying field being checked for changes was an NVARCHAR(MAX) field and the users were attempting to enter data greater than 4000 characters (i.e. 8000 bytes) causing the issue. As long as the data remained less than 4000 characters, no error was encountered.

A demo

The script below demonstrates the expected behaviour of HASHBYTES given that the input string is less than or equal to the 8000 byte limit. For the sake of brevity, I am using the REPLICATE function to create the string.

USE tempdb;
GO
--Declare an NVARCHAR((MAX) variable
DECLARE @tHashInputs NVARCHAR(MAX);
--Create a 4000 character string
SELECT @tHashInputs = CAST(REPLICATE('a',4000) AS NVARCHAR(MAX));

--Attempt to generate the HASHBYTEs value for this string
SELECT HASHBYTES('MD5',ISNULL(@tHashInputs,''));
GO

image

Now, let me alter the script such that the string being evaluated using HASHBYTES is greater than the 8000 byte limit, i.e. is 4001 characters for the NVARCHAR data-type:

USE tempdb;
GO
--Declare an NVARCHAR((MAX) variable
DECLARE @tHashInputs NVARCHAR(MAX);
--Create a 4000 character string
SELECT @tHashInputs = CAST(REPLICATE('a',4001) AS NVARCHAR(MAX));

--Attempt to generate the HASHBYTEs value for this string
SELECT HASHBYTES('MD5',ISNULL(@tHashInputs,''));
GO 

The following error is encountered upon executing the batch:

Msg 8152, Level 16, State 10, Line 5

String or binary data would be truncated.

As can be seen from the example above, HASHBYTES will fail for data beyond the documented 8000 character limit. Hence, areas like free-form comments may not be a suitable candidate for usage of HASHBYTES.

Solution

The only known workarounds that we have currently are:

  • Split the strings into multiple parts before generating the HASHBYTES value
  • Opt for any other change detection algorithm

Have you ever encountered such a situation before? If yes, what solution did you apply to overcome it?

References:

  • HASHBYTES – Books On Line page [Link]
  • An in-depth look at change detection in SQL Server – Part 01 [Link]
  • An in-depth look at change detection in SQL Server – Part 02 [Link]
  • HASHBYTES: Is CHECKSUM really required? [Link]

Until we meet next time,

Be courteous. Drive responsibly.

#0252 – Shutdown/Restart a local or remote server via command prompt


Today’s post is not SQL Server related, but is related to the underlying host operating system and it’s administration. When working on development projects, one may need to restart servers and/or workstations often. This becomes a challenge when one is working from remote locations or on virtual machines hosted on the network.


Today, I will show how to shutdown or restart a local or remote machine via the command prompt. In fact, you may be surprised (as are most people around me) to learn that this functionality exists since Windows 2000 (i.e. it’s more than a decade old!)


Remote Shutdown tool – SHUTDOWN.EXE


The windows operating system ships with a remote shutdown tool. It is a command line tool that can be used to shutdown or restart local and remote machines. In Windows Server 2003, this tool has been enhanced to also accept the reason for the shutdown.


The syntax and help for this tool can be obtained by going to the command prompt on the machine and typing:


shutdown /?


The tool allows administrators to:



  • Shutdown or restart a local machine

    • Shutdown: shutdown /s
    • Restart: shutdown /r

  • Shutdown or restart a remote machine

    • Shutdown: shutdown /s /m \MyRemoteMachine 
    • Restart: shutdown /r /m \MyRemoteMachine

  • Schedule shutdown/restart operations

    • Shutdown: shutdown /s /t 200
    • Restart: shutdown /r /t 200
    • The above examples set a timeout of 200 seconds before the shutdown/restart takes place

  • Specify a reason for the shutdown/restart

    • Planned: shutdown /s /d p:xx:yy
    • Unplanned: shutdown /s /d u:xx:yy
    • Where xx is the major reason number and yy is the minor reason number. For example, a shutdown due to application installation should have a major reason code of 4 and a minor reason code of 2
    • User can also specify a custom comment by using the /c swtich

  • Abort a system shutdown

    • shutdown /a

  • Log off from a local machine (remote logoff is not supported)

    • shutdown /l

  • Hibernate a local machine

    • shutdown /h

  • Force the operation

    • shutdown /s /t 200 /d p:4:2 /f

Further Reading: http://technet.microsoft.com/en-us/library/cc780360(v=ws.10).aspx


Until we meet next time,


Be courteous. Drive responsibly.


[EDIT: April 25, 2013, 0215IST – rectified the option for Hibernate.]

#0251 – SQL Server – Script to rename a database


Recently, one of my colleagues asked me a seemingly simple question:



I am facing issues in renaming a database – can you give me a script that can help me?


I was quite surprised at the question, but later realized why the issue was encountered. What had happened was that on our development servers, a database was restored, some data-cleanup work done and then the team wanted to run some pre-defined scripts on the database for checking and comparison purposes. These scripts were hard-coded to use a particular set of database names and therefore, the team wanted to rename the given SQL Server database.


However, what most of us don’t realize when working with the SQL Server Management Studio (SSMS) is that it opens up multiple connections to a given database. In this particular case also, the query editor’s connection was open which was causing issues with database renaming.


I therefore provided the team with the following script, which essentially takes the database into single-user mode and then renames the database to avoid any issues being caused by multiple open connections.

–Important: This changes the database context to master.
–If the user database remains in use, the rename will not succeed
USE master;
GO
–Now, take the DB in single-user mode
ALTER DATABASE AdventureWorks2008R2 SET SINGLE_USER;
GO
–Now, rename the DB
USE master;
GO
ALTER DATABASE AdventureWorks2008R2 MODIFY NAME = MyAdWrks2008R2;
GO
–Now, bring the database back to multi-user mode
–Caution: Use the new name here because the database would have already been renamed
USE master;
GO
ALTER DATABASE MyAdWrks2008R2 SET MULTI_USER;
GO

–Do not forget to apply necessary permissions again


Further Reading:


In the same context of SSMS and related connections, some of my previous posts might interest you:



Until we meet next time,


Be courteous. Drive responsibly.

#0250-SQL Server 2012-High Availability & Disaster Recovery [HADR] related DMVs and Catalog Views


SQL Server Catalog Views & Dynamic Management Views (DMVs) take an administrator to the very heart of SQL Server. DMVs expose vital diagnostic information which are not only useful to indicate the overall health of the SQL Server, but also of the databases hosted by the given SQL Server instance. The list of DMVs that changed in SQL Server 2008 R2/2012 is available in one of my previous posts here: http://bit.ly/XobXup.

Microsoft SQL Server 2012 comes with a very wide variety of changes designed to make the SQL Server more available. These features are collectively known as High Availability & Disaster Recovery [HADR] features and are also often recognized via their code name – “Always ON”. Some of the key enhancements introduced in SQL Server 2012 are:

  • AlwaysON extends Windows clustering
  • A shared storage disk is no longer required to configure clustering
  • One Primary database, four secondary replicas, and two secondary synchronous replicas can be configured
  • Readable secondaries, supporting DBCC and backups
  • Log backup and Full backup with COPY_ONLY option can be performed on any replicas
  • Log backups done on all replicas does not break across replicas and therefore can be used as part of recovery strategy

It would be next to impossible to cover all of HADR in a single post. Therefore, I would redirect you to the posts by Balmukund Lakhani (B|T) who is an expert in all matters SQL. He demonstrated HADR features of SQL Server during :

A complete list of the HADR related DMVs and Functions is available at the links below:

  • AlwaysOn Availability Groups Catalog Views: Link
  • AlwaysOn Availability Groups Dynamic Management Views and Functions: Link

Until we meet next time,

Be courteous. Drive responsibly.

#0249-SQL Server – sp_can_tlog_be_applied-How to determine if a given log backup can be restored?


Microsoft SQL Server databases support three recovery models – Simple, Bulk-logged and Full Recovery – each targeted to provide unique recovery capabilities. For this post, it is assumed that the reader is aware about the various recovery models.

When restoring a database under the FULL recovery model, the recovery involves restoring the databases from upto 3 different kinds of backups:

  • Full Database Backup
  • Differential Database Backup
  • Transaction Log Backup

As can be understood from the post on backup timelines and understanding the database restore process from Pinal Dave, a.k.a SQLAuthority (B|T), the fastest way to restore a database in the full recovery model is:

  • Restore the last known, good full backup
  • Restore the latest of all known differential backups
  • Restore each transaction log, in sequence backed up after from the last differential backup was performed

This works fine when we have a handful of transaction log files to restore. But, it becomes difficult to identify which particular transaction log should be restored when we have a collection of log files (on a SAN storage, tape or any other form of storage) – some of which would be invalid based on the backups already restored. The question therefore is:

Can a given transaction log backup be restored on a database?

To help answer this question, Microsoft SQL Server provides a built-in stored procedure – sp_can_tlog_be_applied (http://msdn.microsoft.com/en-us/library/ms187769.aspx).

This system stored procedure can be used to determine if a given transaction log backup can be restored on a database in recovery (If the database is not in recovery, no backups can be restored). Allow me to present an example to demonstrate the usage of this function.

Preparing the backup set

The following set of scripts performs the following tasks:

  1. Create a test database
  2. Create a test table within the newly created database
  3. Change the database recovery model to FULL
  4. Take a full backup of the database
  5. Modify some data and take two log backups
USE master;
GO
--1. Create database
CREATE DATABASE LogVerificationDB
ON PRIMARY (NAME = PrimaryFile,
            FILENAME = 'C:SQL DatabasesLogVerificationDBPrimaryFile.mdf'
           )
LOG ON (NAME = LogFile,
        FILENAME = 'C:SQL DatabasesLogVerificationDBLogFile.ldf'
       );
GO

--2. Create test data
USE LogVerificationDB;
GO
CREATE TABLE LogVerificationTable (ObjectId INT, ObjectName VARCHAR(200));
GO

--3. Change recovery mode to FULL
ALTER DATABASE LogVerificationDB SET RECOVERY FULL;
GO

USE master;
GO
BACKUP DATABASE LogVerificationDB 
TO DISK = 'C:SQL DatabasesLogVerificationDBLogVerificationDB_Full.bak';
GO

--4. Make some modifications
USE LogVerificationDB;
GO
INSERT INTO LogVerificationTable (ObjectId, ObjectName)
SELECT so.object_id, so.name
FROM sys.objects AS so;
GO

--5. Take a log backup
USE master;
GO
BACKUP LOG LogVerificationDB
TO DISK = 'C:SQL DatabasesLogVerificationDBLogVerificationDB_Log1.bak';
GO

--6. Make some more modifications
USE LogVerificationDB;
GO
INSERT INTO LogVerificationTable (ObjectId, ObjectName)
SELECT so.object_id, so.name
FROM sys.objects AS so;
GO

--7. Take another log backup
USE master;
GO
BACKUP LOG LogVerificationDB
TO DISK = 'C:SQL DatabasesLogVerificationDBLogVerificationDB_Log2.bak';
GO

sp_can_tlog_be_applied in action

Now, let us assume that the database crashed and needs to be restored from the available backups. To do so, I manually dropped the database.

--08. Drop the test datbase
USE master;
GO
ALTER DATABASE LogVerificationDB SET SINGLE_USER;
GO
DROP DATABASE LogVerificationDB;
GO

First, I restore the full backup with NORECOVERY specified, indicating that other backups are yet to be restored.

--09. Restore WITHOUT Recovery
USE master;
GO
RESTORE DATABASE LogVerificationDB
FROM DISK = 'C:SQL DatabasesLogVerificationDBLogVerificationDB_Full.bak'
WITH  FILE = 1,  
      NOUNLOAD ,  
      STATS = 10,  
      NORECOVERY ,  
MOVE N'PrimaryFile'    TO N'C:SQL DatabasesLogVerificationDBPrimaryFile.mdf',
MOVE N'LogFile' TO N'C:SQL DatabasesLogVerificationDBLogFile.ldf';
GO

--09A. Check status
SELECT state_desc, state, user_access_desc FROM sys.databases WHERE name = 'LogVerificationDB';
GO

image

Now that the full backup has been restored, we know that we can start restoring the differential and/or the transaction log backups. But, which one of the backup file goes first? We use the sp_can_tlog_be_applied system stored procedure to check which one of Log backup #1 and #2 can be applied at this stage.

--10. Check if the transaction logs can be applied
--    Since we restored the database with no recovery, transaction log backups can be applied
--    However, can Log Backup #01 be applied?
DECLARE @canTxLogBeApplied BIT = 0;
EXEC sp_can_tlog_be_applied 
         @backup_file_name = 'C:SQL DatabasesLogVerificationDBLogVerificationDB_Log1.bak', 
         @database_name = 'LogVerificationDB', 
         @result = @canTxLogBeApplied OUTPUT;

SELECT @canTxLogBeApplied AS CanTransactionLog#1BeApplied;
GO

--11. Check if the transaction logs can be applied
--    Since we restored the database with no recovery, transaction log backups can be applied
--    However, can Log Backup #02 be applied?
DECLARE @canTxLogBeApplied BIT = 0;
EXEC sp_can_tlog_be_applied 
         @backup_file_name = 'C:SQL DatabasesLogVerificationDBLogVerificationDB_Log2.bak', 
         @database_name = 'LogVerificationDB', 
         @result = @canTxLogBeApplied OUTPUT;

SELECT @canTxLogBeApplied AS CanTransactionLog#2BeApplied;
GO

Because the transaction log backup #2 is newer than #1, it cannot be applied directly. Log backup #1 has to be applied first. This can be confirmed in the screen-shot below where it is seen that the sp_can_tlog_be_applied returns a 1 for Log backup #1, but a 0 for backup #2.

image

Conclusion:

As can be seen from the example above, a simple check using sp_can_tlog_be_applied can help administrators determine the sequence in which transaction log backup files are to be restored on a database.

Did you know?

Did you know that sp_can_tlog_be_applied was available in SQL Server 2000 also? I will admit that I did not know about it before researching for this blog.

Further Reading

  • sp_can_tlog_be_applied (BOL Link)
  • Restore Sequence and Understanding NORECOVERY and RECOVERY (Link)
  • Backup Timeline and Understanding of Database Restore Process in Full Recovery Model (Link)

Until we meet next time,

Be courteous. Drive responsibly.