Mailbox Databases Balancing Script

Goal of this script

This script was written to provide a solution on Microsoft Exchange servers with multiple Mailbox Databases that could be differently loaded.

When creating mailboxes over multiple databases, it's difficult to measure how much a database is loaded. It's easy to find out how full is a system volume (through Windows Explorer, CMD or Powershell), but is not as easy to know if a Mailbox Database is full or not.

Difficulties with mailbox moves

Sometimes, you could have problems with a mailbox database that cannot receive any email because the system volume on which it's written is almost full. The first common step is to move big mailboxes to another database and then you're able to receive new emails...

But, when checking how many space is left on the database with the following Powershell command, we doesn't understand where is gone our space !

 

PowerShell
Edit|Remove
[PS] Get-MailboxDatabase -Database MyFirstDb -Status|ft DatabaseSize,AvailableNewMailboxSpace 
 
DatabaseSize                                           AvailableNewMailboxSpace 
------------                                           ------------------------ 
1.161 TB (1,276,020,588,544 bytes)                     67.17 GB (72,124,891,136 bytes)
In this example, we've moved around 200 Gb of mailboxes on another Mailbox Database : but, where has gone our 200 Gb !?!
Let's take a look at disconnected mailboxes on that source database :
PowerShell
Edit|Remove
[PS] Get-MailboxStatistics -Database MyFirstDb|Where {$_.DisconnectReason -eq "SoftDeleted"}|Select DisplayName,TotalItemSize 
DisplayName                                            TotalItemSize 
-----------                                            ------------- 
Romain D.                                              9.455 GB (10,151,851,718 bytes) 
Karim D.                                               10.58 GB (11,359,116,413 bytes) 
Bruno M.                                               15.06 GB (16,166,325,067 bytes) 
Agnès N.                                               8.371 GB (8,988,220,750 bytes) 
Coralie C.                                             16.93 KB (17,334 bytes) 
(...) 
Valérie S.                                             10.15 GB (10,899,338,720 bytes) 
Patrick R.                                             14.48 GB (15,548,593,366 bytes) 
Nadine A.                                              8.885 GB (9,540,389,892 bytes) 
Pierre-Yves G.                                         21.37 GB (22,944,644,691 bytes) 
Alexandre M.                                           30.49 GB (32,739,954,024 bytes) 
Michel A.                                              8.976 GB (9,637,492,609 bytes)
We can see that moved mailboxes are kept left in the source database with the status "SoftDeleted". So, the goal is to clear them to get back free space immediatly.

 

SoftDeleted Status

The SoftDeleted status isn't a problem at all because in case of space needs, Exchange will first use free space, and then will use space "reserved" by SoftDeleted mailbox is needed.

But, in our case, we want to clear out the space immediatly to make databases balanced.

How does this script work ?

First, the script get all mailbox databases on Exchange organization with the command :

 

PowerShell
Edit|Remove
[PS] Get-MailboxDatabases
For each database, it calculates the ratio of directly available space, based on that formula :
100 * ((AvailableNewMailboxSpace + Volume Space) / Volume Size)
Then, it takes the more used Database (the greater ratio) - aka the source database - and the less used Database.
It looks for a random mailbox to move from the source database and creates a mailbox move request.
It monitors the move request process.
When the move request is completed, it removes the move request and clears up the source mailbox database from the moved mailbox.
Then, it loops with the same process until all mailboxes have the same available free space +/- 10%.

Screenshot

The top of the screen shows some progress bars that represent :

 

Usage

This script is very easy to use : set those two parameters inside the code and run it :

 

PowerShell
Edit|Remove
# Debug Mode 
$global:debugMode  = $True 
 
# Tolerance between Databases in percent 
$spaceToleranceBetweenDBs = 10 
Turn $global:debugMode to $True if you want detailled information (like the snapshot).
Set the $spaceToleranceBetweenDBs to the percentage of delta tolerate between mailbox databases space.

Change Log

1.0 : Initial Release

1.1 : Add check of databases at startup : start only is there's at least 2 databases.

Correct removes from $aDatabases : now, we use the .Remove() method.