Wednesday, January 29, 2014

SQL Monitoring

I use a variety of methods for monitoring my database systems. Some are home grown. Others are 3rd party tools. Some look at more than SQL Server, reaching out to services and network and beyond. Some are very specific; monitoring a collection of file to ensure that imports are occurring on a regular basis.

One of the tools that I love is RedGate's SQL Monitor. I consider it my junior DBA. It is always on and always watching my systems. It lets me know when things are going awry.

With the custom metrics, I have been able to create and monitor some things that are near and dear to my heart, but are not generic enough that an alert already exists. For example, I have one custom metric that collects data about replication. Its not perfect, but the goal is to let me know when we are experiencing a particularly heavy replication period, as i may need to stay on my feet and be vigilant. Most times these periods simply pass without incident, but on occasion, in retrospect, something has gone terribly awry and one of the early indicators was heavier than normal replication business. So, thus the custom alert.

All this is to share with you some valuable information before i share the funny that I found. I was tweeking one of the alerts, and went back in time a day to see the data it had collected in the Analysis portion of the SQL Monitor tool. And the graphic representation of the data seemed to be mimicking the icon of the application itself.

 


This made me giggle and i had to share it with you.

Monday, January 27, 2014

what does a DBA do?



What I feel like I do      





  




What I really do





Just keeping the lights on

Wednesday, January 08, 2014

Full Backups, Log Backups and catching developers doing things

We all have our favorite ways to ensure that our databases are backed up. We may even have our favorite scripts, tools, and so on. Talking to someone that believes differently on this topic than you can be akin to discussion between religions or politics, with heated arguments seemingly making sense on both sides.

This is not what I want to discuss. I'm just going to share with you why I like what I like and why.

I love having individual backups for each job. This is more work for me, and is not automated. But I can create a single job for a single database and schedule it at an appropriate time. When this job fires off, i can ensure that it starts, performs its task, and completes, in a timely manner, without interruption from anything else. This takes a bit of doing and scheduling, but once done, I feel that my backups are the only thing going on at that moment, and can complete successfully. If an issue arises with a single backup, it can notify that it failed, and I know by the job name which database is having issues. Most likely the other databases are all fine, and not impeded by this single failure. This is harder to accomplish if you have shared jobs or maintenance plans, in my opinion.

So I spend the time creating individual jobs, determine the appropriate time, space these times out so that each can start and complete successfully. I also configure them to notify if a failure occurs. This coupled with other monitoring ensures that if a job fails, I know about it, soon. Knowing which one failed helps speed up the recovery.

So, that's how I like it for full backups. Single, measurable, simple. But for transaction logs, this is where I get lazy. I will often let all dbs fall to the same schedule (if possible) for tlog backups, and I will run a single job that cycles thru 'all' databases and performs the transaction log backup. I will schedule this appropriately on a db server, and let it fly.

On of the side effects to this method is that the global 'all' database approach to the tlog will fail if a certain database has not had its full backup performed already. A transaction log backup cannot happen until a full backup has occurred, and it will error. Since it cycles thru 'all' databases, this forces me to have taken all databases into account in the other method.

If I do my job, then all is well. For example, a new database needs to be stood up. I get the space needed for it, create it, size it, and so on. I then create a full backup job and find the time when it should execute. I then do nothing for tlogs, as they will automatically be backed up. Good to go.

But what about the time when someone else creates a database? Shouldn't they let the DBA know? Yes, they should, but sometimes, they do not. This is when the above scenario inadvertently helps me out. Developer X creates a new db, but doesn't perform any of the steps I usually do. No backup is created, no backup job is created, and so on. So, when the tlog job kicks off, it cycles thru 'all' databases, and encounters this one with no full backup, and freaks out, and fails and emails me.

