The database mirror monitor is a nice tool, but registering all your databases and clicking through each one can be time consuming when you have dozens. I want quick, easy to read results when an error comes in. If things look bad, I’ll open the monitor for a specific database to start an in depth look.
And yes, I do have reasonable alerts set up, but scripts are for proactive searching, dealing with new servers, and, most importantly, a jumping off point when an alert is generated. My normal process is:
- Read alert email
- Open multi-server query and run all the mirroring scripts below
- Investigate specific databases that are still reporting errors from the scripts
Sometimes I get to stop at step 2 because the issue has already been resolved due to a network glitch or someone else responding faster than me. I keep all the scripts saved in a single file which is always open and I run periodically.
The scripts are not as refined as I’d like, so please tweak them. They do the job when errors are coming in though. The only time I can think of any changes are when they are showing a slew of horrific errors, and at that time I just don’t have time to think about changing a script to make it prettier.
Find un-Synchronized Mirrors
Running this as a multi-server query will provide a list of all mirrored databases not currently
synchronized. This is my most used method for verifying that a mirror is still in trouble.
SELECT * FROM sys.database_mirroring WHERE mirroring_state_desc IS NOT NULL AND mirroring_state_desc <> 'SYNCHRONIZED'
Find Databases that are not Online or are Restoring
This script is a bit more specialized. I rarely get results (which is good), but it has indicated anomalies before. This will return any databases that are offline or in a restoring state, but not part of a mirror. Sometimes this indicates a test database or one left in the process of being mirrored, but at least in my environment, I never want to let a database be left in that mode for very long.
The worst scenario I’ve had with this script was a time that it found a database that had mirroring removed, so the partner had just been left in restoring state. Somehow that had been overlooked until I found it with this.
SELECT d.name ,d.user_access_desc ,d.state_desc ,m.mirroring_state_desc ,m.mirroring_role_desc FROM sys.databases d LEFT JOIN sys.database_mirroring m ON m.database_id = d.database_id WHERE (d.state_desc <> 'ONLINE' OR d.state_desc IS NULL) AND (m.mirroring_role_desc IS NULL OR m.mirroring_role_desc <> 'MIRROR')
DB Mirror Monitor Script
This mimics the database mirroring monitor. Main benefits here are you do not have to preregister every single database to the monitor and then wait for each one to refresh and click through each database. Just run the script, and apply any filters that you want. When run as a multi-server query it will automatically increment through each mirrored database.
If you want to see your entire mirroring monitor in one moment, this is for you.
The reason for this script is because sometimes I get mirrors that are still considered synchronized, but are not pushing data fast enough. They throw strange alerts, if any, when this happens. Resolving this normally involves finding out why the network is moving slowly. Ultimately there is little I can do while I wait for a fix, but it’s good to know what is going on in the meantime.
DECLARE @Mirror TABLE (database_name SYSNAME,[role] INT,mirroring_state INT ,witness_status INT,log_generation_rate INT,unsent_log INT ,send_rate INT,unrestored_log INT,recovery_rate INT ,transaction_delay INT,transactions_per_sec INT,average_delay INT ,time_recorded DATETIME,time_behind DATETIME,local_time DATETIME) -- @id will increment and pull each mirrored database DECLARE @id INT ,@db VARCHAR(256) ,@command VARCHAR(2000) SELECT @id = MIN(database_id) FROM sys.database_mirroring WHERE mirroring_guid IS NOT NULL -- Loop through each database to pull mirror monitor information WHILE @id IS NOT NULL BEGIN SELECT @db = d.name FROM sys.databases d WHERE d.database_id = @id SELECT @command = 'EXEC msdb.dbo.sp_dbmmonitorresults @database_name='+QUOTENAME(@db)+'' PRINT @command INSERT INTO @Mirror EXEC (@command) --Increment @id SELECT @id = MIN(database_id) FROM sys.database_mirroring WHERE mirroring_guid IS NOT NULL AND database_id > @id END -- Your WHERE clause/values will vary SELECT * FROM @Mirror WHERE unsent_log > 10