•  
  • Archives for SQL Server (8)

Lost that Single-User Connection?

You have changed your database to single_user mode to do a task.  As you go about your business, you lose track of which connection was the single_user connection.  You start closing connections and mistakenly close the session that was your single_user connection.  Now you are unable to start a new single_user session.  It would seem that somebody or something has taken your connection.

Today, I am going to discuss some things you may do to get around this problem.

The first thing that may come to mind when you encounter this is “Oh crap!”  Well, no need to get too terribly worried (not unless you really hosed something up and you are trying to fix it real quick before the boss notices).

The next thing you may think of trying is how to circumvent the single_user mode.  And during that thought process you may be thinking that single_user does not really mean single_user so you might try something like start a DAC session.  Well, let’s go through that and see what would happen in a DAC session if your single_user session is stolen.

I am going to skip the part of setting a database into single_user mode because we are presuming that the condition already exists.  To start a DAC session, I am going to point you to a previous article I did on the topic – here.

To ensure I am using a DAC session, I am going to issue the following query.  This will ensure I am in the right session and that DAC is in use.

SELECT s.group_id,e.name, CAST(g.name AS NVARCHAR(20)) AS ResourceGroup, s.session_id 
		, s.login_time, CAST(s.HOST_NAME AS NVARCHAR(20)) AS HostName 
		, CAST(s.program_name AS NVARCHAR(20)) AS ProgramName 
		,s.original_login_name 
		,s.is_user_process 
		,s.STATUS 
	FROM sys.dm_exec_sessions s 
		INNER JOIN sys.dm_resource_governor_workload_groups g 
			ON g.group_id = s.group_id 
		INNER JOIN sys.dm_exec_connections ec 
			ON s.session_id = ec.session_id 
		LEFT OUTER JOIN sys.endpoints e  
			ON ec.[endpoint_id]=e.[endpoint_id] 
WHERE s.session_id = @@SPID 
ORDER BY g.NAME; 
GO

In my case, this results in an endpoint with the name “Dedicated Admin Connection” and a spid of 84.  Good, I am in the correct session for the rest of this test.  Next, I will issue a Use database statement.  I have created a test database called ClinicDB.  So I will issue the following.

USE ClinicDB;
GO

I get the following result.

Msg 924, LEVEL 14, STATE 1, Line 1
DATABASE 'ClinicDB' IS already OPEN and can ONLY have one USER AT a TIME.

So, that blows that idea right out of the water.  It shouldn’t really have been a consideration in the first place because single_user really means just that – single_user.

Now What?

Well, what do you think we could do now to circumvent this little problem and get that single_user session back?

That requires a little investigative work.  It is time to find out who has taken the single_user session and politely ask them to give it up.  To make that task a little easier, we could modify the previous query to find out who has that single_user session (thus limiting how many people we have to ask).  I have modified the following query to use sys.sysprocesses so I could limit the results to the ClinicDB.  This is a limitation of SQL 2008 R2 and older versions.  Getting the database reliably means using sysprocesses.  Despite the database_id being available in other related DMVs, it’s just not that easy.  One would think you could use sys.dm_exec_requests.  But if a request is not active, an entry won’t exist for that session.  This problem is fixed in SQL 2012 since the sys.dm_exec_connections DMV now has the database_id field.  Enough of that birdwalk and on to the query.

SELECT s.group_id,e.name, CAST(g.name AS NVARCHAR(20)) AS ResourceGroup, s.session_id ,DB_NAME(r.dbid) AS DBName
		, s.login_time, CAST(s.HOST_NAME AS NVARCHAR(20)) AS HostName
		, CAST(s.program_name AS NVARCHAR(20)) AS ProgramName 
		,s.original_login_name 
		,s.is_user_process 
		,s.STATUS 
	FROM sys.dm_exec_sessions s 
		INNER JOIN sys.dm_resource_governor_workload_groups g 
			ON g.group_id = s.group_id 
		INNER JOIN sys.dm_exec_connections ec 
			ON s.session_id = ec.session_id 
		INNER JOIN sys.sysprocesses r
			ON r.spid = s.session_id
		LEFT OUTER JOIN sys.endpoints e  
			ON ec.[endpoint_id]=e.[endpoint_id]
	WHERE DB_NAME(r.dbid) = 'ClinicDB'