This is when I know that a DB was created, but properly configured. In a way, its like the Database Server is tattling on the developers that created the DB without my knowledge. This lets me quietly go in, size the DB, configure it properly, create the appropriate maintenance jobs and processes for it, and get it going. I usually do this without fanfare, and simply get it setup correctly, and go back to my previous tasks. But now I know that this newly minted DB has had some TLC given to it, and will fit into my topology well.

Monday, December 02, 2013

How a patch for IE11 filled up my transaction log

The story

Our developers and QA group noticed a bug in our systems with regards to IE11. When the website was used with an IE11 browser, things didn't quite work as expected. After some research and testing, they determined that a patch could be applied to our web server that would fix IE11. It introduced some new code and some changes to the .Net framework on our web server.

So far, nothing affecting the database, right? Right! After all, they did some testing and saw that the effects of applying the patch were negligible to the test system. So, onward ho, we go!

The patch was applied one Saturday night a few weeks ago. Around 6:30 pm. I was at a basketball game with my family at the time, and noticed an alert from RedGate's SQLMonitor about a failed job. Odd I thought. (I had no idea that the patch had been applied at this point). Since it was a single job failure, I chose to continue with the family activity. An hour later, another one appeared. Another job failure. Odd. This is a simple job that is doing some simple validation of errors received from our web site services. Its never failed before.

Again, the game is almost over, and since it a once an hour job, I pushed it off a bit. When the game was over, instead of heading home, we headed to the office. My entire family. They love it, for about 5 minutes. But they bear it when it happens. In this case, we only spent an hour or so at the office. As I dig into the failed job, i realize that its a powershell script that is failing. It seems to be failing on the send email portion of the script. Duh. How lame. I could have swore that it had been tested and functioning at one point, but alas, it is failing. With some tweeking (not twerking) I get it to work, and execute it again manually. This time it sends mail. Yeah! Problem solved? No.

The email it sent me went on to describe that the errors received from the web site services had surpassed a threshold of acceptability. Oops. So a few hours ago, let's lie and say 2, I received an alert that should have told me that a threshold had been exceeded. Something bad was going on. But since the monitor couldn't email me, I didn't know the true depth of the issue.

A bit more digging finds me locating some 7k emails indicating an error I've never seen before. A short phone call later to a developer helps me see that this is a new error, and it might be associated with the patch that was applied to the web site (news i uncovered during my research of the situation). We do a quick cycle of the app pool and viola, the error stops happening in the frequency it was just bombarding us. Yeah!. Problem solved? No.

The Next Day

The next day several folks hit this issue and dig and dig and determine that the patch did something odd to the web site services, which in turn caused this new error to arise when our engines communicated from the outside world to our central services, attempting to synchronize their data with us. So, each one of the attempts failed, causing them to be told to go away and try again another day. In the meantime, the error didn't go away. It was just suppressed for a bit. It would raise again, causing the app pool to crash, and when the app pool was restarted, it would sometimes be good for a while, and other times start or continue spewing the error message email. Still, this seemed isolated from the database. Not affecting it, only in that engines were unable to connect. Some engines. Some of the time.

After more research and several days of looking, it was determined that we should roll the patch back from the system. Maybe that would revert us to the state we were in before. Maybe. How to test for this? Not a lot of confidence was given to several ideas, but the one that was picked was to increase the verbose logging on some of the services so that we could track down what was going wrong with said services as they attempted to connect and process. Yeah!. Problem solved? No.

This increased logging was applied to the web server, which is a VM, which has a small footprint. The increased logging caused some issues as it tried to write out the massive amount of logs for all the connections made that night. This caused the response to the engines to be something like "Hey, I know you tried to contact me, your central server, but I am borked right now. So, instead of accepting your data, why don't you reset your data next time we try to talk." Of course this message was editorialized, but that is the gist. Each of the engines that tried to connect and errored was told to 'reset' next time. A reset means, purge all data on central (which can be like a gig or 2 gig. maybe 5) and resend all said data. This reset process occurs all the time, from a lot of engines. It is a process that shouldn't be a bear on the topology. Usually. So as the web services did their job this night, with more verbose logging, we should have seen a fix, no? No!. Problem solved? No.

