Showing posts with label Database. Show all posts
Showing posts with label Database. Show all posts

Friday, March 16, 2018

The Microsoft Exchange Mailbox Replication service was unable to process jobs in a mailbox database - EventID 1006

After deleting a mailbox database from Exchange 2013 in one of my test environment, I was getting the following warning in the Application log of the server hosting that database:
Log Name:      Application
Source:        MSExchange Mailbox Replication
Date:          3/13/2018 7:16:44 AM
Event ID:      1006
Task Category: Service
Level:         Warning
Keywords:      Classic
User:          N/A
Computer:      server.domain.com
Description:   The Microsoft Exchange Mailbox Replication service was unable to process jobs in a mailbox database.
Database: Missing database (a435e9be-b010-400d-9d56-659065d6c9df)
Error: Database 'a435e9be-b010-400d-9d56-659065d6c9df' doesn't exist.

After running the cmdlet below, I confirmed that the database mentioned in the warning didn’t exist (so it was safe to assume it was the one I deleted):
Get-MailboxDatabase | FT Name, GUID -Auto

Most of the times, you can resolve this by simply restarting the Microsoft Exchange Mailbox Replication service or the Information Store service. Alternatively, rebooting the server will stop the warning since all the required services will be restarted.

Saturday, March 11, 2017

Exchange DAG Replication Port

Have you ever wondered what TCP port Exchange 2010/2013/2016 uses for database replication (log shipping and seeding)? That would be 64327 by default.

This can be checked using the Get-DatabaseAvailabilityGroup cmdlet:

Administrators can also change this default port is they so desire by using the Set-DatabaseAvailabilityGroup cmdlet with the -ReplicationPort parameter.
If you decide to do so, it is recommended to create a new Windows Firewall rule for the new port on all DAG members before the actual change to avoid any disruption to database replication. After the change, the existing firewall rule can then be deleted or updated (depending on the approach taken):

Friday, February 3, 2017

Disk space missing from Exchange LUN

I was recently troubleshooting an issue where the LUN disk space for one particular Exchange database kept reducing by around 3GB a day, even though the database had plenty of whitespace for use:
 
Looking at the properties of the mount point, I could see there was indeed 80GB left of free space, so the previous report was accurate:
 
However, looking at how much the Exchange database and log files were taking, there was supposed to be over 200GB free space!
 
 
After some digging around, it turns out this space was being used by Volume Shadow Copies. Using vssadmin tool, I could see 122GB being used by VSS (Volume Shadow Copy Service) for MDB11:

By listing all the shadows, we can check when this shadow copy was created. In my case, it was over a month’s old:
 
We can also get details regarding shadow copies on Windows servers by using a hidden utility named vssuirun.exe:
 
It turns out that this particular server was rebooted mid-backup, causing this orphaned shadow copy. Since all the backups were working, I could safely delete this shadow copy. To do this, I tried using the "vssadmin delete shadows /all" command to delete it, but received the following error:
Error: Snapshots were found, but they were outside of your allowed context. Try removing them with the backup application which created them.”
 
Despite being logged in as an admin, Windows won’t let me touch the shadow copy. Or better put, VSSadmin doesn’t like messing with snapshots taken by other applications. Enter DiskShadow, a “tool that exposes the functionality offered by the Volume Shadow Copy Service (VSS).” Using diskshadow we can double-check the shadow copy details we got with vssadmin:
 
 
To delete all shadow copies using diskshadow, we can run "delete shadows all" or, if we want to delete only a particular one (not relevant in this case as there was only one copy), we can specify the ID of the shadow copy we want to delete:
 
Once it has been deleted, we can confirm there are no more shadow copies lying around using DiskShadow:
 
Or using VSSadmin:
 
As expected, the space was then recovered :)

Saturday, April 23, 2016

Monitor Mailbox Database Transaction Logs

Excessive database and/or transaction log growth is, unfortunately, not an uncommon problem in Exchange deployments. On top of being hard to troubleshoot, if it is found too late, it can cause serious issues for users and even the business. As such, it is crucial to have an adequate monitoring solution. However, this is not the case in every single organization, so I decided to write a basic script to keep an eye on the number of logs being generated across databases.
 
You can, for example, run the script every hour and if any database currently has more logs than a specified threshold, it sends an alert by email with the number of transaction logs for all databases, highlighting the one(s) that triggered the alert, and the current free space for the database (you might need to update it depending on whether you have the .edb file and logs on the same or different locations).
 
