Mailbox Database Management

Benefit from over 120 recipes that tackle the everyday issues that arise with Microsoft Exchange Server. Using PowerShell you’ll learn to add scripts that provide new functions and efficiencies. Only basic knowledge required.


Determining the average mailbox size per database

PowerShell is very flexible and gives you the ability to generate very detailed reports. When generating mailbox database statistics, we can utilize data returned from multiple cmdlets provided by the Exchange Management Shell. This section will show you an example of this, and you will learn how to calculate the average mailbox size per database using PowerShell.

How to do it...

To determine the average mailbox size for a given database, use the following one-liner:

Get-MailboxStatistics -Database DB1 |
ForEach-Object {$_.TotalItemSize.value.ToMB()} |
Measure-Object -Average |
Select-Object –ExpandProperty Average

How it works...

Calculating an average is as simple as performing some basic math, but PowerShell gives us the ability to do this quickly with the Measure-Object cmdlet. The example uses the Get-MailboxStatistics cmdlet to retrieve all the mailboxes in the DB1 database. We then loop through each one, retrieving only the TotalItemSize property, and inside the ForEach-Object script block we convert the total item size to megabytes. The result from each mailbox can then be averaged using the Measure-Object cmdlet. At the end of the command, you can see that the Select-Object cmdlet is used to retrieve only the value for the Average property.

The number returned here will give us the average mailbox size in total for regular mailboxes, archive mailboxes, as well as any other type of mailbox that has been disconnected. If you want to be more specific, you can filter out these mailboxes after running the Get-MailboxStatistics cmdlet:

Get-MailboxStatistics -Database DB1 |
Where-Object{!$_.DisconnectDate -and !$_.IsArchive} |
ForEach-Object {$_.TotalItemSize.value.ToMB()} |
Measure-Object -Average |
Select-Object –ExpandProperty Average

Notice that, in the preceding example, we have added the Where-Object cmdlet to filter out any mailboxes that have a DisconnectDate defined or where the IsArchive property is $true.

Another thing that you may want to do is round the average. Let's say the DB1 database contained 42 mailboxes and the total size of the database was around 392 megabytes. The value returned from the preceding command would roughly look something like 2.39393939393939. Rarely are all those extra decimal places of any use. Here are a couple of ways to make the output a little cleaner:

$MBAvg = Get-MailboxStatistics -Database DB1 |
ForEach-Object {$_.TotalItemSize.value.ToMB()} |
Measure-Object -Average |
Select-Object –ExpandProperty Average

You can see that this time, we stored the result of the one-liner in the $MBAvg variable. We then use the Round method of the Math class in the .NET Framework to round the value, specifying that the result should only contain two decimal places. Based on the previous information, the result of the preceding command would be 2.39.

We can also use string formatting to specify the number of decimal places to be used:

[PS] "{0:n2}" -f $MBAvg

Keep in mind that this command will return a string, so if you need to be able to sort on this value, cast it to double:

[PS] [double]("{0:n2}" -f $MBAvg)

The -f format operator is documented in PowerShell's help system in about_operators.

There's more...

The previous examples have only shown how to determine the average mailbox size for a single database. To determine this information for all mailbox databases, we can use the following code (save it to a file called size.ps1):