The next day was when we realized that the verbose logging caused bottlenecks on writing out all the logging, causing the engine's requests to time out, and send back the lovely error requesting a reset. This is the day before Thanksgiving. Which I had taken off as a vacation day. So I find out this information while off of work. I was informed that tons of resets may occur tonight, but everyone thinks it will be OK. No worries. Yeah!. Problem solved? No.

Thanksgiving Eve

That night, around 130am, after we had finished watching several movies as a family, I was headed to bed, and looked at my emails. Tons of emails. Tons of alerts. Tons of something hit the fan. I log into work to find that a database log file had filled up, grown to capacity on the drive, filled the drive and was basically sitting in a bad state. Other processes were still working. For example, replication was still sending data from this db server to the reporting system. Other requests were being serviced. But this db was in a bad state. Poor SQLMonitor was freaking out trying to keep up with the errors in the log about the tlog fulled up. It turned out that some 65 engines were performing resets. Right now. All at the same time. Some had finished, but others were still trying. Data was flying in and out of the system at a breakneck speed. Delete here, insert there. Tons of changes. Since it all needed to be replicated, it stuck around in the tlog longer and larger than it had ever before done. After some research, calming my beating heart, and maybe a little cussing under my breath, I add another tlog to the system on another drive, and see some pressure released, and processes continue to flow. I watch it and monitor it for an hour or so, until after 3am, and finally call it good. Things were working as expected, just a bit backed up. Several emails explaining the situation were sent out to the team, mainly to document what was going on, what I had found, and making sure others knew what was happening in realtime. I then decided to go to bed. Yeah!. Problem solved? No.

Around 5 am I awake and check my mail only to find out that just before that time, the replication database log file had filled up as well. It didn't fill the drive, but was 100% full, and things were halted. Fearing that I would have to rebuild replication in a few days, or worse, over the holiday, I got up, and drug my self downstairs to see what I could do with my magic DBA pixie dust. After reviewing things, looking at the state of several pieces of the puzzle, I created another log file on another drive for the distribution database. I double checked the status of the other log file, to find out that it was doing fine. Replication was backed up, and latent. But it started flowing again. It was like finding those pesky beavers had built yet again another dam across my river of data. Once the river was diverted, flow occurred. Yeah!. Problem solved? At this point, its 6am the morning of a major holiday, and I have no idea. It looked good at the moment. But would take a while to catch up. After watching a bit, I went to bed.

I slept in until after 10am on Thanksgiving morning. When I awoke, I grabbed my phone and looked, and viola, all seemed well. There was even an apology from the developer that had spearheaded the movement to rollback the patch, increase the logging, and see what happens. Well, we now know what happens. We can potentially affect systems and services to the point that they get blocked up way upstream, causing untold blockage down the river of our data, and inadvertently cause database problems.

What did I learn?

This was a perfect storm situation that I had not planned for. What can i take from this experience? What can I learn from it and do better?


  • I had sized the log files and drives appropriately, at least as far as normal processing occurred and the baseline of normality allowed me to measure. But in this situation, more log file size, and a bit of a larger disk, would have been the preferred configuration. Something I need to look into. 
  • I was happy that I had planned on having extra luns attached that were unused for Data and Log, in the case of an emergency. Since these already existed, and had space, I could easily add files to dbs and sit them on these drives, which are raring to go. This saved a lot of heartache and pressure. The solution was easily reached in both cases, and when things settled down to normal, the extra log files were removed, returning the drives to their emergency waiting state again. 
  • I also realize that for some types of alerts, it would be better if a more noisy alert occurred. When the db log file first filled up, it was around 11pm. I noticed it at 130am. I could have fixed it a lot earlier, had i been properly notified. I need to fix this. 
  • We all need to be more careful about touching our production system. Something as simple as an IE11 patch to a webserver was ultimately responsible for the log file filling up. If we could have tested this much better, in conjunction with the rest of the services, and not just assuming that this patch would affect a website, that it could reach into services that could cause errors to spew, and pile up too many errors and logging which could ultimately affect data coming in, etc. etc. If, If, If. We have to be better at seeing and planning for the If situations, and not be overly cautious that it causes us to freeze in our tracks and not let any change occur.
  • As smart as we all are individually and collectively, there is still much to be learned, even about our system that we have created and believe to know intimately. 