The script simply counts all files in the LogFolderPath location (variable for each database) as this makes it quicker than only looking for *.log files, and still be accurate for what we want to achieve.

You can download the complete final script from the TechNet Script Gallery.

Thursday, April 21, 2016

Mailbox Database Seed Status

Seeding large mailbox databases can potentially take a long time. Although it is something that usually does not need to be monitored, it is always good to keep an eye on it to see how it is doing. The Get-MailboxDatabaseCopyStatus cmdlet gives us all the information we need for this.

Usually I use this cmdlet in the following format to ensure the mailbox database copies on a particular server are mounted and/or healthy:
Get-MailboxDatabaseCopyStatus -Server "server_name" | Sort Name


But we can use it to get further details for a particular mailbox databases (the following output has been shortened to only include the most relevant information for this tip):

[PS] C:\>Get-MailboxDatabaseCopyStatus “MDB01\EXAIO” | FL

Identity : MDB01\EXAIO
DatabaseName : MDB01
Status : Seeding
MailboxServer : EXAIO
ActiveDatabaseCopy : EXMBX01
ActiveCopy : False
ActivationPreference : 3
IsLastCopyAvailabilityChecksPassed : False
LastCopyAvailabilityChecksPassedTime :
IsLastCopyRedundancyChecksPassed : False
LastCopyRedundancyChecksPassedTime :
ActivationSuspended : True
ContentIndexState : FailedAndSuspended
ContentIndexErrorMessage : Reseeding of the index is required.
ContentIndexErrorCode : 22
CopyQueueLength : 718053
ReplayQueueLength : 0
ReplicationIsInBlockMode : False
ActivationDisabledAndMoveNow : False
AutoActivationPolicy : Unrestricted
ReplayLagStatus : Enabled:False; PlayDownReason:None; Percentage:0; Configured:00:00:00;
Actual:00:00:00
DatabaseSeedStatus : Percentage:33; Read:95.19 GB; Written:95.19 GB; ReadPerSec:23.65 MB; WrittenPerSec:23.67 MB

DiskFreeSpacePercent : 60
DiskFreeSpace : 434.7 GB (466,730,405,888 bytes)
DiskTotalSpace : 717 GB (769,869,737,984 bytes)
DatabaseVolumeMountPoint : E:\Mount\edb09\
LogVolumeMountPoint : E:\Mount\edb09\



If we are particularly interested on the progress of the seed operation, we can filter the above output to only include what we want:
(Get-MailboxDatabaseCopyStatus “MDB01\EXAIO”).DatabaseSeedStatus

Sunday, November 29, 2015

Identifying IIS Worker Process in Exchange 2013/2016

It might come a time when troubleshooting performance issues where we need to identify exactly what a particular IIS Worker Process is in an Exchange 2013 environment:


First thing we need to do is get the Process ID (or PID). To do this, right-click on one of the columns and select PID:


We can now see that that PID for the IIS Worker Process we are trying to identify is 10300:


Now open a Command line or PowerShell console, navigate to Windows\System32\Inetsrv and then run the command “appcmd list wp” or “.\appcmd list wp” if you are using PowerShell:


We now know that the IIS Worker Process with the PID of 10300 is the Exchange OWA Application Pool.

Friday, September 25, 2015

How to determine which store worker process is responsible for which mailbox database?

As we all know by now, the Exchange Store service in Exchange 2013 has been rewritten in such a way that each database now runs under its own process, thus preventing store issues to affect all databases in the server. Managed Store is the new name for the rewritten Information Store process (store.exe). It is now written in C#, designed to enable a more granular management of resources (additional I/O reduction, for example) and is even more integrated with the Exchange Replication service (MSExchangeRepl.exe), in order to provide a higher level of availability.

The database engine continues to be ESE, but the mailbox database schema itself has changed in order to provide many optimizations.

The Managed Store is composed of two processes. The first one is the Store Worker Process (Microsoft.Exchange.Store.Worker.exe) that is similar to the old store.exe process. The difference is, as already mentioned, that there is one Store Worker Process for each database. This means that if one of these processes fails, only the database it is responsible for will be affected, while all the other databases will remain operational.

The second one is the Store Service Process (Microsoft.Exchange.Store.Service.exe) that controls all store worker processes. For example, when a database is mounted, the store service process will start a new store worker process for that particular database. On the other hand, when a database is dismounted, it will terminate the store worker process responsible for that database.

The question that sometimes arises is “how do we determine which store worker process is responsible for which mailbox database?” To show how to do this, I am going to use a test server where I have 2 mailbox databases, and therefore two Microsoft.Exchange.Store.Worker.exe):


