Change and make a difference

Let me tell you a story…

It is a drizzly night in November and I am sat with a bunch of people I have never met before. They are all eating and I am not (one too many Whiskys the night before). They all appear to know each other and are vigorously moving from subject to subject with enthusiasm and I am listening intently to the conversation but not really saying too much. I am probably the only Englishman in the entire bar -or at least, if I am not alone, there can’t be many of us there. To be honest I am not even sure whether that would really make a difference, for I am still relatively poor at introducing myself to strangers and, as I sit there feeling a little bit like a fish out of water everyone else is a fish in water. The date is Sunday 7th November 2010 and I am sitting in a bar called Lowell’s in a place known as Pike’s Place Market in a city called Seattle for a convention called the PASS Summit.

Going to Lowell’s

The fact that I am even sat here is a minor miracle, and really completely out of character but this is going to be the start of something I tell myself -the new me, and I am going to start to learn to socialize (like a human being) -like everyone else seems to do …effortlessly. I had registered for the “Sunday Night Meetup” hosted by Andy Warren (blog|twitter) and am intent on using the opportunity for a new beginning and actually making the effort to meet new people rather than let them be the ones to approach me whilst I hide behind my hard exterior. As Sunday evening drew nearer I started to get cold feet. ‘Why it’s only an Eventbrite ticket, it doesn’t really matter to anyone if I don’t come’ I told myself -’Besides, I’d have an even better time by myself stuck at the hotel bar on my own (at worst) or have a talkative stranger drop by and chat for a bit (hopefully)’.

The depressing reality of that sunk in. ‘NO I AM GOING!’ I decided. I will go, have something to eat, maybe have a couple of drinks and perhaps even learn the skills of communication like I always wished I could. In the worst case scenario, if it didn’t really go to plan, I could make my excuses and leave early with the added bonus that I would have eaten and had a drink… So I went.

Whilst sat there listening, on my right I had a young lady called Jessica Moss (blog|twitter) and on my opposite right a lady called Pam Shaw (blog|twitter). Pam was talking about the SQLSaturday movement, how it all began, where it is all going and what things need to change. Her enthusiasm and passion for SQLSaturdays immediately raised my interest and I soaked up the conversation. Whilst I sat there my mind wandered and I started to wonder if this could ever work in the U.K. and decided there and then that I wanted to host one. However there was only one small problem in my eyes. Even though several weeks ago I had just given my first ever presentation to a major event prior to heading off to the PASS Summit, for me the experience was a rather insular and miserable affair in that I didn’t really know anyone and they didn’t know me. In short I felt very lost as a speaker. I didn’t really know what to expect and the way the events work from a speaker’s perspective. I remember walking into the “Speaker room” for the very first time and it felt very much like I had entered the Slaughtered Lamb (from the American Werewolf in London film) and felt very much like the person I really was – a nobody. I digress slightly, but the point is that in Seattle, having listened to the conversation for a while I realised that in order for me to really be able to host one of these events I would have to have a slightly bigger profile than I had (something > zero) and so on my return back to the U.K. I didn’t mention my ambitions again to anyone and patiently waited.

Over the next year or so I worked very hard on my “social self” and made it my goal to present as much as possible to work on this side of me, share knowledge with others and to gain knowledge in the process. It was a win-win situation all around.  I have since gone on to present at many major and small events over the last couple of years and now feel completely at home just arriving in a new City of a new Country, giving a presentation, talking and socialising with people and returning home again. My self-development is certainly not fait accompli but I believe I have made significant progress. Even more importantly I have got to know who are the right people to ask for things and I eventually submitted my desire to host a SQLSaturday for Cambridge. Unfortunately when I did so the timing was not quite right it and I was asked to patiently wait on the wings until it would be possible to give it the green light. I will confess that at this stage I gave up all hope and as months passed by I believed it would not happen.

Then… joy of joys… several months ago an email arrived in my Inbox asking me if I still wanted to host an event. The reply probably took me around 10 seconds to send. It was of course a massive ‘YES!’.

I want you to know that by one simple action (going to Lowell’s) set off a chain of events and you could do the same. I am no longer “afraid” to approach you if you are a stranger and say hello or talk about the Weather, I have realised that ambitions can be fulfilled and today feel like almost anything is possible if you work hard enough for it.