Monday, September 23, 2013

Thoughts about the SQL PASS Board of Directors Voting 2013

Volunteering is a special kind of madness that many humans suffer. They continue to give of their time to volunteer to perform tasks and duties that they would normally not do. All this in the valiant effort to make their sphere of the world a little better by their wake of work. Some humans continue to do this over and over, with little recompense. Still others rise above the rest and want to stand out as targets. Often they promote themselves or become elected to be these targets, and  while ofttimes tripling or more their volunteer efforts, continue to give and give and give. These are they that run for the board of directors for almost any organization. They will stand out, at the head of this organization, make decisions that will be possibly helpful or hurtful to the organization as a whole or even individuals. They will continue to move forward working, doing, deciding and so on, until they are either done, get kicked out, or their terms expire. All the while, they are doing what the rest of us may be afraid to do; to work hard, in the face of obstinate obstacles, trying their darnedest to do a good/great job and leave behind them a better organization than when they entered.
I must believe that they all want the best, and they all try to do the best of their abilities, and they do what most of the population of the group would rather not do, the hard stuff, the difficult decisions, the long nights, the excessive back and forth discussions attempting to create a better place than yesterday. I must believe they do this. For the betterment of all, including themselves.

So, go and figure out who among the slate of this years volunteers you want out front doing the jobs that you don't want to do, and lets get behind them, let's support them, let's buoy them up when they need it, and even when they don't. Let's get behind them and help them help us be a better organization.

And remember, we'll do this again in a few years, when a new batch comes along, with a new set of ideas and goals, and the ones that are volunteering now have all but spent their last breath of energy trying, and trying to improve this place we all call PASS.


Wednesday, August 21, 2013

Permissions by user

I have a script that I have tweeked and tweeked over the years that offers me a quick view into what objects have specific permissions on them per user. I have used this oft times to audit systems and prove that things are the way they should be, or to possibly generate work when they are not.

The output of this little script is the servername, databasename, username, grantor, object type, object name, and the permissions (like grant select, or deny execute).

I have used this script in the past to generate a source and destination table, and then run compares on the two outputs to see what is different between two systems that should be identical. But this version below is just a quick and raw output.

I hope that this helps.