First thing we need to do is get the Process ID (or PID). To do this, right-click on one of the columns and select PID:
 
 
We can now see that that PID for the store worker we are trying to identify is 3308:
 
Now open an Exchange Management Shell console and run the following cmdlet:
Get-MailboxDatabase -Status | Sort Name | FT Name, WorkerProcessID


 
We now know that the store worker process with the PID of 3308 is responsible for the mailbox database DB01.

Tuesday, September 9, 2014

Clean-MailboxDatabase in Exchange 2013

In Exchange 2007 and 2010 we had the Clean-MailboxDatabase cmdlet to get disconnected mailboxes visible in the GUI without having to wait for the maintenance schedule.

However, in Exchange 2013 this cmdlet no longer exists but the same problem persists: disconnected mailboxes are not visible immediately after being removed or disabled.... Clean-MailboxDatabase has been replaced by Update-StoreMailboxState, which forces the mailbox store state in the Exchange store to be synchronized with Active Directory.

Its syntax is as follows:
Update-StoreMailboxState -Database “DatabaseIdParameter” -Identity “StoreMailboxIdParameter” [-Confirm [SwitchParameter]] [-WhatIf [SwitchParameter]]

Both the –Database and –Identity parameters are required, meaning we need to know the identity of the mailbox (mailbox GUID) that we want to update the store state for. To do so, we can run the following cmdlet for example:
Get-MailboxDatabase | Get-MailboxStatistics | Format-List DisplayName, MailboxGuid, Database, DisconnectReason, DisconnectDate

Once we know the mailbox’s GUID and in which database it was located, we can update its mailbox state by running:
Update-StoreMailboxState -Database “db_name” -Identity “mailbox_guid”

If we want to update the mailbox state for all mailboxes on a particular database, we can adapt the cmdlet to:
Get-MailboxStatistics -Database “db_name” | ForEach {Update-StoreMailboxState -Database $_.Database -Identity $_.MailboxGuid -Confirm:$False}

Finally, if we want to just update the mailbox state for all disconnected mailboxes on a particular database:
Get-MailboxStatistics -Database “db_name” | Where {$_.DisconnectReason -ne $null } | ForEach {Update-StoreMailboxState -Database $_.Database -Identity $_.MailboxGuid -Confirm:$False}

To be honest, I am not sure why this change from Clean-MailboxDatabase to Update-StoreMailboxState. The only reason I can think of is to give administrators the possibility to just update the state of a single mailbox instead of having to update an entire database.

Wednesday, August 27, 2014

Exchange 2013 Loose Truncation

Loose Truncation is a new feature that was introduced in Exchange 2013 Service Pack 1. Its purpose is to prevent possible disk space issues that can occur in environments with DAGs when one or more copies of a database is offline for an extended period of time. When enabled, loose truncation changes the “normal” truncation behavior. Each database copy tracks its own free disk space and starts to truncate transaction log files independently if the available disk space falls behind a set threshold configurable by the administrator.

To continue reading, please check the full Exchange 2013 Loose Truncation article at MSExchange.org.

Thursday, July 10, 2014

Database Availability Group Failover during a Mailbox Move

During a mailbox move operation if the active database becomes unavailable then the Mailbox Replication Service [MRS] contacts the active manager to see which copy will take over. MRS then logs on to the mailbox on the new database and continues with the move process from where it left off. This as long as the DataMoveReplicationConstraint setting for the database is set to something else other than None and as long as the database was not down for longer than 30 minutes (or there is another copy satisfying the constraint).
 
Let us assume the database has 3 copies. It is entirely possible that MRS will just continue working after a failover even if the original server is down.
 
If DataMoveReplicationConstraint is set to None then MRS will try to connect to the same database every 30 seconds for the next 30 minutes. The 30 minute is from the maximum retry of 60 times every 30 seconds. This value can be changed in the in the msExchMailboxReplication.exe.config file.
 
The DataMoveReplicationConstraint parameter specifies the throttling behavior for high availability mailbox moves. The possible values are:
  • None: moves should not be throttled to ensure high availability. Use this setting if the database is not part of a DAG;
  • SecondCopy (default): at least one passive mailbox database copy must have the most recent changes synchronized. Use this setting to indicate that the database is replicated to one or more mailbox database copies;
  • SecondDatacenter: at least one passive mailbox database copy in another AD site must have the most recent changes replicated. Use this setting to indicate that the database is replicated to database copies in multiple AD sites;
  • AllDatacenters: at least one passive mailbox database copy in each AD site must have the most recent changes replicated. Use this setting to indicate that the database is replicated to database copies in multiple AD sites;
  • AllCopies: all copies of the database must have the most recent changes replicated. Use this setting to indicate that the database is replicated to one or more mailbox database copies.
 Note: any value other than None enables MRS to coordinate with Active Manager.