ORDER BY g.NAME; 
GO

I chose not to do an entirely new query to simply demonstrate that it was possible with a very small tweak to what has been already used.

Now that you know (in my case I can see that I have a session open with ID = 80 that is connected to that single_user database), I can walk over to the person (knowing his/her login id and computer name) and politely ask them to disconnect.

In the end, this is really an easy thing to resolve.  Sure it may take some people skills – but that doesn’t make the task too terribly difficult.  Next time this happens to you, just remember you can run a quick query to find who has sniped that single_user session.

Lions and Tigers and Bears…

Categories: Corner, News, Professional, SSC, SSSOLV
Comments: No Comments
Published on: October 15, 2012

Last Thursday I found myself on a journey of sorts.  There weren’t any lions or tigers or bears, but there were plenty of “Oh My”‘s.

It all began on a dark and gloomy night.  Well, I am sure it was dark and gloomy somewhere.  In reality it was before dusk and the sun was shining.  I was heading out of town for a quick trip.  My family was to drop me off at the airport so we could have dinner together before I left.

We ended up at a McDonalds.  We let the kids play in the play area while we chatted with some of the other parents in the area.  For all intents and purposes this is where the journey began.

Our timing was pretty good to arrive at dinner.  We had just missed the commotion.  A family had just been robbed at gunpoint.  A rare thing on this side of the river in the woods.

Finishing up with the excitement and dinner we were back on our way to the airport.  When arriving at the airport, I found that my flight was to be delayed by about an hour. Apparently, the flight from San Francisco was delayed causing us some big delays.  In turn, this resulted in me getting to my hotel after midnight.

At the hotel after a few hours of rest, I was awake and prepping for the day.  The most nerve racking thing was about to happen and I had no clue it was coming.  I had taken the elevator downstairs to get some breakfast.  After having eaten, and needing to leave within the next 20 minutes, I was back in the elevator on my way back up to the room.  Five of those minutes were consumed in that elevator as it decided to stop working between floors.  It was as if the elevator took a break or decided to reboot.  Needless to say, I took the stairs the next time which was the last time.

Now why does any of this matter?  Well, it was certainly an interesting situation as I was heading to the Prometric test center to take the MCM Knowledge exam.  The exam was intense enough without the added complexity of travel.  For now, the only option (besides paying extra for remote delivery) for people such as myself living in Utah is to travel out of Utah.  This exposes us to that extra complexity and challenges such as getting stuck in an elevator.  I was a bit anxious thanks to that experience, but I made it to the center in time for my exam.  Thankfully I was planning on being there extra early.

Moral of the story – plan ahead.  I considered flying in and out the same day to take the exam and then reconsidered.  I didn’t want to take the risk of flight delays causing me to miss it.  Having that extra time, it made these lions and tigers and bears all the more bearable and I still was able to take the exam.

Finally, it has happened…

Comments: 2 Comments
Published on: October 4, 2012

Last month I blogged about my absence from the blogosphere.  If you want, you can read about it again – here.  Granted, it has been a month and I still have been slacking.  I am hoping to turn a new leaf and post more regularly here in the next few weeks.

Since that last post I had been anxiously waiting.  The book seemed to keep getting delayed.  Yesterday, reality finally hit home.  It is so weird how much different it feels to finally have a book physically in my hands.

I am one that likes ebooks and I don’t normally have to be able to feel the pages of the book.  But this is one case where the ability to rifle the pages is so much more gratifying.  Finally the book is real!!

If you are interested, you can get the book here.

Oh and if you are wondering why I posted this picture, it is simple.  I didn’t want to take a picture of myself today holding the book and the other books pictured happen to be books that I had on hand because I have been reading them of late.

Another Interesting Sort

Categories: News, Professional, SSC, SSSOLV
Tags: ,
Comments: No Comments
Published on: March 19, 2012

In October of 2011, I shared an example of a peculiar set of sort requirements.  Today, I am going to share another similar set of requirements.  Based on prior experience, when I saw this request on a sort order, I was sure I could find a simpler solution.  Today, I will share the requirements and solution with you.

Requirements