If you are able to, I really hope to see you at SQLSaturday #162 Cambridge and if not then please make sure you say hello to me at SQLRally Dallas, the SQL 2012 Summit in Seattle, SQLBits or many of the other SQLSaturdays and user groups that I hope to be at. I would also like to extend a huge thank you Pam Shaw whose enthusiasm and continued support for the SQL Community has been the spark for something new and exciting and to Niko Neugebauer (blog|twitter) and his SQLSaturday #115 Lisbon team for giving me a huge welcome and amazing insight into the running of his event which inspired me and provided a template model that I hope to replicate where possible. I would also like to thank SQLSaturday and SQLPASS for allowing me to do this, but most of all I want to thank Karla Landrum (twitter|blog) for her unwavering support and dedication to the task in hand. Thank you all!

Remember that everything you do, everything you say, everyone you meet and everywhere you go has the power to touch and change your and other peoples lives. Be mindful of this and once in a while try to change a little!

Posted in personaldevelopment, publicspeaking, sqlpass, sqlrally, sqlsaturday, SQLServerPedia Syndication, summit | Leave a comment

Remember your OS when upgrading to SQL 2012

Probably as far back as the end of last year when I first started putting material together for my Enter the Dragon and Moves like Jagger presentations and giving very early mash up presentations of them combined together, I started emphasising one very important upgrade consideration which is very often ignored. It is also a fact that is quite nicely touched upon by Glenn Berry (twitter|blog) in his excellent book SQL Server Hardware and if you have yet to discover its unique delights then I strongly advise you to check it out.

The consideration I am talking about is of course the mainstream support dates of our Hardware and Software but most specifically the Operating System (in our case Windows) which is the one of most concern.

Spot the problem?

During my Moves Like Jagger – Upgrading to SQL Server 2012 presentation (most recently given to 24HOP) I have discussed that should you decide to upgrade to SQL Server 2012 then you should watch out for the mainstream support end dates for Windows 2008 and Windows 2008 R2. If you are installing SQL 2012 to Windows Server Core then your only consideration anyway is Windows 2008 R2 (SP1) otherwise using Windows 2008 (SP2) is a supported Operating System. However from a mainstream support perspective the version of Windows you use is kind of irrelevant since (as you can see in the slide above) each expires on exactly the same date -surprisingly mid July next year!

Yes people you heard me right, should you choose to upgrade your environment to SQL 2012 today, tomorrow or have already done so, then I hope you have taken this into consideration -for if your company are not prepared to pay for Extended Support then you could be looking at yet another upgrade (this time the OS) sometime next year. This scenario is one very strong reason why if you have implemented SQL 2012 in an Availability Group or Clustered configuration you can probably give yourself a pat on the back right now. It is going to simplify your OS upgrade and maintain a level of High Availability where this is required.

Beautiful now, but rebuild costs could be large!

At the turn of the year I went slightly out on a limb by saying that because of the Mainstream Support expiry dates it was my firm belief that Microsoft would release their newest Operating System (I called it Windows 8 Server at the time :) ) before mid July and that if you did not have a compelling reason to upgrade to SQL 2012 now, then it is probably a good idea to wait a while.

Well so far my guesstimate appears to be coming true. We now know that the next Server release of Windows is called Windows 2012 (I personally like the fact it is in-line with the Server based Application names) and  today I have seen the following url- Windows Server 2012 Release Candidate Timing. So we know by the very name that the OS is coming this year and at the time of writing all indications point to an imminent release but let me stress that I have no inside knowledge and this is all guesswork so please don’t get upset if the release happens on the 31st of December 2012 -however unlikely!

In summary I believe you should take three approaches to implementing SQL Server 2012 at this present time :-

  1. The first and probably my most recommended option would be to wait for (hopefully only) a few more months if you can until the release of Windows 2012.

The second and third options are to plan for the Mainstream Support end of Windows 2008/R2 by :-

  1. Arranging and paying for Extended Support.
  2. Implementing SQL 2012 in an HA configuration that enables you up blow away your base Operating System and start again (for instance using AlwaysOn or even Peer to Peer Replication are possible routes you can take).

Whatever you do, don’t forget the obvious …and remember your dates.

Posted in 24HOP, availability, sql, SQLServerPedia Syndication | 1 Comment

Who’s active on SQL 2000

Yes yes yes I *know* we are currently on SQL 2012 but just hear me out for a second…

I think I am probably one of the only people on the planet who has not (yet) used Adam Machanic’s (blog|twitter) whoisactive Stored Procedure. One of the reasons for this is that going right back to the days of SQL Server 2000 I had rolled my own stored procedure which worked very nicely and did everything that I ever needed it to.

