Troubleshooting

Coding naked.

Me, circa 1992. This is not the most embarrassing picture of that time period.

Me, circa 1992. This is not the most embarrassing picture of me from that time period.

True story: when I was in college, I was the lead singer (if you can call it that) for a goth rock Christian rave band called Sandi’s Nightmare.  I had zero musical talent, and relied solely on the strengths of my band-mate (Brad; you still rock); however, while my singing ability was dubious at best, I was pretty theatrical.  We had a total of 3 awesome shows before we moved on to other things, but it was a lot of fun while it lasted.  Our biggest hit was a cover of Lust Control’s Dancing Naked, a fantastic little number about David’s celebration of the ark returning; his passion and excitement overwhelmed his embarrassment.

I promise, I’m not making this stuff up; it was pretty edgy for the Bible belt of  Northeast Louisiana in the early 90’s.  I mean, I had an earring and everything.   The point of this post (besides reveling in my musical abilities and tastes of 25 years ago) is that sometimes we just need to be naked.

Let me explain; I made choices that in hindsight are difficult to defend (like my haircut). However, there was a reason for the choice at the time, and even though it may not have been the greatest idea, I’ve learned something from every experience I had.  While there are things that I would do differently if given the choice and knowledge I have today, I don’t regret many things.  That’s what the metaphor of nakedness is all about; being open and honest about not only your successes, but your choices along the way.  You can’t change the past, but you can learn from it.

Becoming a Naked Developer

I’ve spent most of my professional career as a SQL developer working for one company (13 years in November);  I was the first developer hired by that company, and my job was to build an integration platform transforming syslog data into reports, all on a shoestring budget.  I strung something together in a couple of weeks, and in the first month, I took a process that normally took two weeks to do by hand down to a day; my boss threatened to kiss me (I was flattered, but declined).

Was it pretty (the code, not the boss)?  No.  Was it successful?  Yes.

Fast forward a couple of years to 2004: I’m a member of small team building a solution to analyze more data than I’ve ever seen in my life (terabytes of data from firewalls and Windows machines); we had to import and semantically normalize data in near-real-time.  We built a solution using DTS, and then moved it to .NET and MSMQ.

Was it pretty? No.  Was it successful?  Yes.  Part of that code is still being used today, and my company has thrived off of it.  We were acquired by a larger company 8 years ago, and we’ve kept moving forward.

Every few years, we’d talk about doing a rewrite, and we’d bring in some outside expertise to evaluate what we’ve done and help us come up with a migration plan.  Some consultant would come in, look at what we did, and shake their heads at us.  Each time, we (the remaining original developers) would attend meeting after meeting as our code was dissected and judged; we sat naked (metaphorically) in front of a team of experts who told us everything that was wrong with the choices that we made.  At the end of each visit, we’d regroup and complain about the agony of judgement. In all honesty, we would have done things differently, given our current experience (and modern technology).  However, the simple truth is: we won the day.  We continue to win the day.

During some of these initial code reviews, the consultants were jerks.  They’d spend a lot of time bemoaning how horrid everything was; I’d be embarrassed and try to explain what I would have done differently if only I had the time.  The consultants would eventually propose some complex solution that would cost hundreds of thousands of dollars to implement.  Our company would consider the offer, stick it in a file somewhere, and we’d keep on keeping on.   Clunky code that works is better than expensive code with the same outcome.

Over time, I learned to live with the embarrassment (as you can tell from this post); I started listening to what the consultants would say and could quickly figure out which ones had good advice, and which ones were there to just be seagulls.  People that focused on solving the immediate problems were much easier to talk to than the people who wanted to rip out everything and start over.  Don’t get me wrong; sometimes you need to start over, but there is  a cost associated with that decision.  It’s usually much easier to start where you are, rather than trying to reinvent the wheel.

What’s my point?

First and foremost, don’t dwell on your past mistakes.  If you can honestly say that you built something that worked within the constraints of the time period, no matter how clunky or silly it seems now, then it was the right decision.  Working software works.  Laugh at it, learn from it, and let it go; repair what you can, when you can, but keep moving forward.

Second, learn to code naked.  Whatever it is that you’re trying to do at the moment, share it.  Open yourself up to code review, to criticism; exposure brings experience.  Granted, you’ll meet some seagulls along the way, but eventually, you’ll figure out who’s there to help you grow as a developer.  Foster those relationships.

Third, encourage people to grow; recognize that the same grace you desire for your coding mistakes is applicable to others as well.  Be kind, be gentle, but be honest; seek to understand why they made the design choices they did, and be sensitive to the fact that if it works, it works.  Sometimes we get caught up on trying to figure out the right way to do something, and ultimately end up doing nothing because it’s too difficult to implement it according to the textbook.

Life is too short to not enjoy what you do; try to share that joy without embarrassment.

THIS is the most embarrassing picture of me from that time period.  I thought being an actor was the best way to meet girls… Yes, those are tights I am wearing…

 

 

 

