(For more resources related to this topic, see here.)
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.
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
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
[Math]::Round($MBAvg,2)
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
2.39
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)
2.39
The -f format operator is documented in PowerShell’s help system in about_operators.
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.
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.
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:RecoveryDB1 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:
New-MailboxDatabase -Name RecoveryDB `
-EdbFilePath E:RecoveryDB1DB1.edb `
-LogFolderPath E:RecoveryDB01 `
-Recovery `
-Server MBX1
Eseutil /mh .DB1.edb
Eseutil /R E02 /D
Mount-Database -Identity RecoveryDB
Get-MailboxStatistics –Database RecoveryDB | fl DisplayName,Mailbo
xGUID,LegacyDN
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.
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.
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.
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.
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:
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.
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:
For complete details and examples for each of these cmdlets, use the Get-Help cmdlet with the appropriate cmdlet using the -Full switch parameter.
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.
Further resources on this subject:
I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…
Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…
Once we learn how to deploy an Ubuntu server, how to manage users, and how…
Key-takeaways: Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…
While developing a web application, or setting dynamic pages and meta tags we need to deal with…
Software architecture is one of the most discussed topics in the software industry today, and…