foreach($DB in Get-MailboxDatabase) {
Get-MailboxStatistics -Database $DB |
ForEach-Object{$_.TotalItemSize.value.ToMB()} |
Measure-Object -Average |
Select-Object @{n="Name";e={$DB.Name}},
@{n="AvgMailboxSize";e={[Math] `
::Round($_.Average,2)}} | Sort-Object `
AvgMailboxSize -Desc

The result of this command would look something like this:

This example is very similar to the one we looked at previously. The difference is that, this time, we are running our one-liner using a foreach loop for every mailbox database in the organization. When each mailbox database has been processed, we sort the output based on the AvgMailboxSize property.

Restoring data from a recovery database

When it comes to recovering data from a failed database, you have several options depending on what kind of backup product you are using or how you have deployed Exchange 2013. The ideal method for enabling redundancy is to use a DAG, which will replicate your mailbox databases to one or more servers and provide automatic failover in the event of a disaster. However, you may need to pull old data out of a database restored from a backup. In this section, we will take a look at how you can create a recovery database and restore data from it using the Exchange Management Shell.

How to do it...

First, restore the failed database using the steps required by your current backup solution. For this example, let's say that we have restored the DB1 database file to E:\Recovery\DB1 and the database has been brought to a clean shutdown state. We can use the following steps to create a recovery database and restore mailbox data:

  1. Create a recovery database using the New-MailboxDatabase cmdlet:

    New-MailboxDatabase -Name RecoveryDB `
    -EdbFilePath E:\Recovery\DB1\DB1.edb `
    -LogFolderPath E:\Recovery\DB01 `
    -Recovery `
    -Server MBX1

  2. When you run the preceding command, you will see a warning that the recovery database was created using the existing database file. The next step is to check the state of the database, followed by mounting the database:

    Eseutil /mh .\DB1.edb
    Eseutil /R E02 /D
    Mount-Database -Identity RecoveryDB

  3. Next, query the recovery database for all mailboxes that reside in the database RecoveryDB:

    Get-MailboxStatistics –Database RecoveryDB | fl DisplayName,Mailbo

  4. Lastly, we will use the New-MailboxRestoreRequest cmdlet to restore the data from the recovery database for a single mailbox:

    New-MailboxRestoreRequest -SourceDatabase RecoveryDB `
    -SourceStoreMailbox "Joe Smith" `
    -TargetMailbox joe.smith

When running the eseutil commands, make sure you are in the folder where the restored mailbox database and logs are placed.

How it works...

When you restore the database file from your backup application, you may need to ensure that the database is in a clean shutdown state. For example, if you are using Windows Server Backup for your backup solution, you will need to use the Eseutil.exe database utility to play any uncommitted logs into the database to get it in a clean shutdown state.

Once the data is restored, we can create a recovery database using the New-MailboxDatabase cmdlet, as shown in the first example. Notice that when we ran the command we used several parameters. First, we specified the path to the EDB file and the logfiles, both of which are in the same location where we restored the files. We have also used the -Recovery switch parameter to specify that this is a special type of database that will only be used for restoring data and should not be used for production mailboxes. Finally, we specified which mailbox server the database should be hosted on using the -Server parameter. Make sure to run the New-MailboxDatabase cmdlet from the mailbox server that you are specifying in the -Server parameter, and then mount the database using the Mount-Database cmdlet.

The last step is to restore data from one or more mailboxes. As we saw in the previous example, New-MailboxRestoreRequest is the tool to use for this task. This cmdlet was introduced in Exchange 2010 SP1, so if you have used this process in the past, the procedure is the same with Exchange 2013.

There's more…

When you run the New-MailboxRestoreRequest cmdlet, you need to specify the identity of the mailbox you wish to restore using the -SourceStoreMailbox parameter. There are three possible values you can use to provide this information: DisplayName, MailboxGuid, and LegacyDN . To retrieve these values, you can use the Get-MailboxStatistics cmdlet once the recovery database is online and mounted:

Get-MailboxStatistics -Database RecoveryDB |
fl DisplayName,MailboxGUID,LegacyDN

Here we have specified that we want to retrieve all three of these values for each mailbox in the RecoveryDB database.

Understanding target mailbox identity

When restoring data with the New-MailboxRestoreRequest cmdlet, you also need to provide a value for the -TargetMailbox parameter. The mailbox needs to already exist before running this command. If you are restoring data from a backup for an existing mailbox that has not changed since the backup was done, you can simply provide the typical identity values for a mailbox for this parameter.

If you want to restore data to a mailbox that was not the original source of the data, you need to use the -AllowLegacyDNMismatch switch parameter. This will be useful if you are restoring data to another user's mailbox, or if you've recreated the mailbox since the backup was taken.

Learning about other useful parameters

The New-MailboxRestoreRequest cmdlet can be used to granularly control how data is restored out of a mailbox. The following parameters may be useful to customize the behavior of your restores:

  • ConflictResolutionOption: This parameter specifies the action to take if multiple matching messages exist in the target mailbox. The possible values are KeepSourceItem, KeepLatestItem, or KeepAll. If no value is specified, KeepSourceItem will be used by default.
  • ExcludeDumpster: Use this switch parameter to indicate that the dumpster should not be included in the restore.
  • SourceRootFolder: Use this parameter to restore data only from a root folder of a mailbox.
  • TargetIsArchive: You can use this switch parameter to perform a mailbox restore to a mailbox archive.
  • TargetRootFolder: This parameter can be used to restore data to a specific folder in the root of the target mailbox. If no value is provided, the data is restored and merged into the existing folders, and, if they do not exist, they will be created in the target mailbox.

These are just a few of the useful parameters that can be used with this cmdlet, but there are more. For a complete list of all the available parameters and full details on each one, run Get-Help New-MailboxRestoreRequest -Detailed.

Understanding mailbox restore request cmdlets

There is an entire cmdlet set for mailbox restore requests in addition to the New-MailboxRestoreRequest cmdlet. The remaining available cmdlets are outlined as follows:

  • Get-MailboxRestoreRequest: Provides a detailed status of mailbox restore requests
  • Remove-MailboxRestoreRequest : Removes fully or partially completed restore requests
  • Resume-MailboxRestoreRequest : Resumes a restore request that was suspended or failed
  • Set-MailboxRestoreRequest: Can be used to change the restore request options after the request has been created
  • Suspend-MailboxRestoreRequest: Suspends a restore request any time after the request was created but before the request reaches the status of Completed

For complete details and examples for each of these cmdlets, use the Get-Help cmdlet with the appropriate cmdlet using the -Full switch parameter.

Taking it a step further

Let's say that you have restored your database from backup, you have created a recovery database, and now you need to restore each mailbox in the backup to the corresponding target mailboxes that are currently online. We can use the following script to accomplish this:

$mailboxes = Get-MailboxStatistics -Database RecoveryDB
foreach($mailbox in $mailboxes) {
New-MailboxRestoreRequest -SourceDatabase RecoveryDB `
-SourceStoreMailbox $mailbox.DisplayName `
-TargetMailbox $mailbox.DisplayName

Here you can see that first we use the Get-MailboxStatistics cmdlet to retrieve all the mailboxes in the recovery database and store the results in the $mailboxesvariable. We then loop through each mailbox and restore the data to the original mailbox. You can track the status of these restores using the Get-MailboxRestoreRequest cmdlet and the Get-MailboxRestoreRequestStatistics cmdlet.


Thus in this article, we covered a very small but an appetizing part of mailbox database management by determining the average mailbox size per database and restoring data from a recovery database.

Resources for Article :

Further resources on this subject:

Books to Consider

Mastering Management Styles: Expert Guidance for Managers
$ 7.50
The Professional Woman’s Guide to Managing Men
$ 7.50
Web Host Manager Administration Guide
$ 12.00
comments powered by Disqus