SQL Server – SSMS – Table Designer v/s ALTER TABLE – Best Practices – Msg 1701 – Creating or altering table failed….This exceeds


A few months ago, I wrote about how one might end up with a Message #1701 error when attempting to execute an ALTER TABLE…ALTER COLUMN statement. You can refer the original post here. Vishal Gajjar (blog) recently wrote about the Table Designer component of SSMS. In his post, he draws attention to the fact that altering the data-type of a column causes the Table Designer to re-create the entire table, which is one of the solutions to this problem.

However, the table designer while useful in this case, may not be that useful always. As I try to build my case through the post, do let me know whether the conclusions I derive sound as logical to you as they do to me.

A recap

Assume that we have the following setup:

CREATE DATABASE foo
GO

USE foo
GO
CREATE TABLE MyTbl (MyName CHAR(4030))
GO

INSERT INTO MyTbl
SELECT REPLICATE('a',4030)
GO

Let us assume that we need to modify the structure of our table:

ALTER TABLE MyTbl ALTER COLUMN MyName CHAR(4031)
GO

The result of this would be a Message #1701 error:

Msg 1701, Level 16, State 1, Line 2

Creating or altering table ‘MyTbl’ failed because the minimum row size would be 8068, including 7 bytes of internal overhead. This exceeds the maximum allowable table row size of 8060 bytes.

The Root Cause

The root cause of the error was that the maximum allowed row size in Microsoft SQL Server is 8060 bytes (calculations presented in the original post here).

The ALTER TABLE statement attempts to expand the column “in-place”, i.e. it copies the data over to a new column with the new length specifications on the same row, making the row total now 8061 bytes, which is more than the 8060 maximum – resulting in the error seen.

The Solution – SSMS Table Designer

Besides modifying the storage to have smaller, more granular tables,the only solution I see is to apply the change in the following sequence:

  1. Create a new table with the new specifications
  2. Copy all the data over from the existing table to the new table
  3. Drop the old table and rename the newly created table

Let’s see how the table designer can help us overcome the issue at hand with the row size increasing the 8060-byte limit.

Right-click the table in question and choose “Design” to launch the Table Designer. image
In the Designer, simply change the column size. image
Script the changes to a file image
Save the changes & confirm in the Object Explorer that the size change completed successfully image

For those interested, the scripted output of SSMS is as under, with descriptive comments added by me as required to demonstrate the essentials.

/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
---Nakul - Step 01: Creating the new table
CREATE TABLE dbo.Tmp_MyTbl
	(
	MyName char(4031) NULL
	)  ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_MyTbl SET (LOCK_ESCALATION = TABLE)
