diff --git src/wp-admin/includes/admin-filters.php src/wp-admin/includes/admin-filters.php
index d0709f4..2787736 100644
--- src/wp-admin/includes/admin-filters.php
+++ src/wp-admin/includes/admin-filters.php
@@ -100,6 +100,7 @@ add_action( 'profile_update', 'default_password_nag_edit_user', 10, 2 );
 // Update hooks.
 add_action( 'admin_init', 'wp_plugin_update_rows' );
 add_action( 'admin_init', 'wp_theme_update_rows'  );
+add_action( 'admin_init', 'maybe_split_shared_terms' );
 
 add_action( 'admin_notices', 'update_nag',      3  );
 add_action( 'admin_notices', 'maintenance_nag', 10 );
diff --git src/wp-admin/includes/schema.php src/wp-admin/includes/schema.php
index 95ee375..e8f3037 100644
--- src/wp-admin/includes/schema.php
+++ src/wp-admin/includes/schema.php
@@ -496,6 +496,9 @@ function populate_options() {
 
 	// 3.5
 	'link_manager_enabled' => 0,
+
+	// 4.3
+	'shared_terms_split' => 0,
 	);
 
 	// 3.3
diff --git src/wp-admin/includes/taxonomy.php src/wp-admin/includes/taxonomy.php
index 4f11bdb..783125e 100644
--- src/wp-admin/includes/taxonomy.php
+++ src/wp-admin/includes/taxonomy.php
@@ -288,3 +288,92 @@ function wp_create_term($tag_name, $taxonomy = 'post_tag') {
 
 	return wp_insert_term($tag_name, $taxonomy);
 }
+
+/**
+ * Split existing shared taxonomy terms, if necessary.
+ *
+ * @since 4.3.0
+ */
+function maybe_split_shared_terms() {
+	if ( ! current_user_can( 'update_core' ) ) {
+		return;
+	}
+
+	if ( get_option( 'shared_terms_split' ) ) {
+		return;
+	}
+
+	update_option( 'shared_terms_split', 1 );
+	split_all_shared_terms();
+}
+
+/**
+ * Splits all shared taxonomy terms.
+ *
+ * @since 4.3.0
+ *
+ * @global wpdb $wpdb WordPress database abstraction object.
+ */
+function split_all_shared_terms() {
+	global $wpdb;
+
+	// Get a list of shared terms (those with more than one associated row in term_taxonomy).
+	$shared_terms = $wpdb->get_results(
+		"SELECT tt.term_id, t.*, count(*) as term_tt_count FROM {$wpdb->term_taxonomy} tt
+		 LEFT JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
+		 GROUP BY t.term_id
+		 HAVING term_tt_count > 1"
+	);
+
+	if ( empty( $shared_terms ) ) {
+		return;
+	}
+
+	// Rekey shared term array for faster lookups.
+	$_shared_terms = array();
+	foreach ( $shared_terms as $shared_term ) {
+		$term_id = intval( $shared_term->term_id );
+		$_shared_terms[ $term_id ] = $shared_term;
+	}
+	$shared_terms = $_shared_terms;
+
+	// Get term taxonomy data for all shared terms.
+	$shared_term_ids = implode( ',', array_keys( $shared_terms ) );
+	$shared_tts = $wpdb->get_results( "SELECT * FROM {$wpdb->term_taxonomy} WHERE `term_id` IN ({$shared_term_ids})" );
+
+	// Split term data recording is slow, so we do it just once, outside the loop.
+	$suspend = wp_suspend_cache_invalidation( true );
+	$split_term_data = get_option( '_split_terms', array() );
+	$skipped_first_term = $taxonomies = array();
+	foreach ( $shared_tts as $shared_tt ) {
+		$term_id = intval( $shared_tt->term_id );
+
+		// Don't split the first tt belonging to a given term_id.
+		if ( ! isset( $skipped_first_term[ $term_id ] ) ) {
+			$skipped_first_term[ $term_id ] = 1;
+			continue;
+		}
+
+		if ( ! isset( $split_term_data[ $term_id ] ) ) {
+			$split_term_data[ $term_id ] = array();
+		}
+
+		// Keep track of taxonomies whose hierarchies need flushing.
+		if ( ! isset( $taxonomies[ $shared_tt->taxonomy ] ) ) {
+			$taxonomies[ $shared_tt->taxonomy ] = 1;
+		}
+
+		// Split the term.
+		$split_term_data[ $term_id ][ $shared_tt->taxonomy ] = _split_shared_term( $shared_terms[ $term_id ], $shared_tt, false );
+	}
+
+	// Rebuild the cached hierarchy for each affected taxonomy.
+	foreach ( array_keys( $taxonomies ) as $tax ) {
+		delete_option( "{$tax}_children" );
+		_get_term_hierarchy( $tax );
+	}
+
+	wp_suspend_cache_invalidation( $suspend );
+	update_option( '_split_terms', $split_term_data );
+	update_option( 'shared_terms_split', 1 );
+}
diff --git src/wp-admin/includes/upgrade.php src/wp-admin/includes/upgrade.php
index 86c6f9a..221c7e8 100644
--- src/wp-admin/includes/upgrade.php
+++ src/wp-admin/includes/upgrade.php
@@ -1505,10 +1505,6 @@ function upgrade_430() {
 		upgrade_430_fix_comments();
 	}
 