Given a set of characters, you must be able to sort according to the following:

  1. !
  2. $
  3. ?
  4. @
  5. ^
  6. {
  7. >
  8. ASCII values

Setup

To demonstrate the requirements and solution, let’s create a temp table and populate it with some values like those in the requirements.

CREATE TABLE #Chars
(
	MyChar CHAR(1)
)
 
INSERT INTO #Chars (MyChar)
VALUES
  ('!'), ('"'), ('$'), ('?'), ('@'), ('^')
, ('{'), ('>'), ('1'), ('2'), ('3'), ('4')
, ('5'), ('6'), ('7'), ('8'), ('9'), ('A')
, ('B'), ('C'), ('D')

Solution

SELECT *
	FROM #Chars
	ORDER BY MyChar COLLATE SQL_Latin1_General_Cp1251_CS_AS

Sometimes the simplest solution requires a lot of testing.  When I came across the requirements, I thought it could be solved via a collation.  The problem was that I did not know which collation.  I had to test a few collations to find the collation that would create the correct result set.  If you are interested in learning about other collations, you can read this article.

Dedicated Administrator Connection

Categories: News, Professional, SSC
Tags: , , ,
Comments: 2 Comments
Published on: January 19, 2012

Recently you may have read my article about some hidden functions in SQL Server.  In that article you learned that those functions were in some DMOs and that you could get at them through the resource database.

Today I found myself learning more about the resource database.  Due to what I had learned in my prior foray into the resource database, I was curious if certain other functions might call some hidden functions in that database.

Sadly – they did not.  But in my travels I did happen across something else that is in that database.  Those items are called system base tables.  Unlike the trio of functions from the last article – you can get to these but it is STRONGLY advised to not do it.

Naturally, I want to check these tables out – especially since the MSDN article does say how to get to them.  I will write about some adventures into looking at these tables in the future.  I already found one interesting thing that seemed odd – but first I will need to login using the DAC and start testing to confirm a hypothesis.

For now, I want to cover how to create a Dedicated Administrator Connection.  This should be something that DBAs know how to do.  It isn’t difficult, and I will only cover one method and leave the other method to the Microsoft documentation.

You can create a DAC through either SSMS or through SQLCMD.  You can create one remotely, but you will need to enable that option since it is disabled by default.  You can find the method for creating this connection via SQLCMD here.

To create a connection through SSMS, it is rather easy as well.  You simply add (case insensitive) “admin:” to the beginning of your server as shown in this image.

In order for this to work, you will need to have the browser service running.  If it is not running, you will get an error message.  This error message is informative if you read it.  It will provide a clue to look at the browser service.

Once you have successfully created this connection, you can now use it when necessary to perform administrative tasks or for some learning opportunities.  If you open a query using this connection you will see something like this next image in your query tab.

You can see in the tab of this query tab that there is the label “ADMIN:”.  This is your DAC connection.  You are limited to one of these at a time – period.

If you try to create a second connection, you will get a nasty message.  The message is not entirely informative – just understand that you are getting it because you already have a DAC open.

It is a good idea to become familiar with how to connect via the DAC.  I have a connection saved for quick access.  Luckily I have a development server which I can test and use for learning opportunities.  As the warning MSDN states: “Access to system base tables by using DAC is designed only for Microsoft personnel, and it is not a supported customer scenario.”  If you venture into the system base tables via the DAC – Microsoft will not support it if you break it.

Haunting a Database Near You

Comments: 4 Comments
Published on: October 31, 2011

Today, we have a special Halloween edition.  For me, Halloween and computer geek go quite well together.  And thinking about it, I wanted to try to better understand if there was a correlation.  As a DBA, have you wondered the same thing?

Well, I have a short list of five things that may help you to correlate your affinity for Halloween with your love for Databases.

Tombstones

Did you know that a tombstone is a legitimate thing in SQL Server?

Tombstones are replica related.  They are deleted items in the replica and are used to make sure the deleted item doesn’t get put back in the replica inadvertently.

You can read a lot more about tombstones from the msdn article here.

Tombstones are not unique to SQL Server.  These are commonplace in Active Directory as well.

 

Ghosts

Not all rows that are deleted move on to the afterlife quickly like they should.  Some like to hang around due to unfinished business.

The unfinished business in this case is the server running a cleanup thread.  This has to be done when the server is not too busy and has enough free resources to help these records move on to the afterlife.

You can see the evidence of these ghosts with specialized equipment.  By the use of a DMO, we can see the ghost record count on a per index basis.  The DMO is sys.dm_db_index_physical_stats.  Take a look at the ghost_record_count column in the returned record set.

With more specialized equipment, the engine takes care of the cleanup and removal of these ghosts.  Here is an in-depth foray into the world of SQL ghost hunting.  Whatever you do, don’t cross the streams.

Zombies

It’s alive!!

No, I killed it!!

It can’t be…How is it still alive?

The transaction will not commit and may get rolled back.  The zombie has reared its’ ugly head.  A transaction that cannot commit but keeps going (or rolls back) due to an unrecoverable error is a zombie transaction.

From MSDN, here is a more specific definition of a zombie.

Rowsets can become zombies if the internal resource on which they depend goes away because a transaction aborts.

Spawn

The spawn of SQL server is not so much like the Spawn character of the comics.  Nor is it much like the spawn shown to the right.

That is unless it is not managed very well.  SQL can spawn multiple threads if the optimizer deems it necessary for a query.  This is also known as parallelism.

Parallelism can be a good thing or it can be a bad thing.  Understanding it can help keep it on the good side.  You might want to check out some of Paul White’s articles on the topic.

Children of the Corn

Well, this one is not really something in SQL server.  That said, every time I think of orphaned users in SQL server – children of the corn comes to mind.

An orphaned user is one in which the login SID does not match for one reason or another.  This makes it so that the user can no longer log in to SQL server.

If you don’t know about these kids, they can really make for a frustrating day.  Read more here.

Bonus

I have just covered five things in SQL server that correlate quite closely to Halloween.  But this by no means is an exhaustive list.  For instance, an obvious correlation is the “KILL” command.  Another good one is the monster known as the Blob (read more about that monster here and here).

With the opportunity to have Halloween every day, it’s no wonder I like being a DBA.

Happy Halloween

Precision and Scale

Tags: ,
Comments: No Comments
Published on: August 24, 2011

PrecisionAs is the case with many of my topics of late, I came across this one by helping somebody else.  In SQL, we should be well aware of Precision and Scale of certain datatypes.

The particular case I was working on was focused on the decimal datatype, and so we will work with that throughout this post explicitly.

What are these attributes?

According to MSDN, these attributes have the following definitions.

Precision – specifies the number of digits an object can hold

Scale – specifies the number of digits to the right of the decimal point that an object can hold.

Based on those definitions, it seems pretty straight forward, right?  Well, it is until you start doing a bit of math.  Microsoft has formulas for figuring out what the resultant precision and scale will be for various math operations.  You can read about that here.

Throughout our example, we will be focusing on multiplication and division.  We will demonstrate a few different results and configurations as well.

First, let’s get some formulas out of the way.  The formulas for precision and scale, as they show in MSDN at the link above, are as follows:

Multiplication
	Precision
	p1 + p2 + 1
	Scale
	s1 + s2
Division
	Precision
	p1 - s1 + s2 + max(6, s1 + p2 + 1)
	Scale
	max(6, s1 + p2 + 1)

As is described in the MSDN article, p represents precision and s represents scale.  The number annotations with p and s represent the corresponding expressions in the mathematical operation.  The equation that we will be trying to solve is as follows:

SELECT ROUND(((@numerator*@multiplier)/@divisor1)*@anothermultiplier,2)

ScaleBut for the majority of these exercises, we will be focusing on this part of the formula.

SELECT ((@numerator*@multiplier)/@divisor1)

This will provide us with ample example of the math involved when calculating the resultant precision and scale of a SQL math operation.

Here is an example of the above query with values.  This query results in a value that is consistent with such calculators as MS Excel ( ;0) ).