#SQLServer – Where does my index live?

Today, I got asked by one of my DBA’s about a recently deployed database that seemed to have a lot of filegroups with only a few tables.  He wanted to verify that one of the tables was correctly partition-aligned, as well as learn where all of the indexes for these tables were stored.  After a quick search of the Internets, I was able to fashion the following script to help.  The script below will find every index on every user table in a database, and then determine if it’s partitioned or not.  If it’s partitioned, the scheme name is returned; if not, the filegroup name.  The final column provides an XML list of filegroups (because schemes can span multiple filegroups) and file locations (because filegroups can span multiple files).

 WITH C AS ( SELECT ps.data_space_id
, f.name
, d.physical_name
FROM sys.filegroups f
JOIN sys.database_files d ON d.data_space_id = f.data_space_id
JOIN sys.destination_data_spaces dds ON dds.data_space_id = f.data_space_id
JOIN sys.partition_schemes ps ON ps.data_space_id = dds.partition_scheme_id
UNION
SELECT f.data_space_id
, f.name
, d.physical_name
FROM sys.filegroups f
JOIN sys.database_files d ON d.data_space_id = f.data_space_id
)
SELECT [ObjectName] = OBJECT_NAME(i.[object_id])
, [IndexID] = i.[index_id]
, [IndexName] = i.[name]
, [IndexType] = i.[type_desc]
, [Partitioned] = CASE WHEN ps.data_space_id IS NULL THEN 'No'
ELSE 'Yes'
END
, [StorageName] = ISNULL(ps.name, f.name)
, [FileGroupPaths] = CAST(( SELECT name AS "FileGroup"
, physical_name AS "DatabaseFile"
FROM C
WHERE i.data_space_id = c.data_space_id
FOR
XML PATH('')
) AS XML)
FROM [sys].[indexes] i
LEFT JOIN sys.partition_schemes ps ON ps.data_space_id = i.data_space_id
LEFT JOIN sys.filegroups f ON f.data_space_id = i.data_space_id
WHERE OBJECTPROPERTY(i.[object_id], 'IsUserTable') = 1
ORDER BY [ObjectName], [IndexName] 

Error 574 Upgrading SQL Server 2012 to SP1

This blog post is way overdue (check the dates in the errror log below), but I promised our sysadmin that I would write it, so here it is.  Hopefully, it’ll help some of you with this aggravating issue.  During an upgrade of our SQL cluster, we ran into the following error as we attempted to upgrade one of the instances:

2014-04-15 23:50:14.45 spid14s     Error: 574, Severity: 16, State: 0.

2014-04-15 23:50:14.45 spid14s     CONFIG statement cannot be used inside a user transaction.

2014-04-15 23:50:14.45 spid14s     Error: 912, Severity: 21, State: 2.

2014-04-15 23:50:14.45 spid14s     Script level upgrade for database ‘master’ failed because upgrade step ‘msdb110_upgrade.sql’ encountered error 574, state 0, severity 16. This is a serious error condition which might interfere with regular operation and the database will be taken offline. If the error happened during upgrade of the ‘master’ database, it will prevent the entire SQL Server instance from starting. Examine the previous errorlog entries for errors, take the appropriate corrective actions and re-start the database so that the script upgrade steps run to completion.

2014-04-15 23:50:14.45 spid14s     Error: 3417, Severity: 21, State: 3.

2014-04-15 23:50:14.45 spid14s     Cannot recover the master database. SQL Server is unable to run. Restore master from a full backup, repair it, or rebuild it. For more information about how to rebuild the master database, see SQL Server Books Online.

Google wasn’t helpful; there’s apparently lots of potential fixes for this, none of which helped.  The closest match we found was that we had some orphaned users in a few databases (not system databases), which we corrected; the upgrade still failed.  We eventually had to contact Microsoft support, and work our way up the second level technician.  Before I reveal the fix, let me give a little more background on how we got orphaned users.

You see, shortly after we upgraded to SQL 2012 (about a year ago), we did what many companies do; we phased out a service offering.  That service offering that we phased out required several database components, including a SQL login associated with users in the database, and several maintenance jobs that were run by SQL Agent.  When we phased out the service, those jobs were disabled, but not deleted.  Our security policy tracks the last time a login was used; if a login isn’t used within 60 days, it’s disabled.  30 days after that (if no one notices), the login is deleted.  Unfortunately, our implementation of this process missed two key steps:

  1. The associated user in each database was not dropped with the login (leaving an orphan), and
  2. any job that was owned by that login was also not dropped or transferred to a sysadmin.

The latter was the key to our particular situation; the upgrade detected an orphaned job even though that job was disabled, and blocked the upgrade from going forward.  Using trace flag –T902, we were able to start the server instance and delete the disabled job.  We then restarted the server without the trace flag, and the upgrade finished successfully.

 

Resources:

Find and fix all orphaned users for all databases.

Brent Ozar Unlimited’s sp_blitz will find jobs that are owned by users other than sa.