With the advent of SQL Server 2005 came the ever so useful DMOs and whilst these gave an even more insightful portal into the guts of SQL 2005 (and now all versions above) internals, my own Stored Procedure still gave me all the information I needed. If there was any extra information I needed to obtain, I would usually delve into the DMVs using code snippets taken primarily from Louis Davidson or Glenn Berry.

I’ll be honest. I never got around to rewriting the code I wrote -I got lazy people! I always intended on doing so, but never quite found the time or excuse.

Well today whilst monitoring Twitter’s #SQLHELP hashtag I came across a request for a SQL 2000 version of whoisactive. I offered up my dusty ol’ proc and it was gratefully accepted…


Please be aware the the following code has been provided as is, taken straight from my very own (old) scripted ‘dbaadmin’ solution database targeted specifically towards SQL 2000 but has been tested and works up to (at least) SQL 2008R2 (I have not tested on SQL 2012). Because of this, my usp_activity Stored Procedure requires two prerequisites to work :-

  1. A dbaadmin database
  2. An activity table created in the dbaadmin database

I appreciate that in your environment, you may have your own administrative databases -but luckily I have extensively commented my code so it really shouldn’t be very difficult for you to do the switch. With respect to the activity table, that is simply needed for the capture parameter if you wish to persist activity statistics. If that is not something that you need, then again you can remove the code segment for that and therefore remove the dependency.

Before I give you the code let me tell you roughly how it works. In SQL 2000, in order to obtain the last executed statement for a SPID we would use DBCC INPUTBUFFER(spidid). The other part of the equation is the querying of the master.dbo.sysprocesses  table to view all active SPIDs on our instance. Unfortunately, since the DBCC result set is being returned per SPID and not as a tabular result set for all, we are unable to join our last executed statement result to the sysprocesses result set. In addition, the second challenge is that in order to store the output of each DBCC INPUTBUFFER request (using the INSERT EXEC technique)  we must insert each item separately into a table as is. The output does not have a SPID id and therefore this means we are missing the join key in this table. To overcome this second challenge I simply perform the insert (into a table that has a column for a SPID id) and then update the SPID number as a separate operation. We perform our DBCC INPUTBUFFER for each SPID in succession using a cursor. Now we have our last executed statement table with respective SPID ids. More importantly we have also solved our first problem and are able to join our sysprocesses data (first captured into a temporary table)  against our statement data …who needs DMOs!

The stored procedure uses a selection of named parameters with defaults and the most important of these is the @help parameter.

If you execute the stored procedure as follows :-

exec dbo.usp_activity @help=1

Then you will receive the very useful help output :-

Help Specified.

	@dbname sysname = '', --optional option (if unspecified all activity is captured, otherwise only activity for specified database is captured)
	@capture bit = 0, --optional option (if unspecified results are not captured, otherwise enables capture process activity to dbaadmin..activity table)
	@show bit = 1, --optional option (show process list (default))
	@excludespid int = 0, --optional option (exclude spidid from process list (default))
	@filteronspid int = 0, --optional option (display only spid, 0 for all spids (default))
    @blockedonly int = 0, --optional option (display only spids participating in blocking, 0 for all active spids (default))
	@simple int = 0, --option option (display cut down column list for result set)
	@help bit = 0 --optional option (view help)

If you wish to return all current SPIDs then leave off all parameters OR if you wish to return all SPIDs currently running in a database context then specify the @dbname parameter. One parameter that comes in very useful is @blockedonly and will return only blockers or blocked SPIDs by specifying a value of 1 :-

exec dbo.usp_activity @blockedonly=1

This returns a very useful amount of information about our blockers and blocked SPIDs and has saved my bacon on many occasions (result set below has been condensed) :-

I shan’t go into any more detail about any of the other parameters or how you would use them since I think they are fairly obvious but if not they shouldn’t take you very long to figure them out. So for now I shall list the code that you will need to setup usp_activity.

First we create the dbaadmin database.

CREATE DATABASE dbaadmin
GO

Next we need to create the activity table within the dbaadmin database.

