Introduction
In Exchange 2010, you now have the option to allow mailboxes to be automatically distributed across databases. However, the algorithm used simply randomly allocates the new mailbox to your chosen databases – rather than ensuring the mailbox count is balanced, and doesn’t do anything about re-distributing mailboxes if you add new databases.
To help with this, and of course to help with any situation where you want to balance the number of mailboxes across a set of databases, I’ve written a simple script that help with moving mailboxes to balance out your databases.
Using Generate-DBBalanceScript.ps1
There’s nothing too complicated about the script- it doesn’t balance based on mailbox size (a future version), but simply creates a script with Move-Mailbox or New-MoveRequest commands that once complete, balances based on mailbox counts across the databases. You pass it the results of a Get-MailboxDatabase command, along with an output file that will contain the Mailbox move commands.
First of all, lets see it in action:
Of course, my example was the simplest – across all databases. Here’s a few examples including the one above, and some others that show how to drill down to databases on specific servers:
Example One – Generate a move file based on all Exchange 2010 Databases:
1 | .\Generate-BalanceMoveRequests.ps1 -DBs (Get-MailboxDatabase) -OutputPowershellFile .\moves.ps1 |
Example Two – Generate a move file based on Exchange 2010 Databases located on a single server “servername”:
1 2 | $o=Get-MailboxDatabase -Server servername .\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false |
Example Three – Generate a move file based on Exchange 2007 Databases located on two servers, “serverone” and “servertwo”:
1 2 |
Download Generate-DBBalanceScript.ps1
You can download Generate-DBBalanceScript.ps1 here or view the script below.
Hope this helps!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | <# .SYNOPSIS Generates a Powershell file containing Mailbox Move Cmdlets to help balance mailbox databases, based on mailbox count, not size. .DESCRIPTION Using a list of Databases, works out the average number of mailboxes there should be per DB, then generates move commands to run seperately. By Steve Goodman .PARAMETER DBs Databases to use The result of a Get-MailboxDatabase cmdlet. Eg. (Get-MailboxDatabase -Server name) .PARAMETER OutputPowershellFile The filename to write, for example C:\output.ps1 or .\output.ps1 .PARAMETER Exchange2010 By default, true. Set to $false to generate Exchagne2007 move-mailbox commands .EXAMPLE Generate a move file based on all Exchange 2010 Databases .\Generate-BalanceMoveRequests.ps1 -DBs (Get-MailboxDatabase) -OutputPowershellFile .\moves.ps1 .EXAMPLE Generate a move file based on Exchange 2007 Databases located on a single server "servername" $o=Get-MailboxDatabase -Server servername .\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false .EXAMPLE Generate a move file based on Exchange 2007 Databases located on two servers, "serverone" and "servertwo" $o=Get-MailboxDatabase | where {$_.Server -eq "serverone" -or $_.Server -eq "servertwo"} .\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false #> param( [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false,HelpMessage="Mailbox database object")][array]$DBs, [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$false,HelpMessage="Filename for output Powershell script")][string]$OutputPowershellFile, [parameter(Position=2,Mandatory=$false,ValueFromPipeline=$false,HelpMessage="Is this for Exchange 2010")][bool]$Exchange2010=$true ) # Check for Exchange cmdlets if (!(Get-Command Get-MailboxDatabase -ErrorAction SilentlyContinue)) { throw "Exchange Cmdlets not available"; } # Check input object if ($DBs[0].GetType().Name -ne "MailboxDatabase") { throw "Object is not an array of mailbox databases" } if ($DBs.Count -eq 1) { throw "You can't balance a single database"; } # Check file does not exist if ((Test-Path $OutputPowershellFile)) { throw "File $($OutputPowershellFile) already exists"; } # Initialise file "# Mailbox Mail Powershell Script File, generated $(date)`r`n"|Out-File -FilePath $OutputPowershellFile -NoClobber if (!(Test-Path $OutputPowershellFile)) { throw "Could not write to $($OutputPowershellFile)"; } # Initialise Variables [int]$TotalMailboxes=0; # Total Mailboxes [int]$BalancedCount=0; # Balanced Number of Mailboxes per DB [array]$DBCounters=@(); # Array with DB Id, Mailbox Count and Mailbox listing [array]$UA_DBCounters=@(); # Under allocated list from above, populated later [array]$OA_DBCounters=@(); # Over allocated list from above, populated later [array]$PA_DBCounters=@(); # Perfectly allocated list from above, populated later [string]$Output=""; # Variable to write output text to # Gather initial mailbox counts Write-Host "Gathering Mailbox Counts" for ($i = 0; $i -lt $DBs.Count; $i++) { Write-Progress -activity "Gathering Mailbox Counts" -status "Processing Database $($DBs[$i].Identity)" -PercentComplete (($i / $DBs.Count) * 100) $Mailboxes = (Get-Mailbox -Database $DBs[$i].Identity -ResultSize Unlimited | select Identity) $DBCounters=$DBCounters+1; $DBCounters[$DBCounters.Count-1] = New-Object Object $DBCounters[$DBCounters.Count-1] | Add-Member NoteProperty Database $DBs[$i].Identity $DBCounters[$DBCounters.Count-1] | Add-Member NoteProperty Total $Mailboxes.Count $DBCounters[$DBCounters.Count-1] | Add-Member NoteProperty Mailboxes $Mailboxes $TotalMailboxes+=$Mailboxes.Count } Write-Progress -Activity "Gathering Mailbox Counts" -Completed -Status "Completed" Write-Host "DB Counts are as follows:" $DBCounters|Select Database,Total $BalancedCount = $TotalMailboxes / $DBs.Count Write-Host "Found $($TotalMailboxes) mailboxes across $($DBs.Count) databases. Aiming for $($BalancedCount) mailboxes per database." Write-Host "Sorting Databases into over, under and perfectly allocated." # Sort DBs into under-allocated, over-allocated and perfectly allocated for ($i = 0; $i -lt $DBCounters.Count; $i++) { Write-Progress -activity "Sorting Databases into over, under and perfectly allocated" -status "Processing Database $($DBCounters[$i].Database)" -PercentComplete (($i / $DBCounters.Count) * 100) if ($DBCounters[$i].Total -lt $BalancedCount) { $UA_DBCounters=$UA_DBCounters+1; $UA_DBCounters[$UA_DBCounters.Count-1] = $DBCounters[$i]; } elseif ($DBCounters[$i].Total -gt $BalancedCount) { $OA_DBCounters=$OA_DBCounters+1; $OA_DBCounters[$OA_DBCounters.Count-1] = $DBCounters[$i]; } else { $PA_DBCounters=$PA_DBCounters+1; $PA_DBCounters[$PA_DBCounters.Count-1] = $DBCounters[$i]; } } Write-Progress -activity "Sorting Databases into over, under and perfectly allocated" -Completed -Status "Completed" Write-Host "Found $($OA_DBCounters.Count) over, $($UA_DBCounters.Count) under and $($PA_DBCounters.Count) perfectly allocated"; # Make move list Write-Host "Generating Powershell File '$($OutputPowershellFile)' to Balance DBs." for ($i = 0; $i -lt $OA_DBCounters.Count; $i++) { Write-Progress -activity "Generating Powershell File '$($OutputPowershellFile)' to Balance DBs" -status "Processing Database $($OA_DBCounters[$i].Database)" -PercentComplete (($i / $OA_DBCounters.Count) * 100) # Get the mailbox list [array]$OA_Mailboxes = $OA_DBCounters[$i].Mailboxes $UA_DBPointer=0; for ($j=$BalancedCount; $j -lt $OA_Mailboxes.Count; $j++) { # Move to next underallocated DB if required if ($UA_DBCounters[$UA_DBPointer].Total -ge $BalancedCount -and $UA_DBPointer -lt $UA_DBCounters.Count-1) { $UA_DBPointer++; } Write-Progress -activity "Generating move commands" -status "Processing $($OA_Mailboxes[$j].Identity)" -PercentComplete (($j / $OA_Mailboxes.Count) * 100) # Generate a Powershell command for the move request if ($Exchange2010) { $Output+="New-MoveRequest -Identity '$($OA_Mailboxes[$j].Identity)' -TargetDatabase '$($UA_DBCounters[$UA_DBPointer].Database)' -Confirm:" + '$false' + "`r`n"; } else { $Output+="Move-Mailbox -Identity '$($OA_Mailboxes[$j].Identity)' -TargetDatabase '$($UA_DBCounters[$UA_DBPointer].Database)'`r`n"; } $OA_DBCounters[$i].Total--; # Take one mailbox of the total on the overallocated DB $UA_DBCounters[$UA_DBPointer].Total++; # Add one mailbox tot the total of the current underallocated DB } Write-Progress -activity "Generating move commands" -Completed -Status "Completed" } Write-Progress -activity "Generating Powershell File '$($OutputPowershellFile)' to Balance DBs" -Completed -Status "Completed" Write-Host "DB Counts will be as follows after executing $($OutputPowershellFile):" $OA_DBCounters|Select Database,Total $UA_DBCounters|Select Database,Total $PA_DBCounters|Select Database,Total Write-Host "Writing Powershell file '$($OutputPowershellFile)'" $Output | Out-File -FilePath $OutputPowershellFile -NoClobber -Append |
There is a bug !
You have just to move “$UA_DBPointer=0;” before “for ($i = 0; $i -lt $OA_DBCounters.Count; $i++)”
This will resolve the kek’s issue.
Ben
Hi Steve
I am not sure if you are still monitoring this thread or not but I have a question to ask.
In you examples above, if the script was to be run for all databases, does this look at the Active and Passive databases in a DAG or just the Active?
If the above is true that the script only looks at the active databases, then I suppose that I would have to use Example 3, but is it possible to run this on Exchange 2010 or 2013?
Pingback: Moving Mailboxes the easy way – flaphead.com
Hi James, are you able to provide an example of how you overcame this? I’m currently having the same issue. I think i understand your workaround, just wanting to verify.
Hi Steve,
I do’nt know if you still monitor this, but this does exactly what I need it to do…except…it doesn’t 🙁
I’m in the same boat as the bloke up above…our users have a parenthesis in their display name quite commonly, and it seems to be throwing an error in the move portion of the script. I don’t see anywhere how to overcome this…is it possible to use the samaccountname or mailnickname or even smtp address in the move file? How would i modify the code to accomplish such a thing?
Thanks!
James
Disregard, I figured it out!
I added primarysmtp to the properties selected in the get-mailbox cmd, then when generating the move requests i changed .identity to .primarysmtpaddress. At this point, I still had an issue with a problem ” ‘ ” terminator, so i did a find\replace on the move file to replace all instances of ” ‘ ” with a blank space. Voila, problem solved!
Hey there Steve. We have a single SBS server with 30 mailboxes on it. The script works for the first two sections but the Database Backup section is what I’m most interested in. Have you worked with anyone to get the script running on the SBS side of things?
Site: Default-First-Site-Name Exchange Version Roles Installed OS Version OS Service Pack
Mailboxes: 30 CAS EDGE HUB MBX UM
SBSServer Exchange 2010 SP1 UR7 v2 30 Windows? Small Business Server 2011 Std Service Pack 1
Has anyone figured out how to exclude the archive database (or any particular mailbox) from being part of the balancing? We have 3 databases, with 1 of the 3 being archival on slow storage. If I run this, I fear that my 300 mailboxes will balance across all 3 databases and lead to major performance issues for 1/3 of the users. I also don’t want archival mailboxes to be moved over to “fast storage” mailbox databases. I haven’t figured out how to exclude 1 database while including the other 2.
Any help would be appreciated!
if you do $o = Get-MailboxDatabase| Where-object {$_.name -ne ‘Archive’}
then
.\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile .\moves.ps1
this will do all but the Archive database. I am running into the problem where im trying to exclude 2 databases and it wont work no matter how i run it.
Just figured my problem out
o$ = Get-MailboxDatabase | Where-Object {$_.name -ne ‘Archive’ -and $_.name -ne ‘Recovery’}
was trying to use -or not -and.
Pingback: Balancing mailboxes across Exchange 2010 and 2007 databases « MidThought's
Steve,
Love the script, but I have a problem.
Does it have a problem with space in the Identity? I’m getting the following error when I try to execute the moves.ps1 script. Is it possible to use the alias as the indentifier instead of the AD OU?
[PS] C:\scripts>.\moves.ps1
The string starting:
At C:\scripts\moves.ps1:85 char:81
+ New-MoveRequest -Identity ‘mycompany.corp/Users/user name’ -TargetDatabase ‘MDB04 <<<< ' -Confirm:$false
is missing the terminator: '.
At C:\scripts\moves.ps1:85 char:98
+ New-MoveRequest -Identity ''mycompany.corp/Users/user name' -TargetDatabase 'MDB04' -Confirm:$false <<<<
+ CategoryInfo : ParserError: ( -Confirm:$false:String) [], ParseException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
Thanks for all the work you've done to make my Exchange tasks easier!
Hiya,
There should be a comment above in this thread that explains what to change to do this.
Steve
I Have a large 130k 2010 environment that really needs the “Generate-BalancebySizeMoveRequests.ps1” script. we have about 3 tiers of MB sizes and use the random theory to distribute them over all 16 MBX servers and DB’s… would be awesome to use mailbox size in that distribution as well. like maybe setting some defaults that can be changed like (low<=50mb, med2048+) and distribute those equally across DB’s so that not all the <50mb ones are on one DB and the 2048+ ones are on another….
anyways. just my +1 for this functionality
Dave P
Great script Steve!!!
Cheers Shawn,
Steve
Hey there Steve, I was wondering if you ever got a chance last year to write the Generate-BalancebySizeMoveRequests.ps1???? 🙂
Chris
Steve, do you know if a script can be created to rebalance the DAG in 2010?
If I have 3 servers, 3 databases and have copies of each DB on each server, If I lose a server the DB all work but the third server is never used again when back online unless I manually balance them.
Hiya,
A script is built into Exchange 2010 which performs this:
Open Exchange Management Shell:
cd $exscripts
\RedistributeActiveDatabases.ps1 -DagName DAG -BalanceDbsByActivationPreference
Steve
Steve, did you ever update this script to balance mailboxes based on size? We’ve got to divide a single database into 5 and we want to balance the size of the database.
Hi Michael,
I haven’t had a look at it yet, sadly it’s hard to come back to the older posts to add features as I have been pretty busy over the last few months.
Steve
Steve,
Sorry I won’t bombard with anymore information after this. I reduced this down to 2 servers, old to new with 18 databases balancing to 24. Still strange results. Any thoughts?
.\Generate-DBBalanceScript.ps1 -DBs $o -OutputPowershellFile .\moves9to4.2.txt
Gathering Mailbox Counts
DB Counts are as follows:
Database Total
———— —–
EXSRV09DB01 — 122
EXSRV09DB02 — 122
EXSRV09DB03 — 120
EXSRV09DB04 — 118
EXSRV09DB05 — 120
EXSRV09DB06 — 109
EXSRV09DB07 — 118
EXSRV09DB08 — 115
EXSRV09DB09 — 117
EXSRV09DB10 — 112
EXSRV09DB11 — 116
EXSRV09DB12 — 106
EXSRV09DB13 — 111
EXSRV09DB14 — 99
EXSRV09DB15 — 103
EXSRV09DB16 — 108
EXSRV09DB17 — 108
EXSRV09DB18 — 103
EXSRV04DB01 — 5
EXSRV04DB02 — 5
EXSRV04DB03 — 5
EXSRV04DB04 — 5
EXSRV04DB05 — 5
EXSRV04DB06 — 5
EXSRV04DB07 — 5
EXSRV04DB08 — 5
EXSRV04DB09 — 6
EXSRV04DB10 — 5
EXSRV04DB11 — 4
EXSRV04DB12 — 5
EXSRV04DB13 — 5
EXSRV04DB14 — 4
EXSRV04DB15 — 6
EXSRV04DB16 — 3
EXSRV04DB17 — 10
EXSRV04DB21 — 10
EXSRV04DB19 — 6
EXSRV04DB23 — 11
EXSRV04DB20 — 10
EXSRV04DB22 — 3
EXSRV04DB18 — 4
EXSRV04DB24 — 3
Found 2162 mailboxes across 42 databases. Aiming for 51 mailboxes per database.
Sorting Databases into over, under and perfectly allocated.
Found 18 over, 24 under and 0 perfectly allocated
Generating Powershell File ‘.\moves9to4.2.txt’ to Balance DBs.
DB Counts will be as follows after executing .\moves9to4.2.txt:
EXSRV09DB01 — 51
EXSRV09DB02 — 51
EXSRV09DB03 — 51
EXSRV09DB04 — 51
EXSRV09DB05 — 51
EXSRV09DB06 — 51
EXSRV09DB07 — 51
EXSRV09DB08 — 51
EXSRV09DB09 — 51
EXSRV09DB10 — 51
EXSRV09DB11 — 51
EXSRV09DB12 — 51
EXSRV09DB13 — 51
EXSRV09DB14 — 51
EXSRV09DB15 — 51
EXSRV09DB16 — 51
EXSRV09DB17 — 51
EXSRV09DB18 — 51
EXSRV04DB01 — 51
EXSRV04DB02 — 67
EXSRV04DB03 — 67
EXSRV04DB04 — 66
EXSRV04DB05 — 65
EXSRV04DB06 — 64
EXSRV04DB07 — 64
EXSRV04DB08 — 63
EXSRV04DB09 — 62
EXSRV04DB10 — 61
EXSRV04DB11 — 61
EXSRV04DB12 — 60
EXSRV04DB13 — 59
EXSRV04DB14 — 58
EXSRV04DB15 — 57
EXSRV04DB16 — 56
EXSRV04DB17 — 55
EXSRV04DB21 — 54
EXSRV04DB19 — 52
EXSRV04DB23 — 51
EXSRV04DB20 — 41
EXSRV04DB22 — 3
EXSRV04DB18 — 4
EXSRV04DB24 — 3
Writing Powershell file ‘.\moves9to4.2.txt’
Steve,
I quarted it down to 72 databases and have the same strange results. The balacing is going against 3 servers, 2 old and one new. Results below:
Found 5399 mailboxes across 72 databases. Aiming for 75 mailboxes per database.
Sorting Databases into over, under and perfectly allocated.
Found 48 over, 24 under and 0 perfectly allocated
Generating Powershell File ‘.\moves1-2to6.txt’ to Balance DBs.
DB Counts will be as follows after EXSRVecuting .\moves1-2to6.txt:
EXSRV01DB01 — 75
EXSRV01DB02 — 75
EXSRV01DB03 — 75
EXSRV01DB04 — 75
EXSRV01DB06 — 75
EXSRV01DB10 — 75
EXSRV01DB12 — 75
EXSRV01DB09 — 75
EXSRV01DB07 — 75
EXSRV01DB08 — 75
EXSRV01DB05 — 75
EXSRV01DB11 — 75
EXSRV01DB19 — 75
EXSRV01DB22 — 75
EXSRV01DB15 — 75
EXSRV01DB14 — 75
EXSRV01DB23 — 75
EXSRV01DB17 — 75
EXSRV01DB16 — 75
EXSRV01DB21 — 75
EXSRV01DB20 — 75
EXSRV01DB13 — 75
EXSRV01DB18 — 75
EXSRV01DB24 — 75
EXSRV02DB01 — 75
EXSRV02DB02 — 75
EXSRV02DB03 — 75
EXSRV02DB04 — 75
EXSRV02DB05 — 75
EXSRV02DB06 — 75
EXSRV02DB07 — 75
EXSRV02DB08 — 75
EXSRV02DB09 — 75
EXSRV02DB10 — 75
EXSRV02DB11 — 75
EXSRV02DB12 — 75
EXSRV02DB13 — 75
EXSRV02DB14 — 75
EXSRV02DB15 — 75
EXSRV02DB16 — 75
EXSRV02DB17 — 75
EXSRV02DB18 — 75
EXSRV02DB19 — 75
EXSRV02DB20 — 75
EXSRV02DB21 — 75
EXSRV02DB22 — 75
EXSRV02DB23 — 75
EXSRV02DB24 — 75
EXSRV06DB01 — 75
EXSRV06DB02 — 118
EXSRV06DB03 — 116
EXSRV06DB04 — 114
EXSRV06DB05 — 111
EXSRV06DB06 — 109
EXSRV06DB09 — 107
EXSRV06DB07 — 105
EXSRV06DB08 — 103
EXSRV06DB10 — 101
EXSRV06DB11 — 98
EXSRV06DB12 — 96
EXSRV06DB13 — 93
EXSRV06DB14 — 90
EXSRV06DB16 — 88
EXSRV06DB20 — 86
EXSRV06DB17 — 83
EXSRV06DB18 — 77
EXSRV06DB19 — 27
EXSRV06DB15
EXSRV06DB21
EXSRV06DB22 — 2
EXSRV06DB23
EXSRV06DB24
Writing Powershell file ‘.\moves1-2to6.txt’
Steve,
Stretching my weak powershell skills to their limits I managed to do all the inclusions/exclusions and divide everything in half. Half of my existing servers coupled with half the new in each new set. Same results but only half as much 🙂 Same deal. It excludes most, not all of the new databases. We’ve done get-mailboxdatabase |fl side by side between working and non-working db’s and their identical. All databases were created with standard script as you can imagine what a chore it would be manually.
Any ideas? Thanks for your help.
Found 9636 mailboxes across 132 databases. Aiming for 73 mailboxes per database.
Sorting Databases into over, under and perfectly allocated.
Found 84 over, 48 under and 0 perfectly allocated
Generating Powershell File ‘.\moves.ps1’ to Balance DBs.
DB Counts will be as follows after executing .\moves.ps1
Steve,
Thanks for getting back to me. How would I limit? I am excluding a dozen resource account databases. I was trying to figure out a way to try and have it see half of our server and do the balancing against it only. I guess the challenge is how to omit some and include only others?
Steve,
This is a fine piece of work. I am so close to getting it working but keep hitting some limit. Below is output that I get from any Exchange 2010 server where I run this. We have a 12 node DAG that just got 4 new nodes introduced and I’m trying to balance those 19705 accounts across 12 servesr rather than the current 8. There are 96 new databases and the script targets 75 per db which makes sense. What is perplexing is that the file it generates 7103 New-MoveRequests but ignores 58 databases and as you can see below it overloads 36 db’s. Have I hit some limit? Any help would be appreciated.
—————————————————————————————————————–
Found 19705 mailboxes across 264 databases. Aiming for 75 mailboxes per database.
Sorting Databases into over, under and perfectly allocated.
Found 168 over, 96 under and 0 perfectly allocated
Generating Powershell File ‘.\moves6.ps1’ to Balance DBs.
DB Counts will be as follows after executing .\moves6.ps1:
EXSRV09DB01 — 75
EXSRV09DB02 — 75
EXSRV09DB03 — 75
EXSRV10DB01 — 75
EXSRV10DB02 — 75
EXSRV10DB03 — 75
EXSRV11DB01 — 75
EXSRV11DB02 — 75
EXSRV11DB03 — 75
EXSRV12DB01 — 75
EXSRV12DB02 — 75
EXSRV12DB03 — 75
EXSRV01DB01 — 75
EXSRV01DB02 — 75
EXSRV01DB03 — 75
EXSRV01DB04 — 75
EXSRV09DB04 — 75
EXSRV09DB05 — 75
EXSRV09DB06 — 75
EXSRV09DB07 — 75
EXSRV09DB08 — 75
EXSRV09DB09 — 75
EXSRV10DB04 — 75
EXSRV10DB05 — 75
EXSRV10DB06 — 75
EXSRV10DB07 — 75
EXSRV10DB08 — 75
EXSRV10DB09 — 75
EXSRV11DB04 — 75
EXSRV11DB07 — 75
EXSRV11DB05 — 75
EXSRV11DB06 — 75
EXSRV11DB09 — 75
EXSRV11DB08 — 75
EXSRV12DB06 — 75
EXSRV12DB05 — 75
EXSRV12DB04 — 75
EXSRV12DB07 — 75
EXSRV12DB08 — 75
EXSRV12DB09 — 75
EXSRV01DB06 — 75
EXSRV01DB10 — 75
EXSRV01DB12 — 75
EXSRV01DB09 — 75
EXSRV01DB07 — 75
EXSRV01DB08 — 75
EXSRV01DB05 — 75
EXSRV01DB11 — 75
EXSRV09DB10 — 75
EXSRV09DB11 — 75
EXSRV09DB12 — 75
EXSRV09DB13 — 75
EXSRV09DB14 — 75
EXSRV09DB15 — 75
EXSRV09DB16 — 75
EXSRV09DB17 — 75
EXSRV09DB18 — 75
EXSRV10DB10 — 75
EXSRV10DB11 — 75
EXSRV10DB12 — 75
EXSRV10DB13 — 75
EXSRV10DB14 — 75
EXSRV10DB15 — 75
EXSRV10DB16 — 75
EXSRV10DB17 — 75
EXSRV10DB18 — 75
EXSRV11DB11 — 75
EXSRV11DB18 — 75
EXSRV11DB13 — 75
EXSRV11DB12 — 75
EXSRV11DB10 — 75
EXSRV11DB16 — 75
EXSRV11DB17 — 75
EXSRV11DB15 — 75
EXSRV11DB14 — 75
EXSRV12DB10 — 75
EXSRV12DB11 — 75
EXSRV12DB12 — 75
EXSRV12DB13 — 75
EXSRV12DB14 — 75
EXSRV12DB15 — 75
EXSRV12DB16 — 75
EXSRV12DB17 — 75
EXSRV12DB18 — 75
EXSRV01DB19 — 75
EXSRV01DB22 — 75
EXSRV01DB15 — 75
EXSRV01DB14 — 75
EXSRV01DB23 — 75
EXSRV01DB17 — 75
EXSRV01DB16 — 75
EXSRV01DB21 — 75
EXSRV01DB20 — 75
EXSRV01DB13 — 75
EXSRV01DB18 — 75
EXSRV01DB24 — 75
EXSRV02DB01 — 75
EXSRV02DB02 — 75
EXSRV02DB03 — 75
EXSRV02DB04 — 75
EXSRV02DB05 — 75
EXSRV02DB06 — 75
EXSRV02DB07 — 75
EXSRV02DB08 — 75
EXSRV02DB09 — 75
EXSRV02DB10 — 75
EXSRV02DB11 — 75
EXSRV02DB12 — 75
EXSRV02DB13 — 75
EXSRV02DB14 — 75
EXSRV02DB15 — 75
EXSRV02DB16 — 75
EXSRV02DB17 — 75
EXSRV02DB18 — 75
EXSRV02DB19 — 75
EXSRV02DB20 — 75
EXSRV02DB21 — 75
EXSRV02DB22 — 75
EXSRV02DB23 — 75
EXSRV02DB24 — 75
EXSRV03DB01 — 75
EXSRV03DB02 — 75
EXSRV03DB03 — 75
EXSRV03DB04 — 75
EXSRV03DB05 — 75
EXSRV03DB06 — 75
EXSRV03DB07 — 75
EXSRV03DB08 — 75
EXSRV03DB09 — 75
EXSRV03DB10 — 75
EXSRV03DB11 — 75
EXSRV03DB12 — 75
EXSRV03DB13 — 75
EXSRV03DB14 — 75
EXSRV03DB15 — 75
EXSRV03DB16 — 75
EXSRV03DB17 — 75
EXSRV03DB18 — 75
EXSRV03DB19 — 75
EXSRV03DB20 — 75
EXSRV03DB21 — 75
EXSRV03DB23 — 75
EXSRV03DB22 — 75
EXSRV03DB24 — 75
EXSRV08DB01 — 75
EXSRV08DB02 — 75
EXSRV08DB03 — 75
EXSRV08DB04 — 75
EXSRV08DB05 — 75
EXSRV08DB06 — 75
EXSRV08DB07 — 75
EXSRV08DB08 — 75
EXSRV08DB09 — 75
EXSRV08DB10 — 75
EXSRV08DB11 — 75
EXSRV08DB12 — 75
EXSRV08DB13 — 75
EXSRV08DB14 — 75
EXSRV08DB15 — 75
EXSRV08DB16 — 75
EXSRV08DB17 — 75
EXSRV08DB18 — 75
EXSRV08DB19 — 75
EXSRV08DB20 — 75
EXSRV08DB21 — 75
EXSRV08DB22 — 75
EXSRV08DB23 — 75
EXSRV08DB24 — 75
EXSRV04DB01 — 75
EXSRV04DB02 — 240
EXSRV04DB03 — 238
EXSRV04DB04 — 237
EXSRV04DB05 — 236
EXSRV04DB06 — 234
EXSRV04DB07 — 233
EXSRV04DB08 — 231
EXSRV04DB09 — 230
EXSRV04DB10 — 227
EXSRV04DB11 — 225
EXSRV04DB12 — 223
EXSRV04DB13 — 220
EXSRV04DB14 — 218
EXSRV04DB15 — 216
EXSRV04DB16 — 214
EXSRV04DB17 — 212
EXSRV04DB18 — 210
EXSRV04DB19 — 208
EXSRV04DB20 — 206
EXSRV04DB21 — 204
EXSRV04DB22 — 200
EXSRV04DB23 — 195
EXSRV04DB24 — 191
EXSRV05DB06 — 185
EXSRV05DB02 — 180
EXSRV05DB08 — 176
EXSRV05DB09 — 173
EXSRV05DB04 — 169
EXSRV05DB03 — 161
EXSRV05DB05 — 155
EXSRV05DB07 — 150
EXSRV05DB01 — 143
EXSRV05DB14 — 132
EXSRV05DB12 — 112
EXSRV05DB11 — 106
EXSRV05DB10 — 90
EXSRV05DB15 — 50
EXSRV05DB16
EXSRV05DB17
EXSRV05DB13
EXSRV05DB18
EXSRV05DB19
EXSRV05DB20
EXSRV05DB24
EXSRV05DB21
EXSRV05DB22
EXSRV05DB23
EXSRV07DB03
EXSRV07DB01
EXSRV07DB02
EXSRV07DB04
EXSRV07DB05
EXSRV07DB06
EXSRV07DB07
EXSRV07DB08
EXSRV07DB09
EXSRV07DB10
EXSRV07DB11
EXSRV07DB12
EXSRV07DB13
EXSRV07DB14
EXSRV07DB15
EXSRV07DB16
EXSRV07DB17
EXSRV07DB18
EXSRV07DB19
EXSRV07DB20
EXSRV07DB21
EXSRV07DB22
EXSRV07DB24
EXSRV07DB23
EXSRV06DB01
EXSRV06DB02
EXSRV06DB03
EXSRV06DB04
EXSRV06DB05
EXSRV06DB06
EXSRV06DB07
EXSRV06DB08
EXSRV06DB09
EXSRV06DB10
EXSRV06DB11
EXSRV06DB12
EXSRV06DB13
EXSRV06DB14
EXSRV06DB16
EXSRV06DB20
EXSRV06DB17
EXSRV06DB18
EXSRV06DB19
EXSRV06DB15
EXSRV06DB21
EXSRV06DB22
EXSRV06DB23
EXSRV06DB24
Writing Powershell file ‘.\moves.ps1’
—————————————————————————————————————–
Hiya,
I’ve not tried the script on that many mailboxes and wouldn’t recommend running that many move requests in one go (though, I must admit the script shouldn’t have went wrong).
Do you have any better success if you limit the number of databases, perhaps balancing 1-10, 11, 20 etc?
Steve
Hi Steve,
We have 6 databases in all, but they are in pairs. Just for an example say there are two on Solid state drives, two on Fiber channel 15K and 2 on SATA. What would I have to do to get your script to balance mailboxes across two server but just within two specific databases?
In case that isn’t completely clear here is an example:
Server 1 databases: SS-Server1-DB1, FC-Server1-DB1, SATA-Server1-DB1
Server 2 databases: SS-Server2-DB1, FC-Server2-DB1, SATA-Server2-DB1
I would like to balance the mailboxes between the two SS* databases, then the mailboxes between the two FC* databases, and finally the mailboxes between the two SATA* databases.
Thanks for your assistance.
Greg
Hi Steve,
Do you have any information on how to balance the databases based on mailbox size and only on a select list of databases? Thanks for all you do.
Hi Steve,
I did notice one issue when the script generates the list of moves. Currently it uses the Identity of each user which seems to the OU plus CN. We have some users with parenthesis in the name of the OU where their mailbox resides which causes the script to fail with the following error:
The term ‘Sales’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spell
ing of the name, or if a path was included, verify that the path is correct and try again.
At C:\Tech\Scripts\PowerShell\dbmoves.ps1:41 char:83
+ New-MoveRequest -Identity ‘domain.com/Corp/Users/HQ (Sales <<<< )/Smith, Tom' -TargetDat
abase 'DB15'
+ CategoryInfo : ObjectNotFound: (Sales:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Is there any way to have it output the user name via PrimarySMTPAddress in the move script?
Thanks,
-Devon
Hi Devon
Have mailed you an update
Steve
Hi Steve
Great script. Any news on a script that are able to relocate based on size 🙂
Thanks,
Peter
I will have to do that soon, won’t I.. And take into account archive mailboxes, too. It is on my list – the new year has been pretty busy so far so just getting a handle again on the blog 🙂
Steve
Hi,
thanks for your script . I tried and it work but there is a small issue while running moves.ps1 in exchange 2007 environments . so issue is that for every mailbox move it prompts for yes or No input. so can you help me with that so that all i can do without changing anything in moves.ps1. or there is any way to add -confirm :$false in each line while generating the script.
Hi Steve,
Great script! Is it possible to get the reverse, balance mailbox databases based on mailbox size not count for Exchange 2010?
Cheers,
Alan
Hi Alan,
Glad you like it. I’d been thinking the same thing – it would be useful to balance based on size instead of mailbox numbers.
Balancing on mailbox numbers has a basis in each DB’s underlying LUN being fully provisioned to be able to support full quotas for each mailbox. However another approach could be to add storage and additional DBs as mailboxes grow toward their quotas, and this would require re-balancing the databases based on size as you suggest.
So – It’s added to my to-do list 🙂
Steve
Did you ever have a chance to add Mailbox Size as the balancing factor instead of just count?
Hi Steve,
I enjoy reading your blog. I’m trying to come up with a script to do something similar to this one. Our helpdesk creates all new mailboxes in one SG (Staging) and then we spread them out among the other SG’s. to balance them. I would like to automate this task to move them to the least populated SG’s, similar to what you are doing with these scripts.
Hey Randy,
It shouldn’t be too hard to change the script to do what you want, if it won’t out of the box. Are you trying to empty out the staging SG on each run of the script?
Steve
Hi Steve,
That is exactly what we would like to do…
Randy
Oh, and I should point out that we are running Exchange 2007.
Hey Randy,
I’ll take a look and if needed update the script/add extra info. Might be in a couple of days tho!
Steve
Not really good with the scripting thing but i need to do this load balancing across top 2 exchange 2007 servers with 4 storage groups each. How would i achieve this using your scripts
Hi Lamont,
You would use Example three from above:
$o=Get-MailboxDatabase | where {$_.Server -eq “serverone” -or $_.Server -eq “servertwo”}
.\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false
Also, if you are using Powershell V1 and not Powershell V2 you will need to do this:
Change the first bit of the script up until “# Check for Exchange cmdlets” to:
param($DBs,$OutputPowershellFile,$Exchange2010=$true)
# Check for Exchange cmdlets
Steve
I just signed up to your blogs rss feed. Will you post more on this subject?
Yes sure, let me know what you are interested in finding out.
interesting, thanks
Hi Steve,
Thanks again – this worked, although with a slight modification:
I changed it to:
$o=Get-MailboxDatabase -server mkt-mbx01 | where-object {$_.name -ne “Mailbox Database”}
This excludes the first storage group’s mailbox DB successfully from the calculations for balancing the mailboxes.
Thanks once again for all your help – I’m learning more from you about Powershell scripting than I have from numerous books!
Sam
Hi Sam,
Happy to help 🙂 Glad all is working the way you want.
Steve
Hi Steve,
Sorry, one last question: Is there a way to tell the script to exclude one of the Storage Groups when balancing the mailboxes across the DBs? We need to exlude the First Storage Group completely as there is limited disk space available for this and it is only used for service mailboxes etc.
Thanks again,
Sam
Hi Sam,
Would something like this as the bit to get the DBs do what you want?
$o = Get-MailboxDatabase | Where {$_.Storagegroup -ne “The one to exclude”}
Steve
Hi Steve,
It’s working!!! That did the trick, thanks!
I’m planning to split the move script that’s generated into blocks of 100 mailboxes as we have around 1000 mailboxes to move (our old Exchange admin decided to tell the people creating mailboxes to create them all in one storage group for some reason leaving us with one SG with over 1800 mailboxes!!). Obviously we’ve got a fair amount of work to do to tell these users when we’ll be moving their mailboxes and to then schedule the appropriate scripts to run.
Thanks so much for your help with this – it’s saved us a huge amount of work!
Sam
This script looks like it’ll sort out a number of problems we’re having with the distribution of our mailboxes across our storage groups. We’ve got a SCR clustered Exchange 2007 environment and I’ve tried running your script but it fails immediately with the following error:
Unable to find type [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$fa
lse,HelpMessage=”Mailbox database object”)]: make sure that the assembly contai
ning this type is loaded.
To run the script I first typed:
$o=Get-MailboxDatabase -Server servername
followed by:
.\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false
Apologies, I’m far from a powershell expert – more like a novice! Any help you could provide though would be great as this script is exactly the answer to our problems!
Thanks in advance,
Sam
I’ll take a look – I did test on 2007 but will have another go. I tested on Powershell 2.0 so wonder if that is the issue..
Steve
Hi Steve,
Many thanks! I’ll wait to hear from you – let me know if you need any more information about our environment etc. though.
Sam
Hiya,
It looks like it’s a Powershell 1.0 issue – as a quick hack try the following:
Change the first bit of the script up until “# Check for Exchange cmdlets” to:
param($DBs,$OutputPowershellFile,$Exchange2010=$true)
# Check for Exchange cmdlets
This takes out some of the get-help compatibility and prompting for values, but assuming you put the right values (like you did above) it looks like it works fine on Win 2003 Ent + Exchange 2007 SP3 + Powershell 1.0.
Steve