SELECT ((5000000000.00*2.0250000000)/111883775187.72)

However, if we use variables in lieu of those values, we start to see different results.  And thank goodness for that, because there wouldn’t be much to talk about otherwise.  So, let’s dump those values into some variables and see what starts happening.

DECLARE @divisor1	DECIMAL(18,6) = 111883775187.72
		,@numerator	DECIMAL(18,2) = 5000000000.00
		,@multiplier	DECIMAL(10,3) = 2.0250000000
		,@multiplier1	DECIMAL(18,3) = 2.0250000000
		,@stage1		DECIMAL(18,2)
		,@anothermultiplier	DECIMAL(18,2) = 932364.79

And the formula(s).  I say formulas, because I will be demonstrating two results here.  Notice quickly that I have two similar multiplier variables – they differ only in name and precision.

SELECT ((@numerator*@multiplier1)/@divisor1)
SELECT ((@numerator*@multiplier)/@divisor1)

If you execute those two queries, you should get very similar results.  Both should return 0.090xxx, but the second has more scale, extending the decimal out 8 places rather than 6 places.  For the second query our result is 0.09049569.  When you combine this difference at this point, it could make for some accounting nightmares.  Especially given this difference in result occurs early on in the equation.

Notice in my variables there is one called stage.  Let’s use that one now and see how using a staging variable plays into this.