Sunday, August 4, 2013

Error Deleting Database "Failed to remove monitoring mailbox object"

When removing databases from Exchange 2013, you might get the following error if the correct procedures are not followed:
Failed to remove monitoring mailbox object of database “database_name”. Exception: Active directory operation failed on “server_name”. This error is not retrievable. Additional information: Access is denied. Active directory response: 000000005: SecErr: DSID-031520B2, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0.


In this case, the database was removed an Active Directory [AD] error (with a not very useful description) complaining about insufficient permissions is thrown. If you run:
Get-Mailbox -Monitoring

You will most likely see a warning regarding a corrupted Health Mailbox:
WARNING: The object “domain_name”/Microsoft Exchange System Objects/Monitoring Mailboxes/”Health_Mailbox_GUID” has been corrupted, and it's in an inconsistent state. The following validation errors happened: WARNING: Database is mandatory or UserMailbox.


Because Exchange 2013 did not have sufficient permissions to the domainname/Microsoft Exchange System Objects/Monitoring Mailboxes Organizational Unit [OU], it could not delete the AD objects related to the database’s health mailboxes. In this case, the database attribute is null because the database the health mailbox references no longer exists.

To fix this issue, simply delete the health mailboxes referenced by the error(s) from that OU by using Active Directory Users and Computers. After removing these, the warning should be gone.


Deleting health mailboxes is a low risk procedure because they will be automatically re-created by the Microsoft Exchange Health Manager service on the Exchange 2013 server hosting the database when this service is restarted.

Tuesday, July 2, 2013

Exchange 2013 “Please restart the Microsoft Information Store service”

With Exchange 2013 Cumulative Update 1, administrators will notice that every time a new database is added, they are prompted to restart the Information Store service. Although this was also true in Exchange 2013 RTM, the difference was that before administrators did not receive this restart warning.
 
As we saw previously, Exchange 2013 introduced the new Managed Store, which uses a different memory management model than previous editions of Exchange. With a Store Worker Process for each active and passive database present on a server, it is now required to restart the Information Store service because the Store only determines the amount of memory that it will use to manage each database when it starts (which happens when the server starts or when the Information Store service is restarted).
 
In previous editions, Exchange typically seizes as much memory as it is available on a server and uses that memory to cache Store data. In Exchange 2013 this approach was revised and it now calculates how much memory it should use and makes it available to worker processes (obviously active databases are assigned more memory than passive databases). However, this new memory management approach depends on knowing how many worker processes are in use. When databases are added from a server, the Store does not re-calculate the amount of RAM for each worker process dynamically. This does not mean that you cannot mount the new database – it means caching will not be as efficient as it should be until the next time the Store process restarts and memory use is adjusted.

This might be seen as a big drawback of Exchange 2013, and it might even change in the future, but adding or removing databases should not happen that often, so the impact should not be that massive.

Thursday, June 13, 2013

Update-MailboxDatabaseCopy in Exchange 2013 CU1

The Update-MailboxDatabaseCopy cmdlet is used to seed or reseed a mailbox database copy. Seeding is the process in which a copy of a mailbox database is added to another Mailbox server, thus becoming the database copy into which copied log files and data are replayed. This cmdlet can also be used to seed a content index catalog for a mailbox database copy.

In Exchange 2013 CU1 this cmdlet includes some new parameters that are designed to aid with automation of seeding operations. These parameters include:
  • BeginSeed – this is useful for scripting reseeds. With this parameter, the task asynchronously starts the seeding operation and then exits the cmdlet;
  • MaximumSeedsInParallel – this is used with the Server parameter to specify the maximum number of parallel seeding operations that should occur across the specified server during a full server reseed operation. The default value is 10;
  • SafeDeleteExistingFiles – this is used to perform a seeding operation with a single copy redundancy pre-check prior to the seed. Because this parameter includes the redundancy safety check, it requires a lower level of permissions than the DeleteExistingFiles parameter, enabling a limited permission administrator to perform the seeding operation;
  • Server – this is used as part of a full server reseed operation to reseed all database copies in a Failed and Suspended state. It can be used with the MaximumSeedsInParallel parameter to start reseeds of database copies in parallel across the specified server in batches of up to the value of the MaximumSeedsInParallel parameter copies at a time.

