Upgrading SharePoint 2010 to the December 2012 CU or Later

10/9/2013: The August 2013 CU Refresh (7106.5002) and later CUs will no longer flag this issue as an “upgrade blocker” during PSConfig in SharePoint 2010. It is still HIGLY recommended that you run Test-SPContentDatabase in SharePoint 2010 before upgrading to SharePoint 2013, having a wide list will cause the content database upgrade to fail.

The SharePoint 2010 December 2012 Cumulative Update (CU) and all subsequent updates introduced an upgrade check that verified all the lists in the farm conformed to the SharePoint 2013 list schema requirements.  If you have any lists in the farm that violate those thresholds, the content database upgrade will fail, as this issue is flagged as an upgrade blocker.  The ONLY resolution is to reduce the number of columns in the list or delete the list (also from the recycle bin) and re-run PSCONFIG to complete the upgrade. 

If your farm is running the Dec 2012 or later CU, I strongly encourage you to execute Test-SPContentDatabase against each of the databases in the farm prior to all CU installations and verify you have no blocking issues.  If your production farm is running a CU prior to the December 2012 CU, the Test-SPContentDatabase cmdlet does not check for list schema threshold violations.  To test a content databases on a farm prior to the December 2012 CU, you will need to use an external SharePoint 2010 farm running the December 2012 CU or higher with the "unattached database” capabilities of Test-SPContentDatabase.  Basically, this is running the Test-SPContentDatabase check from your December 2012 CU or later farm against the database(s) in a remote (older patched) farm.  To do this, you can execute this PowerShell from a SharePoint Management Shell console window (formatted to fit on the screen)

 $sqlServer = "SQL\SP2010"
$database  = "SHAREPOINT02_ENT_SKU_0000_Content"
$userName  = $null
$password  = $null

$ucdb = [Microsoft.SharePoint.Administration.SPContentDatabase]::`
    CreateUnattachedContentDatabase($sqlServer, $database, $userName, $password)
$ucdb | Test-SPContentDatabase 


This PowerShell is fine for a couple of content databases, but if you have several hundred of content databases in your farm, like my customers, this process can be very cumbersome.  There is where we can introduce some additional PowerShell automation to simplify the validation.

 $exportPath = "C:\ContentDatabaseInfo.csv"
$mappings = @()

Get-SPContentDatabase | % { 
    $mapping = New-Object PSObject
    $mapping | Add-Member -MemberType NoteProperty -name "Name"           -Value $_.Name
    $mapping | Add-Member -MemberType NoteProperty -name "DatabaseServer" -Value $_.Server
    $mapping | Add-Member -MemberType NoteProperty -name "UserName"       -Value $_.UserName
    $mapping | Add-Member -MemberType NoteProperty -name "Password"       -Value $_.Password
    $mappings += $mapping
$mappings | Export-Csv $exportPath -NoTypeInformation

The PowerShell above will create a CSV file containing all the database names, SQL instance names, SQL Auth usernames and SQL Auth passwords for all the content databases in the farm.  You need run the above PowerShell on your pre-December 2012 CU farm to generate the CSV file needed as input on your December 2012 CU, or later, SharePoint 2010 farm.

 Import-Csv $exportPath | % { 

        $ucdb = Get-SPContentDatabase `
                    -ConnectAsUnattachedDatabase `
                    -DatabaseName $_.Name `
                    -DatabaseServer $_.DatabaseServer
        $password = ConvertTo-SecureString $_.Password -AsPlainText -Force
        $databaseCredentials = 
            New-Object System.Management.Automation.PSCredential($_.UserName, $password)
        $ucdb = Get-SPContentDatabase `
                    -ConnectAsUnattachedDatabase `
                    -DatabaseName $_.Name `
                    -DatabaseServer $_.DatabaseServer `
                    -DatabaseCredentials $databaseCredentials

    $ucdb | Test-SPContentDatabase

The PowerShell (formatted to fit on the screen) above will enumerate each line in the CSV file created above and execute Test-SPContentDatabase cmdlet against each content database, outputting the information to the PowerShell console.  If you have a lot of databases, you can get fancy and redirect the output into an HTML file you can review later.  The syntax to redirect the cmdlet output to an HTML file, named with the name of the content database, replaces the last line in the script above, and it looks like the following:

 $ucdb | Test-SPContentDatabase | ConvertTo-Html | Out-File "C:\$($_.Name).html"