DECLARE @divisor1	DECIMAL(18,6) = 111883775187.72
		,@numerator	DECIMAL(18,2) = 5000000000.00
		,@multiplier	DECIMAL(10,3) = 2.0250000000
		,@multiplier1	DECIMAL(18,3) = 2.0250000000
		,@stage1		DECIMAL(18,2)
		,@anothermultiplier	DECIMAL(18,2) = 932364.79
 
SELECT @stage1 = @numerator*@multiplier
SELECT @stage1/@divisor1
SELECT @stage1 = @numerator*@multiplier1
SELECT @stage1/@divisor1

Do you see what just happened?  Both multipliers now produce the same result.  How could that be?  Let’s look at that.  This time, let’s post calculations for precision and scale along-side each of those queries.

SELECT @stage1 = @numerator*@multiplier		--P = 18+10+1 = 29, S = 2+3 = 5
SELECT @stage1/@divisor1					--P = 18-2+6+max(6, 2+18+1) = 43, S = max(6, 2+18+1) = 21 --Actual P = 38 S = 16
SELECT @stage1 = @numerator*@multiplier1	--P = 18+18+1 = 37, S = 2+3 = 5
SELECT @stage1/@divisor1					--P = 18-2+6+max(6, 2+18+1) = 43, S = max(6, 2+18+1) = 21 --Actual P = 38 S = 16

Looking this over, you should be able to quickly pick out some anomalies.  Let’s start with the anomalies present in the calculations for the second query.  First, you can see that the value for p1 is 18.  One might fairly think that it should be the resultant precision of the first query.  But, the variable is created as Decimal(18,2) and that precision and scale is used in calculations involving that variable.

The second thing one should notice is that the resultant precision is 43.  Then why did I change it to 38 at the end?  Max precision is 38.  If the resultant precision of a mathematical operation exceeds 38, then it must be reduced to 38.  This has an impact on scale – which is the next item of note.  In the aforementioned MSDN article, scale is simply reduced by the difference between resultant(p) and final(p).  That simple calculation holds true for these particular queries.  But, if we look at the following queries, we can clearly see that it is behaving differently.

DECLARE @divisor1	DECIMAL(18,6) = 111883775187.72
		,@numerator	DECIMAL(18,2) = 5000000000.00
		,@multiplier	DECIMAL(10,3) = 2.0250000000
		,@multiplier1	DECIMAL(18,3) = 2.0250000000
		,@stage1		DECIMAL(18,2)
		,@anothermultiplier	DECIMAL(18,2) = 932364.79
 
SELECT (@numerator*@multiplier1)/@divisor1
SELECT (@numerator*@multiplier)/@divisor1

And the correlating notes regarding precision and scale calculations.

SELECT (@numerator*@multiplier1)/@divisor1	--P = 37-5+6+max(6, 5+18+1) = 62, S = max(6, 5+18+1) = 24 --Actual P = 38 S = 6
SELECT (@numerator*@multiplier)/@divisor1	--P = 29-5+6+max(6, 5+18+1) = 54, S = max(6, 5+18+1) = 24 --Actual P = 38 S = 8

Look at the final(s) for that first query.  Scale is actually 6, but that does not match the math.  Resultant(p) = 62, Final(p) = 38 and that means the difference is 24.  Resultant(s) is 24, from which I subtract 24 and should get 0.  Well, there is a part of that formula that needs better explanation maybe in the documentation.  The final(s) should actually include the max(6, Resultant(s) – (resultant(p) – final(p))).  The final(s) cannot be less than 6, and thus the reason that we see 6 digits to the right of the decimal in the result of that first query.