DECLARE @MyDBName sysname
 SET @MyDBName = '#Source'
 
 IF EXISTS (SELECT * FROM tempdb..sysobjects WHERE ID = Object_ID('tempdb..#permissions') )
  DROP TABLE #permissions
 
 CREATE TABLE #permissions
 (
  [qid] [int] IDENTITY (1,1) NOT NULL,
  [ServerName] varchar(150) NOT NULL,
  [DatabaseName] varchar(150) NOT NULL,
  [UserName] sysname NOT NULL,
  [Grantor] sysname NOT NULL,
  [ObjectType] varchar(60) null,
  [ObjectName] sysname null,
  [PermissionState] varchar(60) null,
  [PermissionName] varchar(128) null
 )
 
 
 
 set NoCount on
 
 declare
  @result int,
  @ErrorMsg varchar(500),
  @execStr nvarchar(4000),
  @Version int
 
   --cycle thru the databases in this server, and retrieve the dbnames of each
   declare GetDataCursor insensitive cursor
    for
        select
       name
         from sys.sysdatabases
 --      where name not in ('Audit', 'tempdb')
 --         and status not in ( 48, 528)
 --      where name in ('Master', 'MSDB')
       Order by name
 
   if @@Error <> 0 goto ErrorProc
   --try
 
    declare
     @DBName varchar(200)
 
    open GetDataCursor
    if @@Error <> 0 goto ErrorGetDataCursor
    while 0 = 0
    begin
     fetch next from GetDataCursor into
      @DBName
 
     if @@Error <> 0 goto ErrorGetDataCursor
     if (@@Fetch_Status = 0)
     begin
 
      Set @execStr = '
       INSERT INTO #permissions ( [ServerName],[DatabaseName],[UserName],[Grantor],[ObjectType],[ObjectName],[PermissionState],[PermissionName])
        SELECT
          @@ServerName AS [ServerName],
          --DB_NAME() AS [DatabaseName],
          ''' + @DBName + ''' AS [DatabaseName],
          u.name AS [UserName],
          u2.name AS [Grantor],
          CASE
           WHEN major_id > 0 THEN o.type_desc
           ELSE ''System Object''
          END AS [ObjectType],
          CASE
           WHEN major_id > 0 THEN o.name COLLATE DATABASE_DEFAULT
           ELSE o2.name
          END AS [ObjectName],
          dp.state_desc AS [PermissionState],
          permission_name as [PermissionName]
         FROM [' + @DBName + '].sys.database_permissions dp
          LEFT OUTER join [' + @DBName + '].sys.database_principals u on dp.grantee_principal_id = u.principal_id
          LEFT OUTER join [' + @DBName + '].sys.database_principals u2 on dp.grantor_principal_id = u2.principal_id
          LEFT OUTER JOIN [' + @DBName + '].sys.objects o ON o.object_id = dp.major_id
          LEFT OUTER JOIN master.sys.sysobjects o2 ON o2.id = dp.major_id
         WHERE class = 1
          AND dp.grantee_principal_id > 0
         ORDER BY [UserName], [ObjectType], [ObjectName], [PermissionState], [PermissionName]'
 
 --      Print @execStr
      exec @Result = sp_executesql @execStr
      if @@Error <> 0 or @Result <> 0
      begin
       set @ErrorMsg = 'Error occurred retrieving data for 1st query'
       goto ErrorGetDataCursor
      end
 
     end
     else
      break
    end
    goto SuccessGetDataCursor
 
   --except
    ErrorGetDataCursor:
    deallocate GetDataCursor
    goto ErrorProc
 
   --finally
    SuccessGetDataCursor:
    deallocate GetDataCursor
   --end
 
   SELECT * FROM #permissions
 
  --finally
   SuccessProc:
 
  --except
   ErrorProc:
   
   

Friday, March 22, 2013

SLC Code Camp 2013

Tomorrow morning I will be presenting on 'Release Management' at the Salt Lake City Code Camp. I was one of the lucky ones that was selected by the community to present a session at this event.

This is a presentation that I have tailored after the chapter I was honored to write in a SQL Server 2012 book recently. This is a topic that has been close to my heart and part of my day to day job for quite some time. It was fun to prepare this session for a not exclusively SQL Server audience. I am a bit nervous about it, as I usually am before any presentation.

I have uploaded my preso and supporting files to my public Dropbox. You can find the links here.

LINK to Presentation Files



Tuesday, March 05, 2013

What do you do when you hit the finish line?

Do you ever find yourself at the endgame of a task, only to not know what to do next? Having never thought that you would actually end up here? Sometimes it takes so long to get there and the journey is so arduous, that you forget the goal is not the work to accomplish the task. But to complete the task.

Let's say you have a problem that seems persistent and invasive. Its always on your mind. You try this and that to surmount it, only to be stymied each time. Each attempt results in a failure, at least with the the end goal not being reached. Maybe each iteration discovers a bit more information about the problem that helps you attack it in a different direction. Maybe each iteration shows you that what you thought would solve it did not, and you simply need to revisit the drawing board. But along the way you, either consciously or unconsciously, have relegated yourself to some form of failure. Such that you now get stuck in the mire of simply attacking the formidable wall over and over with all your might, with little to no result.