USE [dbaadmin]
GO
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
USE dbaadmin
GO
IF 'activity' IN (SELECT NAME FROM sysobjects WHERE TYPE = 'U')
BEGIN
PRINT 'Table activity already exists, dropping before executing create script...'
DROP TABLE activity
END
GO
-- =============================================
-- Author:        Mark Broadbent
-- Create date: 13/02/2001
-- Description:    Creates activity table to store results for stored procedure usp_activity
-- =============================================
CREATE TABLE [dbo].[activity](
[database] [nvarchar](128) NOT NULL,
[spid] [smallint] NOT NULL,
[kpid] [smallint] NOT NULL,
[blocked] [smallint] NOT NULL,
[waittype] [binary](2) NOT NULL,
[waittime] [bigint] NOT NULL,
[lastwaittype] [nchar](32) NOT NULL,
[waitresource] [nchar](256) NOT NULL,
[dbid] [smallint] NOT NULL,
[uid] [smallint] NOT NULL,
[cpu] [int] NOT NULL,
[physical_io] [bigint] NOT NULL,
[memusage] [int] NOT NULL,
[login_time] [datetime] NOT NULL,
[last_batch] [datetime] NOT NULL,
[ecid] [smallint] NOT NULL,
[open_tran] [smallint] NOT NULL,
[status] [nchar](30) NOT NULL,
[sid] [binary](86) NOT NULL,
[hostname] [nchar](128) NOT NULL,
[program_name] [nchar](128) NOT NULL,
[hostprocess] [nchar](8) NOT NULL,
[cmd] [nchar](16) NOT NULL,
[nt_domain] [nchar](128) NOT NULL,
[nt_username] [nchar](128) NOT NULL,
[net_address] [nchar](12) NOT NULL,
[net_library] [nchar](12) NOT NULL,
[loginame] [nchar](128) NOT NULL,
[context_info] [binary](128) NOT NULL,
[sql_handle] [binary](20) NOT NULL,
[stmt_start] [int] NOT NULL,
[stmt_end] [int] NOT NULL,
[request_id] [int] NULL,    --new column in sysprocesses in 2005
[eventtype] [nvarchar](30) NULL,
[parameters] [int] NULL,
[eventinfo] [varchar](4000) NULL,
[snaptime] [smalldatetime] NULL

) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

PRINT '======================================================================================================='
IF 'activity' IN (SELECT NAME FROM sysobjects WHERE TYPE = 'U')
BEGIN
PRINT 'Table activity successfully created...'
END

GO

And finally the Stored Procedure itself must be created.

USE [dbaadmin]
GO
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
USE dbaadmin
GO
IF 'usp_activity' NOT IN (SELECT NAME FROM sysobjects WHERE TYPE = 'P')
BEGIN
EXEC ('
CREATE PROCEDURE usp_activity AS
SELECT ''This is a stub procedure, implementation of it will be created by an ALTER statement''
')
PRINT 'Procedure usp_activity does not exists, creating a stub procedure before executing create script...'
END
GO
-- =============================================
-- Author:        Mark Broadbent
-- Create date: 13/02/2001
-- Description:    Procedure usp_activity captures current activity and respective executing/ed statements to a table called dbaadmin..activity (table is created if it does not exist). Table is refreshed whenever procedure is ran
-- Version: 0.9
-- Dependencies: NONE
-- Changes: Version 0.6 truncates the activity table when capture = 0
-- Changes: Version 0.7 added stub functionality
-- Changes: Version 0.8 added simple view
-- =============================================
ALTER PROC [dbo].[usp_activity]
@dbname sysname = '', --optional option (if unspecified all activity is captured, otherwise only activity for specified database is captured)
@capture bit = 0, --optional option (if unspecified results are not captured, otherwise enables capture process activity to dbaadmin..activity table. simple view cannot be captured.)
@show bit = 1, --optional option (show process list (default))
@excludespid int = 0, --optional option (exclude spidid from process list (default))
@filteronspid int = 0, --optional option (display only spid, 0 for all spids (default))
@blockedonly int = 0, --optional option (display only spids participating in blocking, 0 for all active spids (default))
@simple int = 0, --option option (display cut down column list for result set)
@help bit = 0 --optional option (view help)
AS
SET NOCOUNT ON

IF @help = 1
BEGIN
PRINT 'Help Specified.'
PRINT ''
GOTO printoptions
END

IF @dbname NOT IN (SELECT name FROM master..sysdatabases) AND LEN(@dbname) > 0
BEGIN
PRINT @dbname + ' database specified cannot be found.'
PRINT ''
RETURN
END

--Create table #inputbuffer (EXEC cannot use table variables so that is why they are not used!)
CREATE TABLE #inputbuffer (
rowid INT IDENTITY,    --simply used to map on spid
spid INT,
EventType NVARCHAR(30),
Parameters INT,
EventInfo varchar(4000)
)

--Create table spids
SELECT d.name AS 'database',p.*
INTO #spids
FROM
Master..sysprocesses p
join master..sysdatabases d ON p.dbid = d.dbid
WHERE 1=0

DECLARE @SPID_id NVARCHAR(5)
DECLARE @statement NVARCHAR(300)