Remember that you must suspend a database copy before you can update it using the Update-MailboxDatabaseCopy cmdlet.

Sunday, February 3, 2013

Exchange 2013 Automatic Reseed

Microsoft has made great improvements in Exchange 2013, some of these around Database Availability Groups [DAGs]. For example, it is now possible to reseed a database from multiple sources, greatly reducing the overall time this operation usually takes. Another improvement, in this case a new feature, is called Automatic Reseed, or simply AutoReseed.

With Exchange 2010, if you lose the disk where your database is (either active or passive), Exchange will failover that database to another server (assuming it is part of a DAG with multiple copies). After that, an administrator will typically replace the faulted disk and reseed the database back to that server. This, of course, in scenarios where resilience through RAID or enterprise-level storage is not provided, which would cater for disk failures.

The purpose of AutoReseed is to overcome this situation and automatically restore database redundancy by using spare disks provisioned specifically for this. All it involves is pre-mapping volumes and databases using mount points that will be used for the databases and the reseed operation. In a simplistic way:
  1. Mount all volumes (used for databases and as spares) under a single mount point, C:\ExchangeVolumes for example;
  2. Mount the root directory of mailbox databases as another mount point under C:\ExchangeDatabases for example. Next, create two directories for each database: one for the database itself and another for the log files;
  3. Finally create the database(s).

 
Here is AutoReseed process flow:
  1. The Exchange Replication service periodically scans for database copies that have a status of FailedAndSuspended;
  2. If one is found, it does pre-requisite checks like checking if spare drives are available and ensuring nothing might prevent Exchange from automatic reseeding the database;
  3. If all the checks pass, the Replication service allocates and remaps a spare drive;
  4. Seeding is performed;
  5. Once seeding is complete, the Replication service checks if the seeded copy is healthy.

All an administrator needs to do now is simply replace the faulty disk and reconfigure it as a spare for the DAG!

To read all about this new feature and how to implement it, please check the article at MSExchange.org.

 

Thursday, January 17, 2013

Exchange 2013 Database Mount Limit

A change introduced in Exchange 2013 that many administrators are not aware is the fact that with the Enterprise Edition of Exchange, you can now only mount up to 50 mailbox databases per server, a reduction in 50% from the 100 with Exchange 2010! The limit of the Standard Edition remains at 5 databases.

Highly available and resilient environments might have some problems when migrating from Exchange 2010 if they have servers with more than 50 databases (in big environments with 3 or 4 copies of each database it is not that uncommon). Therefore, a complete review of the current database layout might have to happen.

But why this change?! Basically it was introduced in order to ensure a good performance from the mailbox servers. Some of the reasons behind this change are the improvements made in some areas, which mean the mailbox servers consume more memory now... For example, Exchange 2013 uses Search Foundation instead of MSSearch in order to be consistent with SharePoint and to allow discovery searches across e-mail and documents. Search Foundation uses more memory and it seems it can take between 10 to 15% of available memory on a mailbox server.
Another change is the move of protocol handling from the Client Access Server [CAS] to the Mailbox server. It helps make the CAS more stateless and not so dependent on a particular mailbox server but it also increases the memory use on the mailbox server...

Note: the limit of 16 mailbox servers per DAG remains in Exchange 2013.

Monday, September 17, 2012

How to Determine Continuous Replication Mode (Block Mode or File Mode)?

In Exchange 2007 and 2010, Continuous Replication operates by shipping copies of the logs created by the active database copy to the passive database copies. With Exchange 2010 SP1, this is known as Continuous Replication - File Mode as the log file is only copied once it is full (1MB). But SP1 introduces a new form of continuous replication known as Continuous Replication - Block Mode. In block mode, when an update is written to the active database log file it is immediately copied to the passive mailbox copies, thus reducing the latency between the time a change is made on the active copy and the time that same change is replicated to a passive copy. This way, if a failure occurs on the active copy, the passive copies will have been updated with most or all of the latest updates.

However, Block Mode is only active when continuous replication is up-to-date in file mode. The Log Copier component monitors the copy and replay queue lengths of databases as transaction logs are generated and takes care of transitioning into and out of block mode automatically.

To determine if continuous replication is operating in block mode or file mode, use the following cmdlet:
Get-Counter -ComputerName <<DAG_Member_Name>> -Counter “\MSExchange Replication(*)\Continuous replication - block mode Active”