I believe that we all find ourselves here on occasion. Either by our own hand or by that of others or even the simple fact that the universe seems completely against our progress. What happens to me on these occasions varies. I often will reattack with a renewed vigor, trying to think outside the box. I have been known to assemble folks and discuss and throw down the gauntlet of challenge to these others to assist me, see it from another set of eyes, find flaws in my logic, approach or tactics. I have even given up. But I believe that the one thing I almost always do, once mired in the clutches of this inability to progress forward, I forget the end game. I forget the goal. I forget the tasks I need to accomplish after this task is complete. I see no end in sight, and become shortsighted to the point that nothing else exists but the eventual success of this problem.

So, when it miraculously occurs, the often sought after success, the end goal of accomplishment, I stand there, as if I were the last one left on the battle field, unsure of what to do next. Not even realizing that I had reached my destination, not able to enjoy the moment of success.

To this end I direct these comments. Envision the moment of success. Plan for it, work towards it, and recognize it when it actually reaches your shores. Take a moment to enjoy it. Regale yourself with whatever treats you deem appropriate. Celebrate the moment. But more importantly, envision what it will look like so that when you reach it, or it reaches you unexpectedly, you will recognize it.

This is what you worked for, and it's sad to me when I reach it, but am so in the trenches that I do not properly realize that its here. That I made it. That I accomplished it. That its finished. Over. Done.

Instead of letting the moment slip past you, plan for it and recognize it when it overcomes you. Enjoy it!

Then move onto the next success moment. How many can you rack up? Now that I've written this, I'm onto the next one. Thanks for listening and letting me express my latest success moment.

Tuesday, February 12, 2013

Habits

Its a new year. Well, it was a new year not too long ago. Often with the new year people start talking about resolutions. Goals. Changes. All fine and dandy if you ask me.

Most of these involve doing this or that more than last year. Like exercise, eating healthy, visiting family and friends, etc. All worthy goals to have, I say.

But as I was driving in to work this morning, I reflected on those things that we do that may not be great for us. They may not be bad, but not great. Or a better way of looking at them is the contrast between Good, Better and Best. We may be doing some thing good, but instead of doing better or best, we settle with good.

So, I challenge you to find something in your life that you do now, something that is not huge, but pervasive, and stop doing it. Or change the good for a better or best version of the activity.

For example, do you find yourself surfing Facebook at night, or in the morning or during the day? I am not saying that this is a bad activity, but if you consistently find that this has worked itself into your routine, why not alter it? Do it differently, or maybe not at all. Spend some time connecting, instead of just reading what others have done. Try it out. See if making a change like this is better or best for your routine. Maybe you do not use it at all, Facebook that is, and the challenge could be to stretch out and use it more. I'm suggesting find something that you do and do it better or best, or even yank it out of your life entirely.

Another example is water. How much water do you drink? Is it enough? What could you do to drink more?

What about food? Do you find yourself eating out often? More often than you should? Step back, analyze, and change the habit drastically. For a small period of time. Enough time that the activity no longer has a hold on you.

How about flossing your teeth? Do you floss often enough? What can you do to do it more often? It will require a drastic change to your routine. A break of an existing habit, and an additional activity added to the habit.

Want to tie it to your works with databases? Why not? Find something that you do not do often enough, and step it up. Force yourself to incorporate it into your habits and activities. Again, often enough that it is a grand difference to your schedule and routine. Or maybe you need to remove something from your routine. Either way.

I challenge you to find the thing you will remove, or add more frequent and better or best actions to be performed. Incorporate this into your routine, or remove it from your routine. Continue with this for a small period of time, and measure the results on the other side. Challenge released.

If you accept the challenge, regardless of outcome (positive/negative) please let us all know what you did by adding to the comments so we can see examples.