--declare and execute cursor
DECLARE SPIDCursor CURSOR FORWARD_ONLY FOR
SELECT p.spid
FROM
Master..sysprocesses p (NOLOCK)
join master..sysdatabases d  (NOLOCK) ON p.dbid = d.dbid
WHERE p.ecid=0 AND (@dbname = '' OR UPPER(d.name) = UPPER(@dbname))
AND (@filteronspid =0 OR p.spid = @filteronspid)
AND (@blockedonly = 0
OR p.spid IN (SELECT spid FROM Master..sysprocesses (NOLOCK) WHERE blocked > 0)
OR p.spid IN (SELECT blocked FROM Master..sysprocesses (NOLOCK) WHERE blocked > 0)
)
ORDER BY p.spid

OPEN SPIDCursor
FETCH NEXT FROM SPIDCursor INTO @SPID_id
WHILE @@fetch_status = 0
BEGIN
SET @statement ='INSERT #inputbuffer (eventtype,parameters,eventinfo) EXEC(''DBCC inputbuffer(' + ltrim(@SPID_id) + ') WITH NO_INFOMSGS'')'
--PRINT @statement

--Insert current running spids into table
INSERT INTO #spids
SELECT d.name AS 'database', p.*
FROM
Master..sysprocesses p (NOLOCK)
join master..sysdatabases d  (NOLOCK) ON p.dbid = d.dbid
WHERE p.ecid=0 and p.spid =@SPID_id
and p.spid <> @@spid  --exclude running spid
and p.spid <> @excludespid

EXEC (@statement)
--Update #inputbuffer table to tag on spid
UPDATE #inputbuffer SET spid = @SPID_id WHERE rowid = IDENT_CURRENT( '#inputbuffer' )

FETCH NEXT FROM SPIDCursor INTO @SPID_id
END
CLOSE SPIDCursor
DEALLOCATE SPIDCursor

IF @capture = 1 AND @simple = 0 --simple view cannot be captured
BEGIN
--reason this is being executed through exec is to have ordering and to be able to specify ordering
--of columns if we so wish
INSERT dbaadmin.dbo.activity EXEC('SELECT s.*,i.eventtype,i.parameters,i.eventinfo, getdate() from #spids s
LEFT JOIN #inputbuffer i ON i.spid = s.spid
ORDER BY s.spid')
END
ELSE
TRUNCATE TABLE dbaadmin..activity

IF @show =1
IF @simple = 0
EXEC('SELECT s.*,i.eventtype,i.parameters,i.eventinfo, getdate() as snapdate from #spids s
LEFT JOIN #inputbuffer i ON i.spid = s.spid
ORDER BY s.spid')
ELSE
EXEC('SELECT s.[database], s.spid, s.blocked, s.waittime, s.cpu, s.physical_io, s.memusage, s.open_tran, s.status, s.hostname, s.loginame, I.eventinfo from #spids s
LEFT JOIN #inputbuffer i ON i.spid = s.spid
ORDER BY s.spid')

DROP TABLE #inputbuffer
DROP TABLE #spids

RETURN
PRINT '======================================================================================================='
printoptions:
PRINT
'
@dbname sysname = '''', --optional option (if unspecified all activity is captured, otherwise only activity for specified database is captured)
@capture bit = 0, --optional option (if unspecified results are not captured, otherwise enables capture process activity to dbaadmin..activity table)
@show bit = 1, --optional option (show process list (default))
@excludespid int = 0, --optional option (exclude spidid from process list (default))
@filteronspid int = 0, --optional option (display only spid, 0 for all spids (default))
@blockedonly int = 0, --optional option (display only spids participating in blocking, 0 for all active spids (default))
@simple int = 0, --option option (display cut down column list for result set)
@help bit = 0 --optional option (view help)
'

GO
SET ANSI_PADDING OFF

PRINT '======================================================================================================='
IF 'usp_activity' IN (SELECT NAME FROM sysobjects WHERE TYPE = 'P')
BEGIN
PRINT 'Procedure usp_activity successfully altered...'
END

GO

So there you have it. I don’t pretend for one minute that the T-SQL code is perfect, even during the process of putting this post together I spotted a couple of things that should be changed such as wrong choices for datatypes and a slightly roundabout way for checking the existence of objects, but the important thing is that the code works and works well. Therefore if you are still using SQL Server 2000 in your existing environment and need whoisactive style functionality then look know further. Enjoy.

Posted in Concurrency, connectivity, dmv, SQLServerPedia Syndication, tsql | 2 Comments