The output will be something similar to:
Timestamp                 CounterSamples
---------                 --------------
04/09/2012 11:39:46       \\MBX1\\msexchange replication(mdb31)\continuous replication - block mode active : 1
                          \\ MBX1\\msexchange replication(mdb32)\continuous replication - block mode active : 1
                          \\ MBX1\\msexchange replication(mdb33)\continuous replication - block mode active : 0

Here, the “1” means that block mode is active while a “0” means it is not. However, note that your active databases will always show “0”, we are just interested in the passive copies!

Sunday, July 8, 2012

Suspend Multiple Database Copies

If you are doing maintenance on a server and want to suspend all passive database copies on that server it is very simple and all you have to do is run:
Get-MailboxDatabaseCopyStatus -Server "server_name" | Suspend-MailboxDatabaseCopy -Confirm:$False

Because we are not excluding the current mounted DBs (if any), the script will throw an error stating that “The suspend operation can't proceed because database "db_name" on Exchange Mailbox server "server_name" is the active mailbox database copy” - which is fine because it’s what we want.

If you want to suspend all passive copies of a particular database across all servers you can simply run:
Get-MailboxDatabaseCopyStatus "db_name" | Suspend-MailboxDatabaseCopy -Confirm:$False

But what if you are reducing the number of database copies in your environment and just want to suspend the 4th copy of all your DBs across all your servers? In this case, we will have to use the following script:
$dbs = Get-MailboxDatabase

ForEach ($db in $dbs) {
  ForEach ($dbCopy in $db.DatabaseCopies) {
    If ($dbCopy.ActivationPreference -eq 4) {
      Suspend-MailboxDatabaseCopy $dbCopy.Identity -Confirm:$False
    }
  }
}

Hope this helps!

Thursday, March 15, 2012

Exclude a Mailbox Database from Provisioning


While with previous versions of Exchange we always had to specify a mailbox database when we created or moved a mailbox, or mail-enabled an existing user, with Exchange 2010 we have the option of letting Exchange choose the database for us by using the new Automatic Mailbox Distribution feature.

Automatic distribution is used when we don't specify the -Database parameter in the New-Mailbox and Enable-Mailbox cmdlets or the -TargetDatabase parameter in the New-MoveRequest cmdlet.

This feature looks at all mailbox databases in the organization and then randomly chooses a database where the mailbox should be located.

By default, all online and healthy databases on Exchange 2010 servers can be chosen by this process. However, because you might have some databases that you don’t want to be selected by this feature (a journaling database, for example), you can manually exclude them. To do this, you can either permanently or temporarily exclude databases from the exclusion process with two properties available in each database:
  • IsExcludedFromProvisioning: used if we want to indicate that the database should be permanently excluded from automatic mailbox distribution;
  • IsSuspendedFromProvisioning: used if we want to indicate that the database should be temporarily excluded from automatic mailbox distribution.

Which one we choose is purely for our information. Setting either one to $True has the same result of excluding the database from the automatic distribution process.

Let’s say we want to permanently exclude database MDB01 from automatic distribution:
Set-MailboxDatabase MDB01 -IsExcludedFromProvisioning $True

To temporarily exclude it, we use the following cmdlet:
Set-MailboxDatabase MDB01 -IsSuspendedFromProvisioning $True

To check which databases are excluded or suspended from provisioning and which ones are not, use the following cmdlet:
Get-MailboxDatabase | FT Name, IsExcludedFromProvisioning, IsSuspendedFromProvisioning

Thursday, August 18, 2011

Monitor Databases in DAGs

A few days ago, someone at the Microsoft Forums asked if there was a script to alert an administrator of when Exchange performs a failover of databases in a DAG.

This was something that I have wanted to do for a long time, but never actually got to do it... So here is my current solution (might get improved in the future).


With Exchange 2010 and DAGs, it is important to monitor whenever a database automatic fails over to another server. Although everything keeps working without any problems for end users (hopefully), administrators still have to investigate why a failover happened.

In case you have Exchange deployed across multiple AD sites and a database fails over to a server on another site, this will probably impact the way your users access OWA, for example.

Databases in a DAG, and therefore with multiple copies, have the ActivationPreference attribute that shows which servers have preference over the others to mount the database in case of a disaster or a manual switchover.

The following output is just an example of what you will get if you run the following command in an environment with at least a DAG and multiple copies:

Get-MailboxDatabase | Sort Name | Select Name, ActivationPreference