-	if ( $wp_current_db_version < 32814 ) {
-		split_all_shared_terms();
-	}
-
 	if ( $wp_current_db_version < 33055 && 'utf8mb4' === $wpdb->charset ) {
 		if ( is_multisite() ) {
 			$tables = $wpdb->tables( 'blog' );
@@ -1519,7 +1515,7 @@ function upgrade_430() {
 				$tables = array_diff_assoc( $tables, $global_tables );
 			}
 		}
-	
+
 		foreach ( $tables as $table ) {
 			maybe_convert_table_to_utf8mb4( $table );
 		}
@@ -1881,76 +1877,6 @@ function maybe_convert_table_to_utf8mb4( $table ) {
 }
 
 /**
- * Splits all shared taxonomy terms.
- *
- * @since 4.3.0
- *
- * @global wpdb $wpdb WordPress database abstraction object.
- */
-function split_all_shared_terms() {
-	global $wpdb;
-
-	// Get a list of shared terms (those with more than one associated row in term_taxonomy).
-	$shared_terms = $wpdb->get_results(
-		"SELECT tt.term_id, t.*, count(*) as term_tt_count FROM {$wpdb->term_taxonomy} tt
-		 LEFT JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
-		 GROUP BY t.term_id
-		 HAVING term_tt_count > 1"
-	);
-
-	if ( empty( $shared_terms ) ) {
-		return;
-	}
-
-	// Rekey shared term array for faster lookups.
-	$_shared_terms = array();
-	foreach ( $shared_terms as $shared_term ) {
-		$term_id = intval( $shared_term->term_id );
-		$_shared_terms[ $term_id ] = $shared_term;
-	}
-	$shared_terms = $_shared_terms;
-
-	// Get term taxonomy data for all shared terms.
-	$shared_term_ids = implode( ',', array_keys( $shared_terms ) );
-	$shared_tts = $wpdb->get_results( "SELECT * FROM {$wpdb->term_taxonomy} WHERE `term_id` IN ({$shared_term_ids})" );
-
-	// Split term data recording is slow, so we do it just once, outside the loop.
-	$suspend = wp_suspend_cache_invalidation( true );
-	$split_term_data = get_option( '_split_terms', array() );
-	$skipped_first_term = $taxonomies = array();
-	foreach ( $shared_tts as $shared_tt ) {
-		$term_id = intval( $shared_tt->term_id );
-
-		// Don't split the first tt belonging to a given term_id.
-		if ( ! isset( $skipped_first_term[ $term_id ] ) ) {
-			$skipped_first_term[ $term_id ] = 1;
-			continue;
-		}
-
-		if ( ! isset( $split_term_data[ $term_id ] ) ) {
-			$split_term_data[ $term_id ] = array();
-		}
-
-		// Keep track of taxonomies whose hierarchies need flushing.
-		if ( ! isset( $taxonomies[ $shared_tt->taxonomy ] ) ) {
-			$taxonomies[ $shared_tt->taxonomy ] = 1;
-		}
-
-		// Split the term.
-		$split_term_data[ $term_id ][ $shared_tt->taxonomy ] = _split_shared_term( $shared_terms[ $term_id ], $shared_tt, false );
-	}
-
-	// Rebuild the cached hierarchy for each affected taxonomy.
-	foreach ( array_keys( $taxonomies ) as $tax ) {
-		delete_option( "{$tax}_children" );
-		_get_term_hierarchy( $tax );
-	}
-
-	wp_suspend_cache_invalidation( $suspend );
-	update_option( '_split_terms', $split_term_data );
-}
-
-/**
  * Retrieve all options as it was for 1.2.
  *
  * @since 1.2.0
@@ -2690,7 +2616,7 @@ endif;
 
 /**
  * Determine if global tables should be upgraded.
- * 
+ *
  * This function performs a series of checks to ensure the environment allows
  * for the safe upgrading of global WordPress database tables. It is necessary
  * because global tables will commonly grow to millions of rows on large