Now let’s change that divisor scale up a bit.  The requirements dictate that the divisor be a Decimal(18,2) – I used 18,6 as one of my test sets.  In this case, the only thing that changes is the final(s).  And in this particular case (though, I don’t recommend shortcutting – it just works for this case), we can simply add 4 to the final(s) of the second query.  The first remains unchanged.

Let’s look at the resulting value now.  This difference alone is cause enough for significant differences in the results of the larger formula.

First query = 0.090495, Second query = 0.090495695046.  To this point, I have shown why this happens.  The calculations performed exceed the limitations for precision which impacts scale – which affects accuracy of the formula.

I showed one method, without saying as much, on how to avoid this.  My use of an intermediary step to perform these calculations via variable helped to correct the precision/scale/accuracy problem.  Another viable option is to use appropriate precision and scale for the data being used.  Changing precision and scale to match expected data can have a significant impact on the resultant accuracy of the calculation.

I used two multipliers to demonstrate that last suggestion.  The more accurate result came from the second query which used a more appropriate precision and scale for the data (see the variable @multiplier).

Send DBMail

Categories: News, Professional, SSC
Comments: No Comments
Published on: August 15, 2011

With SQL Server 2005, Microsoft improved the methods available for DBAs to send email from SQL Server.  The new method is called Database Mail.  If you want to send emails programmatically, you can now use sp_send_dbmail.  You can read all about that stored procedure here.

What I am really looking to share is more about one of the variables that has been introduced with sp_send_dbmail.  This parameter is @query.  As the online documentation states, you can put a query between single quotes and set the @query parameter equal to that query.  That is very useful.

Why am I bringing this up?  Doing something like this can be very useful for DBAs looking to create cost-effective monitoring solutions that require emailing result sets to themselves.  I ran across one scenario recently where a DBA was looking for help doing this very thing.  In this case, the query was quite simple.  He just wanted to get a list of databases with the size of those databases to be emailed.

Here is a quick and dirty of one method to do such a thing.

EXEC msdb.dbo.sp_send_dbmail
    @profile_name = 'SQLDBA' ,
    @recipients = 'myEmail@myDomain.com' ,
    @subject = 'List of Databases'
    ,@query = 'Exec sp_databases'

As I said, this is a real quick and dirty example of how to send an email with query results.  The results of the query in the @query parameter (in this case) will be in the body of the email.  A slightly modified version of that first solution is as follows.

EXEC msdb.dbo.sp_send_dbmail
    @profile_name = 'SQLDBA' ,
    @recipients = 'myEmail@myDomain.com' ,
    --@body = @messageBody ,
    @subject = 'List of Databases'
    ,@query = '    select
        DATABASE_NAME   = db_name(s_mf.database_id),
        DATABASE_SIZE   = convert(int,
                                    case -- more than 2TB(maxint) worth of pages (by 8K each) can not fit an int...
                                    when convert(bigint, sum(s_mf.size)) >= 268435456
                                    then null
                                    else sum(s_mf.size)*8 -- Convert from 8192 byte pages to Kb
                                    end)
    from
        sys.master_files s_mf
    where
        s_mf.state = 0 and -- ONLINE
        has_dbaccess(db_name(s_mf.database_id)) = 1
    group by s_mf.database_id'

This is only really slightly modified because I took the guts of sp_databases and dumped that into this query.  The modification being that the remark column was removed.  Why do this?  Well, to demonstrate two different methods to get the same data from the @query parameter.  We can either pass a stored procedure to the parameter, or we can build an entire SQL statement and pass that to the parameter.

This is just a simple little tool that can be used by DBAs.  Enjoy!

page 1 of 1
Calendar
May 2013
M T W T F S S
« Apr    
 12345
6789101112
13141516171819
20212223242526
2728293031  
Content
Now Reading

Now Reading

Planned books:

Current books:

  • SQL Server 2012 T-SQL Recipes: A Problem-Solution Approach

    SQL Server 2012 T-SQL Recipes: A Problem-Solution Approach by Jason Brimhall

Recent books:

View full Library

Categories

Categories

SQLHelp

SQLHelp


Welcome , today is Saturday, May 18, 2013