Now, go to, alter your life, in a small way, and better yourself for it!

Monday, February 11, 2013

Updated speaking/articles/book


Speaking Engagements
User Groups
Utah User Groups June 2005 Reporting Services
Utah User Groups August 2005 Profiler / Trace
Utah User Groups February 2006 Sarbanes-Oxley
Utah User Groups January 2008 Query Processing
Salt Lake City User Group 2004-2008 various topics
Utah County User Group 2006-2008 various topics


Code Camps
Salt Lake City Code Camp October 2006 Profiler / Trace
Salt Lake City Code Camp April 2008 Query Processing
Salt Lake City Code Camp November 2008 Query Processing
Salt Lake City Code Camp November 2013 Release Management


Miscellaneous
Microsoft 2006 Analysis Services
ACS 2006 Sarbanes-Oxley
PASS SIG 2007 Some topic


SQL Server World Wide User Group Virtual Conference
SSWUG vConference April 2009 Auditing your users
SSWUG vConference April 2009 Best Practices
SSWUG vConference April 2009 Job Execution System
SSWUG vConference April 2009 Monitor Index Fragmentation
SSWUG vConference April 2010 Configuring and Managing GoldenGate
SSWUG vConference April 2010 Database Switch
SSWUG vConference April 2010 SQL Server Profiler and Tracing
SSWUG vConference October 2010 Database Change Process
SSWUG vConference October 2010 On Call Duties
SSWUG vConference October 2010 Professional Development
SSWUG vConference October 2010 SQL Server Logical Query Processing
SSWUG vConference April 2011 Data File Sizes
SSWUG vConference April 2011 Documentation – you know you love it
SSWUG vConference April 2011 Server Profiler and Tracing, a “How To”
SSWUG vConference April 2011 Stand-alone DBA dailyweeklymonthly


SQL Saturday
SQL Saturday 54, Salt Lake City       October 2010     Database Switch
SQL Saturday 54, Salt Lake City       October 2010     SQL Server Profiler and Tracing

SQL Saturday 66, Colorado               February 2011    Documentation – you know you love it
SQL Saturday 94, Salt Lake City       October 2011     Data File Sizes
SQL Saturday 94, Salt Lake City       October 2011     Documentation – you know you love it
SQL Saturday 97, Austin                    October 2011     Data File Sizes

SQL Saturday 104, Colorado Springs January 2012      Utility Belt Pre-Con
SQL Saturday 154, Salt Lake City      October 2012      Release Management

SQL Saturday 183, Albuquerque         February 2013    Release Management
SQL Saturday 190, Denver                  September 2013 Documentation

SQL Saturday 246, Salt Lake City      September 2013  Database Monitoring
SQL Saturday 249, San Diego            September 2013  Database Monitoring
SQL Saturday 249, San Diego            September 2013  Documentation

SQL Saturday 279, Phoenix                February 2014     Documentation
SQL Saturday 279, Phoenix                February 2014     Release Management
SQL Saturday 295, Las Vegas            April 2014           Database Monitoring
SQL Saturday 297, Colorado Springs April 2014           Documentation
SQL Saturday 349, San Diego            September 2014   Documentation


SQL Saturday 349, San Diego            September 2014   Database Monitoring
SQL Saturday 349, San Diego            September 2014   Release Management


SQL RALLY 

Dallas Texas, May 2012 All Day Pre-Con with co-presentor Chris Shaw,
        How to be a DBA - A Utility Belt of Tools



Articles

SQLServerCentral.com
On-Call Duties – 27 Oct 2008
A Simple DR Solution – 31 July 2008
Job Execution System – 27 Mar 2008

Simple-Talk.com

SQLServerPerformance.com
Automate Audit Requests - 26 May 2008
Audit Data Modifications - 15 Apr 2008


Books

Apress
Pro SQL Server 2012 Practices  link


--updated 9/24/2014