Name    ActivationPreference
----    --------------------
ADB1    {[MBXA1, 1], [MBXA2, 2]}
ADB2    {[MBXA1, 1], [MBXA2, 2]}
ADB3    {[MBXA1, 1], [MBXA2, 2]}
...
MDB1    {[MBX1, 1], [MBX2, 2], [MBX3, 3], [MBX4, 4]}
MDB2    {[MBX1, 1], [MBX2, 2], [MBX3, 3], [MBX4, 4]}
MDB3    {[MBX1, 1], [MBX2, 2], [MBX3, 3], [MBX4, 4]}
...

Based on the ActivationPreference attribute, we can monitor if databases are currently active on the servers that they should be, i.e., on servers with an ActivationPreference of 1.

To check this, we can use the following script:



Get-MailboxDatabase | Sort Name | ForEach {
 $db = $_.Name
 $curServer = $_.Server.Name
 $ownServer = $_.ActivationPreference | ? {$_.Value -eq 1}

 Write-Host "$db on $curServer should be on $($ownServer.Key) - " -NoNewLine

 If ($curServer -ne $ownServer.Key)
 {
  Write-Host "WRONG" -ForegroundColor Red
 }
 Else
 {
  Write-Host "OK" -ForegroundColor Green
 }
}



Which basically compares the server where the database is currently active with the server that has an ActivationPreference of 1. If they differ, then write WRONG in red to let the administrator know.

But since we are at it, why not also check for the status of the database and the state of its content index? This can be checked using the Get-MailboxDatabaseCopyStatus cmdlet.

According to the Monitoring High Availability and Site Resilience TechNet article, here are all the possible values for the database copy status:


Database Copy Status
Failed - The mailbox database copy is in a Failed state because it isn't suspended, and it isn't able to copy or replay log files. While in a Failed state and not suspended, the system will periodically check whether the problem that caused the copy status to change to Failed has been resolved. After the system has detected that the problem is resolved, and barring no other issues, the copy status will automatically change to Healthy;

Seeding - The mailbox database copy is being seeded, the content index for the mailbox database copy is being seeded, or both are being seeded. Upon successful completion of seeding, the copy status should change to Initializing;

SeedingSource - The mailbox database copy is being used as a source for a database copy seeding operation;

Suspended - The mailbox database copy is in a Suspended state as a result of an administrator manually suspending the database copy by running the Suspend-MailboxDatabaseCopy cmdlet;

Healthy - The mailbox database copy is successfully copying and replaying log files, or it has successfully copied and replayed all available log files;

ServiceDown - The Microsoft Exchange Replication service isn't available or running on the server that hosts the mailbox database copy;

Initializing - The mailbox database copy will be in an Initializing state when a database copy has been created, when the Microsoft Exchange Replication service is starting or has just been started, and during transitions from Suspended, ServiceDown, Failed, Seeding, SinglePageRestore, LostWrite, or Disconnected to another state. While in this state, the system is verifying that the database and log stream are in a consistent state. In most cases, the copy status will remain in the Initializing state for about 15 seconds, but in all cases, it should generally not be in this state for longer than 30 seconds;

Resynchronizing - The mailbox database copy and its log files are being compared with the active copy of the database to check for any divergence between the two copies. The copy status will remain in this state until any divergence is detected and resolved;

Mounted - The active copy is online and accepting client connections. Only the active copy of the mailbox database copy can have a copy status of Mounted;

Dismounted - The active copy is offline and not accepting client connections. Only the active copy of the mailbox database copy can have a copy status of Dismounted;

Mounting - The active copy is coming online and not yet accepting client connections. Only the active copy of the mailbox database copy can have a copy status of Mounting;

Dismounting - The active copy is going offline and terminating client connections. Only the active copy of the mailbox database copy can have a copy status of Dismounting;

DisconnectedAndHealthy - The mailbox database copy is no longer connected to the active database copy, and it was in the Healthy state when the loss of connection occurred. This state represents the database copy with respect to connectivity to its source database copy. It may be reported during DAG network failures between the source copy and the target database copy;

DisconnectedAndResynchronizing - The mailbox database copy is no longer connected to the active database copy, and it was in the Resynchronizing state when the loss of connection occurred. This state represents the database copy with respect to connectivity to its source database copy. It may be reported during DAG network failures between the source copy and the target database copy;

FailedAndSuspended - The Failed and Suspended states have been set simultaneously by the system because a failure was detected, and because resolution of the failure explicitly requires administrator intervention. An example is if the system detects unrecoverable divergence between the active mailbox database and a database copy. Unlike the Failed state, the system won't periodically check whether the problem has been resolved, and automatically recover. Instead, an administrator must intervene to resolve the underlying cause of the failure before the database copy can be transitioned to a healthy state;