GO
---Nakul - Step 02: Pump data from old table to new table
IF EXISTS(SELECT * FROM dbo.MyTbl)
	 EXEC('INSERT INTO dbo.Tmp_MyTbl (MyName)
		SELECT MyName FROM dbo.MyTbl WITH (HOLDLOCK TABLOCKX)')
GO
---Nakul - Step 03: Drop the old table and rename the new table
DROP TABLE dbo.MyTbl
GO
EXECUTE sp_rename N'dbo.Tmp_MyTbl', N'MyTbl', 'OBJECT' 
GO
COMMIT

Conclusion

As we just saw, dropping and recreating tables is the standard scripting mechanism used by the Table Designer. While it does make our life easy, the fact remains that:

  1. The Table Designer method is performance intensive
    • Assume that we are trying to change the size of a character based column in a table that has a million or more rows
    • When using the table designer, we might end up waiting for what would look like infinity, with I/O shooting through the roof and at the end, we would have a bloated transaction log
  2. The Table Designer performs a table recreate even if it is not required (while a recreate is essential in our case, it may not be the case when changing a column from NOT NULL to a NULL

The bottom line is: If efficient DDL can be written to make the changes required, avoid using the Table Designers as far as possible.

There is no denying that the designer is supposed to make life simpler, and that’s where I would share my philosophy around these. I use the designers as a stepping stone using the scripts generated as a base, and then trying to improve upon them. After practicing this a couple of times, I was able to churn out pretty decent, standardized DDL without using the designer at all.

Microsoft SQL Server comes with a set of some pretty good designers (Table & Query designer to name a few) which are useful productivity enhancers under most conditions, but might end up causing issues in other cases. Use them with caution.

Until we meet next time,

Be courteous. Drive responsibly.

Subscribe to my posts via E-mail: Subscribe here | Read my posts via your favourite RSS reader: Click Here!

SQL Server – SSMS – Profiler – Extracting Deadlock Event Data to XDL files


A deadlock occurs when there is a cyclic dependency between two or more threads, or processes, for some set of resources within SQL Server. We can use the SQL Server Profiler to capture deadlock information. Today, we will see how to use the SQL Server Profiler to capture deadlock information, and also how to export this information for distribution to the development team.

Setting up the Environment

First of all, let’s create a scenario that would create the necessary test data for us to generate a deadlock. In the query below, you will find 3 sets of transaction-bound queries, which need to be executed in 3 different SSMS windows – all connected to the same SQL Server instance.

/*
WARNING: This script is provided "as-is" and without warranty.
         Please do not use this in quality assurance and/or production environments.
*/

-- Step 01: To be run in query window #1
USE tempdb
GO

CREATE TABLE DeadlockTestTable1 (DL1Id   INT, DL1Name VARCHAR(20))
CREATE TABLE DeadlockTestTable2 (DL2Id   INT, DL2Name VARCHAR(20))

INSERT INTO DeadlockTestTable1 VALUES (1, 'Deadlock'), (2, 'SQL Server'), (3, 'Test')
INSERT INTO DeadlockTestTable2 VALUES (1, 'Deadlock'), (2, 'SQL Server'), (3, 'Test')

-- Step 02: To be run in query window #1
USE tempdb
GO
BEGIN TRANSACTION 

UPDATE DeadlockTestTable1 SET DL1Name = 'Uplock' WHERE DL1Id = 2
WAITFOR DELAY '00:00:20'
UPDATE DeadlockTestTable2 SET DL2Name = 'Downlock' WHERE DL2Id = 2

ROLLBACK TRANSACTION

-- Step 03: To be run in query window #2
USE tempdb
GO
BEGIN TRANSACTION 

UPDATE DeadlockTestTable2 SET DL2Name = 'Downlock' WHERE DL2Id = 2
WAITFOR DELAY '00:00:20'
UPDATE DeadlockTestTable1 SET DL1Name = 'Uplock' WHERE DL1Id = 2

ROLLBACK TRANSACTION

-- Step 04: To be run in query window #3
USE tempdb
GO
BEGIN TRANSACTION 

UPDATE DeadlockTestTable2 SET DL2Name = 'Uplock' WHERE DL2Id = 2
WAITFOR DELAY '00:00:10'
UPDATE DeadlockTestTable1 SET DL1Name = 'Downlock' WHERE DL1Id = 2

ROLLBACK TRANSACTION

Using the Profiler to Capture & Export the Deadlock trace

In this section, we will see how to use the SQL Server profiler to capture the deadlock trace.

  1. Launch the SQL Server profiler and connect to the desired SQL Server instance
  2. Start a new trace
  3. Under Event selection, clear out any default events. Only keep the Locks –> “deadlock graph” event class as checked. You may also have “Lock:Deadlock” and “Lock:Deadlock chain” as checked
  4. image
  5. Once the trace is running, in SSMS Query window #1, run the query intended for window #1
  6. In SSMS Query window #2, run the query intended for window #2. Repeat this process for query #3
  7. Within 20 seconds, two of the 3 queries would have failed execution because they would have been chosen as the deadlock victims
  8. The Profiler trace would look like the following:
  9. image
  10. One can analyze the deadlock graph here itself. In case this deadlock needs to be sent over to the development team, one can follow one of the many steps highlighted below

Export Deadlock Data – Export Selected deadlock information only

If only a selected deadlock needs to be forwarded to the development team for analysis, then, simply right-click on the deadlock and choose “Extract Event Data”. Deadlock graph information can then be saved to any desired location of your choice. The deadlock graph information is stored in the form of SQL Server Deadlock XML files (*.xdl). As the name indicates, it is ultimately an XML file containing the XML representation of the deadlock graph.

image

Export Deadlock Data – Export all deadlock information

If you need to extract all deadlock graphs from a SQL Server profiler trace, go to File->Export->Extract SQL Server events->Extract Deadlock events…

image

Export this information to a location of your choice in the form of SQL Server Deadlock XML files (*.xdl). You may choose to save all events in a single file, or have separate files for each deadlock event.

image

Opening the trace in SQL Server Management Studio

Now that the deadlock information has been exported to the file system, you can now E-mail these files over to the development team who can in-turn analyze the deadlock graphs for you, and arrive at a resolution to the deadlock issue.

To open these files, one does not need to use the SQL Profiler. The Management Studio (SSMS) is capable of opening the XDL files and representing the information as a deadlock graph.

image

image

As you can see from the image above, hovering the mouse over the deadlock victim also reveals the affected query. You may also open the XDL file in an XML editor of your choice, if you would like to see the deadlock information in the XML format.

I hope that the above method will help you quickly & efficiently exchange deadlock data & related analysis with your development team.

Until we meet next time,

Be courteous. Drive responsibly.

Subscribe to my posts via E-mail: Subscribe here | Read my posts via your favourite RSS reader: Click Here!

SQL Server – How to stay in touch with me – Blog, RSS Feed and E-mail


A lot of my friends and colleagues at the office have asked me how they can easily stay in touch with my posts. Therefore, today, I am posting a very brief post that should help you to stay in touch with my posts.

My Blog

I blog generally on Mondays & Thursdays every week at: http://beyondrelational.com/blogs/nakul/default.aspx.

You can leave a comment (every one of which will be read by me) or send me an E-mail. I would like to hear from you, so please leave your feedback – whether you liked the post, did not like it (if not, why), and what else would you like to know. I eagerly look forward to your comments.

RSS Feed & E-mail!

My posts are available via an RSS feed also. If you prefer to have my posts delivered to your favourite feed reader (including E-mail), you can subscribe to my RSS Feed from my Blog page. Just click the “RSS for Posts” link, and you should be able to subscribe through a variety of options.

image

Ask Me a Question

You can always ask me a SQL Server Question at: http://beyondrelational.com/ask/nakul/default.aspx.

Please note that this is voluntary assistance, and therefore, I will only provide guidance. I will not do your work or assignments for you.

My Linked-In Profile:

You can take a look at my Linked In Profile here:

View Nakul Vachhrajani's profile on LinkedIn

Social Media Presence

You can follow me on the following:

Twitter:

Google+: +Nakul

Facebook: https://www.facebook.com/nakulvachhrajani 

Do note that it’s generally a busy day at the office for me, so I don’t post updates on my stream often.

That’s pretty much it. There aren’t too many channels, which helps me to read each reply, comment or query that you might send out to me.

Until we meet next time,

Be courteous. Drive responsibly.

Subscribe to my posts via E-mail: Subscribe here | Read my posts via your favourite RSS reader: Click Here!

Happy Diwali & A Prosperous New Year to one and all!


Happy Diwali & A Prosperous New Year!

This week, people of Indian origin all around the globe are celebrating the festival of Diwali (http://en.wikipedia.org/wiki/Diwali) – the festival of lights that marks the triumph of good over evil.

I pray that all the readers have a Very Happy Diwali and also have a Prosperous New Year ahead!

Diwali Wishes

Until we meet next time,

Be courteous. Drive responsibly.

SQL Server – TempDB – Is it a copy of the Model database?


Microsoft SQL Server comes with a whole range of system databases, which I visited in my post – How to programmatically identify system and user databases on a SQL Server instance. System databases are special, and there some very specific and peculiar characteristics of each (documentation for which can be found from Books On Line here).

Model v/s TempDB

One such system database is the “model” database. As the name suggests, user databases created on the particular SQL Server instance are copies of the model database.

The TempDB on the other hand, is a special system database. It’s special because every time the SQL Server is restarted, the TempDB is re-created, and we receive a clean copy of the TempDB. This got me thinking:

  • How does SQL Server recreate TempDB?
  • Does it copy the Model database and use that as the base?
  • How is it that all but one of the restrictions on the Model database are also applicable to the TempDB?

The only way to answer these questions, is to run a small test.

WARNING: The tests demonstrated in this post involve changing your default SQL Server installation. Please check with your SQL Server Administrator before performing these steps in your development and quality assurance environments. These tests should not be performed on a production database.

Modifying the Model database

On my test system, the model database is a clean one – no modifications have been made after SQL Server was installed. On such a clean model database, let’s create a table, and fill it with some test data.

USE model
GO
CREATE TABLE DefaultTableTest
( DataId INT IDENTITY(1,1),
  RandomId INT DEFAULT (RAND()*1000),
  DataName VARCHAR(10) DEFAULT 'DEFAULT'
)
GO

/******************************************
   Insert some test data into the table
******************************************/
USE model
GO
INSERT INTO DefaultTableTest DEFAULT VALUES
GO 600000

Now, let’s restart the SQL Server service. Take care to restart the service using the steps mentioned in my post here. Do not use the Services.msc console to restart Microsoft SQL Server.

image

Check the TempDB

Once the SQL Server restart is complete, it’s time to check the TempDB. First of all, let’s navigate to the physical drive where TempDB is located. We all know that typically, TempDB is 8MB in size upon SQL Server restart by default.

image

Because TempDB is larger than expected, it definitely has something more than usual.

Next, let’s refresh the Object Explorer pane in SSMS. We see that under TempDB, we have the DefaultTableTest table created for us. Therefore, let’s attempt to SELECT from the table.

image

Conclusion

TempDB is a copy of the model database – just as is the case with any other user database. No other system database is a copy of the model database – which adds to the reasons why TempDB is special.

There is also a lesson to be learnt from this. Whenever a change is made to the “model” database, one needs to be very careful about the change – it will directly impact one of the most used databases – the TempDB.

I hope you liked today’s post. Leave your feedback before you go.

Until we meet next time,

Be courteous. Drive responsibly.