SharePoint 2016 / 2019 / SE – Use PowerShell to Sync user data from UPA to sites

Some Background:

Since pretty much the beginning of SharePoint, user profile synchronization has been a two-step process:

1. Import user data from Active Directory to the User Profile Service Application (UPA).

2. Push that user data from the UPA down to each site collection.

Step 2 is our focus here, and is automatically done by the “User Profile to SharePoint Full Synchronization” timer job. This part of the “sync” process is also known as “WSSSync” or “ProfSync”.

More about the timer job:

  • It copies important user profile data (display name, title, email address, etc) from the UPA down to each site collections User Information List, so it can be utilized within the site.
  • By default, it runs every 5 minutes, but like pretty much all timer jobs, if the previous instance is still running, the next instance will be skipped.
  • Although it has the word “Full” in its name, it actually does more of an “Incremental” sync most of the time, meaning it only synchronizes user data for users that have had updates to their user profiles in the UPA.
  • If a site collection is new, has had its sync data cleared, or failed on the last sync, it will be marked for a Full sync on the next go-round.
  • It’s pretty much single threaded, meaning that it only runs on one server at a time, and only processes one site collection at a time, in serial fashion.
  • Barring farm-level changes, it always processes each web application, each content database, and each site collection in the same order.

Those last few points can add up to a problem in some cases. In large farms where you may have hundreds of thousands of users in some site collections, it can take it a very long time to process those site collections. What’s worse is that if it should fail for any reason, it marks that site collection as needing a Full sync. Because it processes the sites in the same order each time, if it keeps failing on the same site collection, it may never move on to process the other sites.

The point of this post:

Is to show that you don’t have to solely rely on the timer job. You can take matters into your own hands and synchronize the site collections in any order you choose. This can be especially helpful when you’re troubleshooting the Sync process. User ‘Mary’ still shows her ‘old’ job title in site collection ‘X’ ? No problem, you can schedule that site for a Full sync and then run a synchronization for its content database.

You do this with PowerShell, calling SharePoint object code (OM) code.

Important! In order for this to work, you must first make sure the “User Profile to SharePoint Full Synchronization” timer job is stopped and disabled. If it is in the ‘running’ state when you try to start a manual sync, your manual sync will be aborted. You will see a message like this in the ULS logs:

    PowerShell_ISE.exe (0x2B84) 0x6280 SharePoint Portal Server User Profiles a86n5 Medium OMLog1000000001 WebApp Team Sites(A4b55bb6-7a38-43dd-8d5b-7c164bcaeec3), ContentDB Teams_Content(Aa507fe0-42f1-4827-a098-c6323e34aff3): SynchContentDB is already in progress for this DB, aborting further progress.

To start a manual Sync, first, you would schedule a site for Full sync like this:

$siteURL = "https://site1.contoso.com"
get-spsite $siteURL | % {[Microsoft.Office.Server.UserProfiles.WSSProfileSynch]::ScheduleSiteForFullSynchronization($_); $_.Close() }

Then, you can run the synchronization via object model code, which will run the sync within PowerShell.exe instead of the Timer service (owstimer.exe).

You can target the content database for the site collection you want to Sync:

$db = (Get-SPSite https://site1.contoso.com).contentdatabase
[Microsoft.Office.Server.UserProfiles.WSSProfileSynch]::SynchronizeContentDatabase($db)

You can also pass it an entire web application to sync, in which case, it will sync all content databases within that web app:

$wa = Get-SPWebApplication "https://site1.contoso.com"
[Microsoft.Office.Server.UserProfiles.WSSProfileSynch]::SynchronizeWebApplication($wa)

Or just pass it a single content database:

$db = Get-SPContentDatabase -WebApplication https://site1.contoso.com | ? {$_.name -match "16_Site1_Content"}
[Microsoft.Office.Server.UserProfiles.WSSProfileSynch]::SynchronizeContentDatabase($db)

If you put it all together, you can target a specific site easily like this:

#Specify your site:
$site = get-spsite "https://site1.contoso.com"
#Schedule that site for a Full Sync:
$site | % {[Microsoft.Office.Server.UserProfiles.WSSProfileSynch]::ScheduleSiteForFullSynchronization($_); $_.Close() }
#Run the Synchronization for the content database that stores that site:
[Microsoft.Office.Server.UserProfiles.WSSProfileSynch]::SynchronizeContentDatabase($site.contentdatabase)

The sync that is triggered will run within PowerShell (instead of within the timer job), and you’ll see info about the sync logged in the SharePoint ULS logs, with messages starting with “OMLog”. For example:

PowerShell_ISE.exe (0x1B58)        0x1090        SharePoint Portal Server        User Profiles        ohvm        Medium        OMLog4000000001 WebApp SharePoint – 80 – J16(a21642ee-d768-4301-acba-7c09ad69f7ad), ContentDB 16_J16_Content(089fcf46-7d1f-4667-816c-ab59c8576bc3): Beginning synch of ContentDB        ad1afa3d-0449-0003-7936-21ad4904d601

PowerShell_ISE.exe (0x1B58)        0x1090        SharePoint Portal Server        User Profiles        adbpn        Medium        OMLog4000000002 WebApp SharePoint – 80 – J16(a21642ee-d768-4301-acba-7c09ad69f7ad), ContentDB 16_J16_Content(089fcf46-7d1f-4667-816c-ab59c8576bc3): 1 new sites were schedule for a full sync in database 089fcf46-7d1f-4667-816c-ab59c8576bc3.        ad1afa3d-0449-0003-7936-21ad4904d601

PowerShell_ISE.exe (0x1B58)        0x1090        SharePoint Portal Server        User Profiles        adbp8        Medium        OMLog4000000003 WebApp SharePoint – 80 – J16(a21642ee-d768-4301-acba-7c09ad69f7ad), ContentDB 16_J16_Content(089fcf46-7d1f-4667-816c-ab59c8576bc3), Site https://site1.contoso.com: First time synchronizing site – getting users to synch        ad1afa3d-0449-0003-7936-21ad4904d601

PowerShell_ISE.exe (0x1B58)        0x1090        SharePoint Portal Server        User Profiles        ohvp        Medium        OMLog4000000011 WebApp SharePoint – 80 – J16(a21642ee-d768-4301-acba-7c09ad69f7ad), ContentDB 16_J16_Content(089fcf46-7d1f-4667-816c-ab59c8576bc3): Finished synch of ContentDB.        ad1afa3d-0449-0003-7936-21ad4904d601

Closing thoughts:

Advantages of the PowerShell method:

  • You can control which sites are forced to do a Full sync.
  • You can sync sites in whatever order you choose.
  • You can essentially multi-thread the Sync process. You could run multiple instances of PowerShell on the same server or run instances on multiple servers in the farm. As long as you make some effort to ensure that no two instances will try to sync the same content database at the same time, and that you’re not running so many instances as to overwhelm the UPA, it should work. HOWEVER, please keep in mind that every process has a bottleneck. In your particular environment, it’s quite possible that running two parallel instances may not be any faster than running a single instance and syncing content databases serially.

Note:

This is not meant to replace the “User Profile to SharePoint Full Synchronization” timer job. It’s more useful when troubleshooting a WSS Sync problem. Once you get the synchronization caught up / straightened out, you should reenable the “User Profile to SharePoint Full Synchronization” timer job and let it do its thing.

Add a Comment