SinglePageRestore - This state indicates that a single page restore operation is occurring on the mailbox database copy;



Based on these values, we want the Status attribute to be either Mounted (true for the server where the database is mounted) or Healthy (for the servers that hold a copy of it). For the ContentIndexState attribute, we want it to be always Healthy.

To monitor both these attribute, we can use the following command:


Get-MailboxDatabase | Sort Name | Get-MailboxDatabaseCopyStatus | ForEach {
 If ($_.Status -notmatch "Mounted" -and $_.Status -notmatch "Healthy" -or $_.ContentIndexState -notmatch "Healthy")
 {
  Write-Host "`n$($_.Name) - Status: $($_.Status) - Index: $($_.ContentIndexState)" -ForegroundColor Red
 }
}



Now, let’s put everything together and tell the script that if something is wrong with any database, to send an e-mail to the administrator! This way, we can create a schedule task to run this script every 2 minutes, for example.

Let’s also compare the AD sites where the current server hosting the database is against the AD site where the server that should be hosting the database is. As I mentioned before, this is important as it can change the way users access OWA.

You can also download the entire script from here.

Function getExchangeServerADSite ([String] $excServer)
{
 # We could use WMI to check for the domain, but I think this method is better
 # Get-WmiObject Win32_NTDomain -ComputerName $excServer

 $configNC =([ADSI]"LDAP://RootDse").configurationNamingContext
 $search = new-object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$configNC")
 $search.Filter = "(&(objectClass=msExchExchangeServer)(name=$excServer))"
 $search.PageSize = 1000
 [Void] $search.PropertiesToLoad.Add("msExchServerSite")

 Try {
  $adSite = [String] ($search.FindOne()).Properties.Item("msExchServerSite")
  Return ($adSite.Split(",")[0]).Substring(3)
 } Catch {
  Return $null
 }
}



[Bool] $bolFailover = $False
[String] $errMessage = $null

Get-MailboxDatabase | Sort Name | ForEach {
 $db = $_.Name
 $curServer = $_.Server.Name
 $ownServer = $_.ActivationPreference | ? {$_.Value -eq 1}

 # Compare the server where the DB is currently active to the server where it should be
 If ($curServer -ne $ownServer.Key)
 {
  # Compare the AD sites of both servers
  $siteCur = getExchangeServerADSite $curServer
  $siteOwn = getExchangeServerADSite $ownServer.Key
  
  If ($siteCur -ne $null -and $siteOwn -ne $null -and $siteCur -ne $siteOwn)
  {
   $errMessage += "`n$db on $curServer should be on $($ownServer.Key) (DIFFERENT AD SITE: $siteCur)!" 
  }
  Else
  {
   $errMessage += "`n$db on $curServer should be on $($ownServer.Key)!"
  }

  $bolFailover = $True
 }
}

$errMessage += "`n`n"

Get-MailboxDatabase | Sort Name | Get-MailboxDatabaseCopyStatus | ForEach {
 If ($_.Status -notmatch "Mounted" -and $_.Status -notmatch "Healthy" -or $_.ContentIndexState -notmatch "Healthy")
 {
  $errMessage += "`n$($_.Name) - Status: $($_.Status) - Index: $($_.ContentIndexState)"
  $bolFailover = $True
 }
}

If ($bolFailover)
{
 Send-MailMessage -From "admin_nuno@letsexchange.com -To "exchange.alerts@letsexchange.com" -Subject "DAG NOT Healthy!" -Body $errMessage -Priority High -SMTPserver "mail.letsexchange.com"
 Schtasks.exe /Change /TN "MonitorDAG" /DISABLE
}




As always, sorry for the format of the code...
At the end of the script, if an e-mail is sent, you might want to disable the schedule task, otherwise you will receive an e-mail every two minutes until you resolve the issue...

Please note that there are more attributes that can and should be monitored! For example, you could run the Test-ReplicationHealth to view replication status information about mailbox database copies.

Hope this helps!

Thursday, December 16, 2010

Get Mailbox Database Mount Status

Wondering why when you run the Get-MailboxDatabase you don’t see if the database is Mounted or not? This value might be especially useful when writing a monitoring script, for example. And yes, I was also wondering for a while...


All we have to do is add –status to the cmdlet:

and voila!   :)
Don't ask me why though...