Index: src/wp-includes/author-template.php
===================================================================
--- src/wp-includes/author-template.php	(revision 38271)
+++ src/wp-includes/author-template.php	(working copy)
@@ -332,8 +332,6 @@
  *
  * @since 1.2.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string|array $args {
  *     Optional. Array or string of default arguments.
  *
@@ -361,8 +359,6 @@
  * @return string|void The output, if echo is set to false.
  */
 function wp_list_authors( $args = '' ) {
-	global $wpdb;
-
 	$defaults = array(
 		'orderby' => 'name', 'order' => 'ASC', 'number' => '',
 		'optioncount' => false, 'exclude_admin' => true,
@@ -379,6 +375,7 @@
 	$query_args['fields'] = 'ids';
 	$authors = get_users( $query_args );
 
+	$wpdb = WP::get( 'wpdb' );
 	$author_count = array();
 	foreach ( (array) $wpdb->get_results( "SELECT DISTINCT post_author, COUNT(ID) AS count FROM $wpdb->posts WHERE " . get_private_posts_cap_sql( 'post' ) . " GROUP BY post_author" ) as $row ) {
 		$author_count[$row->post_author] = $row->count;
@@ -466,14 +463,11 @@
  *
  * @since 3.2.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @return bool Whether or not we have more than one author
  */
 function is_multi_author() {
-	global $wpdb;
-
 	if ( false === ( $is_multi_author = get_transient( 'is_multi_author' ) ) ) {
+		$wpdb = WP::get( 'wpdb' );
 		$rows = (array) $wpdb->get_col("SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 2");
 		$is_multi_author = 1 < count( $rows ) ? 1 : 0;
 		set_transient( 'is_multi_author', $is_multi_author );
Index: src/wp-includes/bookmark.php
===================================================================
--- src/wp-includes/bookmark.php	(revision 38271)
+++ src/wp-includes/bookmark.php	(working copy)
@@ -11,8 +11,6 @@
  *
  * @since 2.1.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|stdClass $bookmark
  * @param string $output Optional. Either OBJECT, ARRAY_N, or ARRAY_A constant
  * @param string $filter Optional, default is 'raw'.
@@ -19,8 +17,6 @@
  * @return array|object|null Type returned depends on $output value.
  */
 function get_bookmark($bookmark, $output = OBJECT, $filter = 'raw') {
-	global $wpdb;
-
 	if ( empty($bookmark) ) {
 		if ( isset($GLOBALS['link']) )
 			$_bookmark = & $GLOBALS['link'];
@@ -33,6 +29,7 @@
 		if ( isset($GLOBALS['link']) && ($GLOBALS['link']->link_id == $bookmark) ) {
 			$_bookmark = & $GLOBALS['link'];
 		} elseif ( ! $_bookmark = wp_cache_get($bookmark, 'bookmark') ) {
+			$wpdb = WP::get( 'wpdb' );
 			$_bookmark = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->links WHERE link_id = %d LIMIT 1", $bookmark));
 			if ( $_bookmark ) {
 				$_bookmark->link_category = array_unique( wp_get_object_terms( $_bookmark->link_id, 'link_category', array( 'fields' => 'ids' ) ) );
@@ -92,8 +89,6 @@
  *
  * @since 2.1.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string|array $args {
  *     Optional. String or array of arguments to retrieve bookmarks.
  *
@@ -115,8 +110,6 @@
  * @return array List of bookmark row objects.
  */
 function get_bookmarks( $args = '' ) {
-	global $wpdb;
-
 	$defaults = array(
 		'orderby' => 'name', 'order' => 'ASC',
 		'limit' => -1, 'category' => '',
@@ -203,6 +196,7 @@
 		}
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$search = '';
 	if ( ! empty( $r['search'] ) ) {
 		$like = '%' . $wpdb->esc_like( $r['search'] ) . '%';
Index: src/wp-includes/canonical.php
===================================================================
--- src/wp-includes/canonical.php	(revision 38271)
+++ src/wp-includes/canonical.php	(working copy)
@@ -31,7 +31,6 @@
  * @global WP_Rewrite $wp_rewrite
  * @global bool $is_IIS
  * @global WP_Query $wp_query
- * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param string $requested_url Optional. The URL that was requested, used to
  *		figure if redirect is needed.
@@ -39,7 +38,7 @@
  * @return string|void The string of the URL, if redirect needed.
  */
 function redirect_canonical( $requested_url = null, $do_redirect = true ) {
-	global $wp_rewrite, $is_IIS, $wp_query, $wpdb, $wp;
+	global $wp_rewrite, $is_IIS, $wp_query, $wp;
 
 	if ( isset( $_SERVER['REQUEST_METHOD'] ) && ! in_array( strtoupper( $_SERVER['REQUEST_METHOD'] ), array( 'GET', 'HEAD' ) ) ) {
 		return;
@@ -98,7 +97,7 @@
 	}
 
 	if ( is_singular() && 1 > $wp_query->post_count && ($id = get_query_var('p')) ) {
-
+		$wpdb = WP::get( 'wpdb' );
 		$vars = $wpdb->get_results( $wpdb->prepare("SELECT post_type, post_parent FROM $wpdb->posts WHERE ID = %d", $id) );
 
 		if ( isset($vars[0]) && $vars = $vars[0] ) {
@@ -204,6 +203,7 @@
 				$redirect['query'] = remove_query_arg('year', $redirect['query']);
 		} elseif ( is_author() && !empty($_GET['author']) && preg_match( '|^[0-9]+$|', $_GET['author'] ) ) {
 			$author = get_userdata(get_query_var('author'));
+			$wpdb = WP::get( 'wpdb' );
 			if ( ( false !== $author ) && $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE $wpdb->posts.post_author = %d AND $wpdb->posts.post_status = 'publish' LIMIT 1", $author->ID ) ) ) {
 				if ( $redirect_url = get_author_posts_url($author->ID, $author->user_nicename) )
 					$redirect['query'] = remove_query_arg('author', $redirect['query']);
@@ -581,14 +581,11 @@
  *
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @return false|string The correct URL if one is found. False on failure.
  */
 function redirect_guess_404_permalink() {
-	global $wpdb;
-
 	if ( get_query_var('name') ) {
+		$wpdb = WP::get( 'wpdb' );
 		$where = $wpdb->prepare("post_name LIKE %s", $wpdb->esc_like( get_query_var('name') ) . '%');
 
 		// if any of post_type, year, monthnum, or day are set, use them to refine the query
Index: src/wp-includes/class-wp-comment-query.php
===================================================================
--- src/wp-includes/class-wp-comment-query.php	(revision 38271)
+++ src/wp-includes/class-wp-comment-query.php	(working copy)
@@ -141,6 +141,8 @@
 		return false;
 	}
 
+	protected $dbh;
+
 	/**
 	 * Constructor.
 	 *
@@ -260,6 +262,8 @@
 	 * }
 	 */
 	public function __construct( $query = '' ) {
+		$this->dbh = WP::get( 'wpdb' );
+
 		$this->query_var_defaults = array(
 			'author_email' => '',
 			'author_url' => '',
@@ -363,13 +367,9 @@
 	 * @since 4.2.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @return int|array List of comments or number of found comments if `$count` argument is true.
 	 */
 	public function get_comments() {
-		global $wpdb;
-
 		$this->parse_query();
 
 		// Parse meta query
@@ -388,7 +388,7 @@
 		// Reparse query vars, in case they were modified in a 'pre_get_comments' callback.
 		$this->meta_query->parse_query_vars( $this->query_vars );
 		if ( ! empty( $this->meta_query->queries ) ) {
-			$this->meta_query_clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this );
+			$this->meta_query_clauses = $this->meta_query->get_sql( 'comment', $this->dbh->comments, 'comment_ID', $this );
 		}
 
 		// $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
@@ -480,12 +480,8 @@
 	 *
 	 * @since 4.4.0
 	 * @access protected
-	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	protected function get_comment_ids() {
-		global $wpdb;
-
 		// Assemble clauses related to 'comment_approved'.
 		$approved_clauses = array();
 
@@ -514,7 +510,7 @@
 						break;
 
 					default :
-						$status_clauses[] = $wpdb->prepare( "comment_approved = %s", $status );
+						$status_clauses[] = $this->dbh->prepare( "comment_approved = %s", $status );
 						break;
 				}
 			}
@@ -537,11 +533,11 @@
 			foreach ( $include_unapproved as $unapproved_identifier ) {
 				// Numeric values are assumed to be user ids.
 				if ( is_numeric( $unapproved_identifier ) ) {
-					$approved_clauses[] = $wpdb->prepare( "( user_id = %d AND comment_approved = '0' )", $unapproved_identifier );
+					$approved_clauses[] = $this->dbh->prepare( "( user_id = %d AND comment_approved = '0' )", $unapproved_identifier );
 
 				// Otherwise we match against email addresses.
 				} else {
-					$approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier );
+					$approved_clauses[] = $this->dbh->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier );
 				}
 			}
 		}
@@ -600,7 +596,7 @@
 
 			// If no valid clauses were found, order by comment_date_gmt.
 			if ( empty( $orderby_array ) ) {
-				$orderby_array[] = "$wpdb->comments.comment_date_gmt $order";
+				$orderby_array[] = "{$this->dbh->comments}.comment_date_gmt $order";
 			}
 
 			// To ensure determinate sorting, always include a comment_ID clause.
@@ -633,12 +629,12 @@
 					$comment_ID_order = 'DESC';
 				}
 
-				$orderby_array[] = "$wpdb->comments.comment_ID $comment_ID_order";
+				$orderby_array[] = "{$this->dbh->comments}.comment_ID $comment_ID_order";
 			}
 
 			$orderby = implode( ', ', $orderby_array );
 		} else {
-			$orderby = "$wpdb->comments.comment_date_gmt $order";
+			$orderby = "{$this->dbh->comments}.comment_date_gmt $order";
 		}
 
 		$number = absint( $this->query_vars['number'] );
@@ -655,22 +651,22 @@
 		if ( $this->query_vars['count'] ) {
 			$fields = 'COUNT(*)';
 		} else {
-			$fields = "$wpdb->comments.comment_ID";
+			$fields = "{$this->dbh->comments}.comment_ID";
 		}
 
 		$post_id = absint( $this->query_vars['post_id'] );
 		if ( ! empty( $post_id ) ) {
-			$this->sql_clauses['where']['post_id'] = $wpdb->prepare( 'comment_post_ID = %d', $post_id );
+			$this->sql_clauses['where']['post_id'] = $this->dbh->prepare( 'comment_post_ID = %d', $post_id );
 		}
 
 		// Parse comment IDs for an IN clause.
 		if ( ! empty( $this->query_vars['comment__in'] ) ) {
-			$this->sql_clauses['where']['comment__in'] = "$wpdb->comments.comment_ID IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['comment__in'] ) ) . ' )';
+			$this->sql_clauses['where']['comment__in'] = "{$this->dbh->comments}.comment_ID IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['comment__in'] ) ) . ' )';
 		}
 
 		// Parse comment IDs for a NOT IN clause.
 		if ( ! empty( $this->query_vars['comment__not_in'] ) ) {
-			$this->sql_clauses['where']['comment__not_in'] = "$wpdb->comments.comment_ID NOT IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['comment__not_in'] ) ) . ' )';
+			$this->sql_clauses['where']['comment__not_in'] = "{$this->dbh->comments}.comment_ID NOT IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['comment__not_in'] ) ) . ' )';
 		}
 
 		// Parse comment parent IDs for an IN clause.
@@ -694,15 +690,15 @@
 		}
 
 		if ( '' !== $this->query_vars['author_email'] ) {
-			$this->sql_clauses['where']['author_email'] = $wpdb->prepare( 'comment_author_email = %s', $this->query_vars['author_email'] );
+			$this->sql_clauses['where']['author_email'] = $this->dbh->prepare( 'comment_author_email = %s', $this->query_vars['author_email'] );
 		}
 
 		if ( '' !== $this->query_vars['author_url'] ) {
-			$this->sql_clauses['where']['author_url'] = $wpdb->prepare( 'comment_author_url = %s', $this->query_vars['author_url'] );
+			$this->sql_clauses['where']['author_url'] = $this->dbh->prepare( 'comment_author_url = %s', $this->query_vars['author_url'] );
 		}
 
 		if ( '' !== $this->query_vars['karma'] ) {
-			$this->sql_clauses['where']['karma'] = $wpdb->prepare( 'comment_karma = %d', $this->query_vars['karma'] );
+			$this->sql_clauses['where']['karma'] = $this->dbh->prepare( 'comment_karma = %d', $this->query_vars['karma'] );
 		}
 
 		// Filtering by comment_type: 'type', 'type__in', 'type__not_in'.
@@ -733,7 +729,7 @@
 						break;
 
 					default:
-						$comment_types[ $operator ][] = $wpdb->prepare( '%s', $type );
+						$comment_types[ $operator ][] = $this->dbh->prepare( '%s', $type );
 						break;
 				}
 			}
@@ -750,13 +746,13 @@
 		}
 
 		if ( '' !== $parent ) {
-			$this->sql_clauses['where']['parent'] = $wpdb->prepare( 'comment_parent = %d', $parent );
+			$this->sql_clauses['where']['parent'] = $this->dbh->prepare( 'comment_parent = %d', $parent );
 		}
 
 		if ( is_array( $this->query_vars['user_id'] ) ) {
 			$this->sql_clauses['where']['user_id'] = 'user_id IN (' . implode( ',', array_map( 'absint', $this->query_vars['user_id'] ) ) . ')';
 		} elseif ( '' !== $this->query_vars['user_id'] ) {
-			$this->sql_clauses['where']['user_id'] = $wpdb->prepare( 'user_id = %d', $this->query_vars['user_id'] );
+			$this->sql_clauses['where']['user_id'] = $this->dbh->prepare( 'user_id = %d', $this->query_vars['user_id'] );
 		}
 
 		// Falsy search strings are ignored.
@@ -780,7 +776,7 @@
 			foreach ( $post_fields as $field_name => $field_value ) {
 				// $field_value may be an array.
 				$esses = array_fill( 0, count( (array) $field_value ), '%s' );
-				$this->sql_clauses['where'][ $field_name ] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ')', $field_value );
+				$this->sql_clauses['where'][ $field_name ] = $this->dbh->prepare( " {$this->dbh->posts}.{$field_name} IN (" . implode( ',', $esses ) . ')', $field_value );
 			}
 		}
 
@@ -801,7 +797,7 @@
 				$join_posts_table = true;
 
 				$esses = array_fill( 0, count( $q_values ), '%s' );
-				$this->sql_clauses['where'][ $field_name ] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ")", $q_values );
+				$this->sql_clauses['where'][ $field_name ] = $this->dbh->prepare( " {$this->dbh->posts}.{$field_name} IN (" . implode( ',', $esses ) . ")", $q_values );
 			}
 		}
 
@@ -830,7 +826,7 @@
 		$join = '';
 
 		if ( $join_posts_table ) {
-			$join .= "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
+			$join .= "JOIN {$this->dbh->posts} ON {$this->dbh->posts}.ID = {$this->dbh->comments}.comment_post_ID";
 		}
 
 		if ( ! empty( $this->meta_query_clauses ) ) {
@@ -840,7 +836,7 @@
 			$this->sql_clauses['where']['meta_query'] = preg_replace( '/^\s*AND\s*/', '', $this->meta_query_clauses['where'] );
 
 			if ( ! $this->query_vars['count'] ) {
-				$groupby = "{$wpdb->comments}.comment_ID";
+				$groupby = "{$this->dbh->comments}.comment_ID";
 			}
 		}
 
@@ -889,7 +885,7 @@
 		}
 
 		$this->sql_clauses['select']  = "SELECT $found_rows $fields";
-		$this->sql_clauses['from']    = "FROM $wpdb->comments $join";
+		$this->sql_clauses['from']    = "FROM {$this->dbh->comments} $join";
 		$this->sql_clauses['groupby'] = $groupby;
 		$this->sql_clauses['orderby'] = $orderby;
 		$this->sql_clauses['limits']  = $limits;
@@ -897,9 +893,9 @@
 		$this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
 
 		if ( $this->query_vars['count'] ) {
-			return intval( $wpdb->get_var( $this->request ) );
+			return intval( $this->dbh->get_var( $this->request ) );
 		} else {
-			$comment_ids = $wpdb->get_col( $this->request );
+			$comment_ids = $this->dbh->get_col( $this->request );
 			return array_map( 'intval', $comment_ids );
 		}
 	}
@@ -910,12 +906,8 @@
 	 *
 	 * @since 4.6.0
 	 * @access private
-	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	private function set_found_comments() {
-		global $wpdb;
-
 		if ( $this->query_vars['number'] && ! $this->query_vars['no_found_rows'] ) {
 			/**
 			 * Filters the query used to retrieve found comment count.
@@ -927,7 +919,7 @@
 			 */
 			$found_comments_query = apply_filters( 'found_comments_query', 'SELECT FOUND_ROWS()', $this );
 
-			$this->found_comments = (int) $wpdb->get_var( $found_comments_query );
+			$this->found_comments = (int) $this->dbh->get_var( $found_comments_query );
 		}
 	}
 
@@ -943,8 +935,6 @@
 	 * @return array
 	 */
 	protected function fill_descendants( $comments ) {
-		global $wpdb;
-
 		$levels = array(
 			0 => wp_list_pluck( $comments, 'comment_ID' ),
 		);
@@ -996,7 +986,7 @@
 
 			if ( $uncached_parent_ids ) {
 				$where = 'WHERE ' . $_where . ' AND comment_parent IN (' . implode( ',', array_map( 'intval', $uncached_parent_ids ) ) . ')';
-				$level_comments = $wpdb->get_results( "SELECT $wpdb->comments.comment_ID, $wpdb->comments.comment_parent {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} ORDER BY comment_date_gmt ASC, comment_ID ASC" );
+				$level_comments = $this->dbh->get_results( "SELECT {$this->dbh->comments}.comment_ID, {$this->dbh->comments}.comment_parent {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} ORDER BY comment_date_gmt ASC, comment_ID ASC" );
 
 				// Cache parent-child relationships.
 				$parent_map = array_fill_keys( $uncached_parent_ids, array() );
@@ -1067,20 +1057,16 @@
 	 * @since 3.1.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $string
 	 * @param array $cols
 	 * @return string
 	 */
 	protected function get_search_sql( $string, $cols ) {
-		global $wpdb;
+		$like = '%' . $this->dbh->esc_like( $string ) . '%';
 
-		$like = '%' . $wpdb->esc_like( $string ) . '%';
-
 		$searches = array();
 		foreach ( $cols as $col ) {
-			$searches[] = $wpdb->prepare( "$col LIKE %s", $like );
+			$searches[] = $this->dbh->prepare( "$col LIKE %s", $like );
 		}
 
 		return ' AND (' . implode(' OR ', $searches) . ')';
@@ -1092,14 +1078,10 @@
 	 * @since 4.2.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $orderby Alias for the field to order by.
 	 * @return string|false Value to used in the ORDER clause. False otherwise.
 	 */
 	protected function parse_orderby( $orderby ) {
-		global $wpdb;
-
 		$allowed_keys = array(
 			'comment_agent',
 			'comment_approved',
@@ -1131,12 +1113,12 @@
 
 		$parsed = false;
 		if ( $orderby == $this->query_vars['meta_key'] || $orderby == 'meta_value' ) {
-			$parsed = "$wpdb->commentmeta.meta_value";
+			$parsed = "{$this->dbh->commentmeta}.meta_value";
 		} elseif ( $orderby == 'meta_value_num' ) {
-			$parsed = "$wpdb->commentmeta.meta_value+0";
+			$parsed = "{$this->dbh->commentmeta}.meta_value+0";
 		} elseif ( $orderby == 'comment__in' ) {
 			$comment__in = implode( ',', array_map( 'absint', $this->query_vars['comment__in'] ) );
-			$parsed = "FIELD( {$wpdb->comments}.comment_ID, $comment__in )";
+			$parsed = "FIELD( {$this->dbh->comments}.comment_ID, $comment__in )";
 		} elseif ( in_array( $orderby, $allowed_keys ) ) {
 
 			if ( isset( $meta_query_clauses[ $orderby ] ) ) {
@@ -1143,7 +1125,7 @@
 				$meta_clause = $meta_query_clauses[ $orderby ];
 				$parsed = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) );
 			} else {
-				$parsed = "$wpdb->comments.$orderby";
+				$parsed = "{$this->dbh->comments}.$orderby";
 			}
 		}
 
Index: src/wp-includes/class-wp-comment.php
===================================================================
--- src/wp-includes/class-wp-comment.php	(revision 38271)
+++ src/wp-includes/class-wp-comment.php	(working copy)
@@ -183,14 +183,10 @@
 	 * @access public
 	 * @static
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int $id Comment ID.
 	 * @return WP_Comment|false Comment object, otherwise false.
 	 */
 	public static function get_instance( $id ) {
-		global $wpdb;
-
 		$comment_id = (int) $id;
 		if ( ! $comment_id ) {
 			return false;
@@ -199,6 +195,7 @@
 		$_comment = wp_cache_get( $comment_id, 'comment' );
 
 		if ( ! $_comment ) {
+			$wpdb = WP::get( 'wpdb' );
 			$_comment = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment_id ) );
 
 			if ( ! $_comment ) {
Index: src/wp-includes/class-wp-meta-query.php
===================================================================
--- src/wp-includes/class-wp-meta-query.php	(revision 38271)
+++ src/wp-includes/class-wp-meta-query.php	(working copy)
@@ -105,6 +105,8 @@
 	 */
 	protected $has_or_relation = false;
 
+	protected $dbh;
+
 	/**
 	 * Constructor.
 	 *
@@ -137,6 +139,8 @@
 	 * }
 	 */
 	public function __construct( $meta_query = false ) {
+		$this->dbh = WP::get( 'wpdb' );
+
 		if ( !$meta_query )
 			return;
 
@@ -484,8 +488,6 @@
 	 * @since 4.1.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param array  $clause       Query clause, passed by reference.
 	 * @param array  $parent_query Parent query array.
 	 * @param string $clause_key   Optional. The array key used to name the clause in the original `$meta_query`
@@ -498,8 +500,6 @@
 	 * }
 	 */
 	public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) {
-		global $wpdb;
-
 		$sql_chunks = array(
 			'where' => array(),
 			'join' => array(),
@@ -537,7 +537,7 @@
 			if ( 'NOT EXISTS' === $meta_compare ) {
 				$join .= " LEFT JOIN $this->meta_table";
 				$join .= $i ? " AS $alias" : '';
-				$join .= $wpdb->prepare( " ON ($this->primary_table.$this->primary_id_column = $alias.$this->meta_id_column AND $alias.meta_key = %s )", $clause['key'] );
+				$join .= $this->dbh->prepare( " ON ($this->primary_table.$this->primary_id_column = $alias.$this->meta_id_column AND $alias.meta_key = %s )", $clause['key'] );
 
 			// All other JOIN clauses.
 			} else {
@@ -581,7 +581,7 @@
 			if ( 'NOT EXISTS' === $meta_compare ) {
 				$sql_chunks['where'][] = $alias . '.' . $this->meta_id_column . ' IS NULL';
 			} else {
-				$sql_chunks['where'][] = $wpdb->prepare( "$alias.meta_key = %s", trim( $clause['key'] ) );
+				$sql_chunks['where'][] = $this->dbh->prepare( "{$alias}.meta_key = %s", trim( $clause['key'] ) );
 			}
 		}
 
@@ -601,25 +601,25 @@
 				case 'IN' :
 				case 'NOT IN' :
 					$meta_compare_string = '(' . substr( str_repeat( ',%s', count( $meta_value ) ), 1 ) . ')';
-					$where = $wpdb->prepare( $meta_compare_string, $meta_value );
+					$where = $this->dbh->prepare( $meta_compare_string, $meta_value );
 					break;
 
 				case 'BETWEEN' :
 				case 'NOT BETWEEN' :
 					$meta_value = array_slice( $meta_value, 0, 2 );
-					$where = $wpdb->prepare( '%s AND %s', $meta_value );
+					$where = $this->dbh->prepare( '%s AND %s', $meta_value );
 					break;
 
 				case 'LIKE' :
 				case 'NOT LIKE' :
-					$meta_value = '%' . $wpdb->esc_like( $meta_value ) . '%';
-					$where = $wpdb->prepare( '%s', $meta_value );
+					$meta_value = '%' . $this->dbh->esc_like( $meta_value ) . '%';
+					$where = $this->dbh->prepare( '%s', $meta_value );
 					break;
 
 				// EXISTS with a value is interpreted as '='.
 				case 'EXISTS' :
 					$meta_compare = '=';
-					$where = $wpdb->prepare( '%s', $meta_value );
+					$where = $this->dbh->prepare( '%s', $meta_value );
 					break;
 
 				// 'value' is ignored for NOT EXISTS.
@@ -628,7 +628,7 @@
 					break;
 
 				default :
-					$where = $wpdb->prepare( '%s', $meta_value );
+					$where = $this->dbh->prepare( '%s', $meta_value );
 					break;
 
 			}
Index: src/wp-includes/class-wp-network-query.php
===================================================================
--- src/wp-includes/class-wp-network-query.php	(revision 38271)
+++ src/wp-includes/class-wp-network-query.php	(working copy)
@@ -86,6 +86,8 @@
 	 */
 	public $max_num_pages = 0;
 
+	protected $dbh;
+
 	/**
 	 * Constructor.
 	 *
@@ -124,6 +126,8 @@
 	 * }
 	 */
 	public function __construct( $query = '' ) {
+		$this->dbh = WP::get( 'wpdb' );
+
 		$this->query_var_defaults = array(
 			'network__in'          => '',
 			'network__not_in'      => '',
@@ -290,8 +294,6 @@
 	 * @return int|array A single count of network IDs if a count query. An array of network IDs if a full query.
 	 */
 	protected function get_network_ids() {
-		global $wpdb;
-
 		$order = $this->parse_order( $this->query_vars['order'] );
 
 		// Disable ORDER BY with 'none', an empty array, or boolean false.
@@ -332,7 +334,7 @@
 
 			$orderby = implode( ', ', $orderby_array );
 		} else {
-			$orderby = "$wpdb->site.id $order";
+			$orderby = "{$this->dbh->site}.id $order";
 		}
 
 		$number = absint( $this->query_vars['number'] );
@@ -349,45 +351,45 @@
 		if ( $this->query_vars['count'] ) {
 			$fields = 'COUNT(*)';
 		} else {
-			$fields = "$wpdb->site.id";
+			$fields = "{$this->dbh->site}.id";
 		}
 
 		// Parse network IDs for an IN clause.
 		if ( ! empty( $this->query_vars['network__in'] ) ) {
-			$this->sql_clauses['where']['network__in'] = "$wpdb->site.id IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['network__in'] ) ) . ' )';
+			$this->sql_clauses['where']['network__in'] = "{$this->dbh->site}.id IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['network__in'] ) ) . ' )';
 		}
 
 		// Parse network IDs for a NOT IN clause.
 		if ( ! empty( $this->query_vars['network__not_in'] ) ) {
-			$this->sql_clauses['where']['network__not_in'] = "$wpdb->site.id NOT IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['network__not_in'] ) ) . ' )';
+			$this->sql_clauses['where']['network__not_in'] = "{$this->dbh->site}.id NOT IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['network__not_in'] ) ) . ' )';
 		}
 
 		if ( ! empty( $this->query_vars['domain'] ) ) {
-			$this->sql_clauses['where']['domain'] = $wpdb->prepare( "$wpdb->site.domain = %s", $this->query_vars['domain'] );
+			$this->sql_clauses['where']['domain'] = $this->dbh->prepare( "{$this->dbh->site}.domain = %s", $this->query_vars['domain'] );
 		}
 
 		// Parse network domain for an IN clause.
 		if ( is_array( $this->query_vars['domain__in'] ) ) {
-			$this->sql_clauses['where']['domain__in'] = "$wpdb->site.domain IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['domain__in'] ) ) . "' )";
+			$this->sql_clauses['where']['domain__in'] = "{$this->dbh->site}.domain IN ( '" . implode( "', '", $this->dbh->_escape( $this->query_vars['domain__in'] ) ) . "' )";
 		}
 
 		// Parse network domain for a NOT IN clause.
 		if ( is_array( $this->query_vars['domain__not_in'] ) ) {
-			$this->sql_clauses['where']['domain__not_in'] = "$wpdb->site.domain NOT IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['domain__not_in'] ) ) . "' )";
+			$this->sql_clauses['where']['domain__not_in'] = "{$this->dbh->site}.domain NOT IN ( '" . implode( "', '", $this->dbh->_escape( $this->query_vars['domain__not_in'] ) ) . "' )";
 		}
 
 		if ( ! empty( $this->query_vars['path'] ) ) {
-			$this->sql_clauses['where']['path'] = $wpdb->prepare( "$wpdb->site.path = %s", $this->query_vars['path'] );
+			$this->sql_clauses['where']['path'] = $this->dbh->prepare( "{$this->dbh->site}.path = %s", $this->query_vars['path'] );
 		}
 
 		// Parse network path for an IN clause.
 		if ( is_array( $this->query_vars['path__in'] ) ) {
-			$this->sql_clauses['where']['path__in'] = "$wpdb->site.path IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['path__in'] ) ) . "' )";
+			$this->sql_clauses['where']['path__in'] = "{$this->dbh->site}.path IN ( '" . implode( "', '", $this->dbh->_escape( $this->query_vars['path__in'] ) ) . "' )";
 		}
 
 		// Parse network path for a NOT IN clause.
 		if ( is_array( $this->query_vars['path__not_in'] ) ) {
-			$this->sql_clauses['where']['path__not_in'] = "$wpdb->site.path NOT IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['path__not_in'] ) ) . "' )";
+			$this->sql_clauses['where']['path__not_in'] = "{$this->dbh->site}.path NOT IN ( '" . implode( "', '", $this->dbh->_escape( $this->query_vars['path__not_in'] ) ) . "' )";
 		}
 
 		// Falsey search strings are ignored.
@@ -394,7 +396,7 @@
 		if ( strlen( $this->query_vars['search'] ) ) {
 			$this->sql_clauses['where']['search'] = $this->get_search_sql(
 				$this->query_vars['search'],
-				array( "$wpdb->site.domain", "$wpdb->site.path" )
+				array( "{$this->dbh->site}.domain", "{$this->dbh->site}.path" )
 			);
 		}
 
@@ -439,7 +441,7 @@
 		}
 
 		$this->sql_clauses['select']  = "SELECT $found_rows $fields";
-		$this->sql_clauses['from']    = "FROM $wpdb->site $join";
+		$this->sql_clauses['from']    = "FROM {$this->dbh->site} $join";
 		$this->sql_clauses['groupby'] = $groupby;
 		$this->sql_clauses['orderby'] = $orderby;
 		$this->sql_clauses['limits']  = $limits;
@@ -447,10 +449,10 @@
 		$this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
 
 		if ( $this->query_vars['count'] ) {
-			return intval( $wpdb->get_var( $this->request ) );
+			return intval( $this->dbh->get_var( $this->request ) );
 		}
 
-		$network_ids = $wpdb->get_col( $this->request );
+		$network_ids = $this->dbh->get_col( $this->request );
 
 		return array_map( 'intval', $network_ids );
 	}
@@ -461,12 +463,8 @@
 	 *
 	 * @since 4.6.0
 	 * @access private
-	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	private function set_found_networks() {
-		global $wpdb;
-
 		if ( $this->query_vars['number'] && ! $this->query_vars['no_found_rows'] ) {
 			/**
 			 * Filters the query used to retrieve found network count.
@@ -478,7 +476,7 @@
 			 */
 			$found_networks_query = apply_filters( 'found_networks_query', 'SELECT FOUND_ROWS()', $this );
 
-			$this->found_networks = (int) $wpdb->get_var( $found_networks_query );
+			$this->found_networks = (int) $this->dbh->get_var( $found_networks_query );
 		}
 	}
 
@@ -488,8 +486,6 @@
 	 * @since 4.6.0
 	 * @access protected
 	 *
-	 * @global wpdb  $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $string  Search string.
 	 * @param array  $columns Columns to search.
 	 *
@@ -496,13 +492,11 @@
 	 * @return string Search SQL.
 	 */
 	protected function get_search_sql( $string, $columns ) {
-		global $wpdb;
+		$like = '%' . $this->dbh->esc_like( $string ) . '%';
 
-		$like = '%' . $wpdb->esc_like( $string ) . '%';
-
 		$searches = array();
 		foreach ( $columns as $column ) {
-			$searches[] = $wpdb->prepare( "$column LIKE %s", $like );
+			$searches[] = $this->dbh->prepare( "$column LIKE %s", $like );
 		}
 
 		return '(' . implode( ' OR ', $searches ) . ')';
@@ -514,14 +508,10 @@
 	 * @since 4.6.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $orderby Alias for the field to order by.
 	 * @return string|false Value to used in the ORDER clause. False otherwise.
 	 */
 	protected function parse_orderby( $orderby ) {
-		global $wpdb;
-
 		$allowed_keys = array(
 			'id',
 			'domain',
@@ -531,12 +521,12 @@
 		$parsed = false;
 		if ( $orderby == 'network__in' ) {
 			$network__in = implode( ',', array_map( 'absint', $this->query_vars['network__in'] ) );
-			$parsed = "FIELD( {$wpdb->site}.id, $network__in )";
+			$parsed = "FIELD( {$this->dbh->site}.id, $network__in )";
 		} elseif ( $orderby == 'domain_length' || $orderby == 'path_length' ) {
 			$field = substr( $orderby, 0, -7 );
-			$parsed = "CHAR_LENGTH($wpdb->site.$field)";
+			$parsed = "CHAR_LENGTH({$this->dbh->site}.$field)";
 		} elseif ( in_array( $orderby, $allowed_keys ) ) {
-			$parsed = "$wpdb->site.$orderby";
+			$parsed = "{$this->dbh->site}.$orderby";
 		}
 
 		return $parsed;
Index: src/wp-includes/class-wp-network.php
===================================================================
--- src/wp-includes/class-wp-network.php	(revision 38271)
+++ src/wp-includes/class-wp-network.php	(working copy)
@@ -87,6 +87,8 @@
 	 */
 	public $site_name = '';
 
+	protected $dbh;
+
 	/**
 	 * Retrieve a network from the database by its ID.
 	 *
@@ -93,14 +95,10 @@
 	 * @since 4.4.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int $network_id The ID of the network to retrieve.
 	 * @return WP_Network|bool The network's object if found. False if not.
 	 */
 	public static function get_instance( $network_id ) {
-		global $wpdb;
-
 		$network_id = (int) $network_id;
 		if ( ! $network_id ) {
 			return false;
@@ -109,6 +107,7 @@
 		$_network = wp_cache_get( $network_id, 'networks' );
 
 		if ( ! $_network ) {
+			$wpdb = WP::get( 'wpdb' );
 			$_network = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->site} WHERE id = %d LIMIT 1", $network_id ) );
 
 			if ( empty( $_network ) || is_wp_error( $_network ) ) {
@@ -137,6 +136,8 @@
 			$this->$key = $value;
 		}
 
+		$this->dbh = WP::get( 'wpdb' );
+
 		$this->_set_site_name();
 		$this->_set_cookie_domain();
 	}
@@ -267,8 +268,6 @@
 	 * @return WP_Network|bool Network object if successful. False when no network is found.
 	 */
 	public static function get_by_path( $domain = '', $path = '', $segments = null ) {
-		global $wpdb;
-
 		$domains = array( $domain );
 		$pieces  = explode( '.', $domain );
 
@@ -295,7 +294,7 @@
 		if ( wp_using_ext_object_cache() ) {
 			$using_paths = wp_cache_get( 'networks_have_paths', 'site-options' );
 			if ( false === $using_paths ) {
-				$using_paths = (int) $wpdb->get_var( "SELECT id FROM {$wpdb->site} WHERE path <> '/' LIMIT 1" );
+				$using_paths = (int) $this->dbh->get_var( "SELECT id FROM {$this->dbh->site} WHERE path <> '/' LIMIT 1" );
 				wp_cache_add( 'networks_have_paths', $using_paths, 'site-options'  );
 			}
 		}
@@ -356,11 +355,11 @@
 		// @todo Consider additional optimization routes, perhaps as an opt-in for plugins.
 		// We already have paths covered. What about how far domains should be drilled down (including www)?
 
-		$search_domains = "'" . implode( "', '", $wpdb->_escape( $domains ) ) . "'";
+		$search_domains = "'" . implode( "', '", $this->dbh->_escape( $domains ) ) . "'";
 
 		if ( ! $using_paths ) {
-			$network = $wpdb->get_row( "
-				SELECT * FROM {$wpdb->site}
+			$network = $this->dbh->get_row( "
+				SELECT * FROM {$this->dbh->site}
 				WHERE domain IN ({$search_domains})
 				ORDER BY CHAR_LENGTH(domain)
 				DESC LIMIT 1
@@ -373,9 +372,9 @@
 			return false;
 
 		} else {
-			$search_paths = "'" . implode( "', '", $wpdb->_escape( $paths ) ) . "'";
-			$networks = $wpdb->get_results( "
-				SELECT * FROM {$wpdb->site}
+			$search_paths = "'" . implode( "', '", $this->dbh->_escape( $paths ) ) . "'";
+			$networks = $this->dbh->get_results( "
+				SELECT * FROM {$this->dbh->site}
 				WHERE domain IN ({$search_domains})
 				AND path IN ({$search_paths})
 				ORDER BY CHAR_LENGTH(domain) DESC, CHAR_LENGTH(path) DESC
Index: src/wp-includes/class-wp-post.php
===================================================================
--- src/wp-includes/class-wp-post.php	(revision 38271)
+++ src/wp-includes/class-wp-post.php	(working copy)
@@ -202,14 +202,10 @@
 	 * @static
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int $post_id Post ID.
 	 * @return WP_Post|false Post object, false otherwise.
 	 */
 	public static function get_instance( $post_id ) {
-		global $wpdb;
-
 		$post_id = (int) $post_id;
 		if ( ! $post_id )
 			return false;
@@ -217,6 +213,7 @@
 		$_post = wp_cache_get( $post_id, 'posts' );
 
 		if ( ! $_post ) {
+			$wpdb = WP::get( 'wpdb' );
 			$_post = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID = %d LIMIT 1", $post_id ) );
 
 			if ( ! $_post )
Index: src/wp-includes/class-wp-registry.php
===================================================================
--- src/wp-includes/class-wp-registry.php	(nonexistent)
+++ src/wp-includes/class-wp-registry.php	(working copy)
@@ -0,0 +1,43 @@
+<?php
+
+class WP_Registry {
+	private $data = array();
+	private static $instance;
+
+	public static function instance() {
+		if ( ! self::$instance ) {
+			self::$instance = new self;
+		}
+		return self::$instance;
+	}
+
+	private function __construct() {}
+
+	private function __clone() {}
+
+	public function get( $key, $global = true ) {
+		if ( $global && array_key_exists( $key, $GLOBALS ) ) {
+			return $GLOBALS[ $key ];
+		} elseif ( array_key_exists( $key, $this->data ) ) {
+			return $this->data[ $key ];
+		}
+
+		return $this->set( $key, null, $global );
+	}
+
+	public function set( $key, $value = null, $global = false ) {
+		if ( null === $value ) {
+			switch ( $key ) {
+			case 'wp_hasher':
+				require_once ABSPATH . WPINC . '/class-phpass.php';
+				$value = new PasswordHash( 8, true );
+				break;
+			}
+		}
+		$this->data[ $key ] = $value;
+		if ( $global ) {
+			$GLOBALS[ $key ] = $this->data[ $key ];
+		}
+		return $value;
+	}
+}
\ No newline at end of file
Index: src/wp-includes/class-wp-rewrite.php
===================================================================
--- src/wp-includes/class-wp-rewrite.php	(revision 38271)
+++ src/wp-includes/class-wp-rewrite.php	(working copy)
@@ -450,12 +450,10 @@
 	 * @since 2.5.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @return array Array of page URIs as first element and attachment URIs as second element.
 	 */
 	public function page_uri_index() {
-		global $wpdb;
+		$wpdb = WP::get( 'wpdb' );
 
 		// Get pages in order of hierarchy, i.e. children after parents.
 		$pages = $wpdb->get_results("SELECT ID, post_name, post_parent FROM $wpdb->posts WHERE post_type = 'page' AND post_status != 'auto-draft'");
Index: src/wp-includes/class-wp-roles.php
===================================================================
--- src/wp-includes/class-wp-roles.php	(revision 38271)
+++ src/wp-includes/class-wp-roles.php	(working copy)
@@ -105,11 +105,11 @@
 	 * @since 2.1.0
 	 * @access protected
 	 *
-	 * @global wpdb  $wpdb          WordPress database abstraction object.
 	 * @global array $wp_user_roles Used to set the 'roles' property value.
 	 */
 	protected function _init() {
-		global $wpdb, $wp_user_roles;
+		global $wp_user_roles;
+		$wpdb = WP::get( 'wpdb' );
 		$this->role_key = $wpdb->get_blog_prefix() . 'user_roles';
 		if ( ! empty( $wp_user_roles ) ) {
 			$this->roles = $wp_user_roles;
@@ -137,8 +137,6 @@
 	 *
 	 * @since 3.5.0
 	 * @access public
-	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	public function reinit() {
 		// There is no need to reinit if using the wp_user_roles global.
@@ -145,7 +143,7 @@
 		if ( ! $this->use_db )
 			return;
 
-		global $wpdb;
+		$wpdb = WP::get( 'wpdb' );
 
 		// Duplicated from _init() to avoid an extra function call.
 		$this->role_key = $wpdb->get_blog_prefix() . 'user_roles';
Index: src/wp-includes/class-wp-site-query.php
===================================================================
--- src/wp-includes/class-wp-site-query.php	(revision 38271)
+++ src/wp-includes/class-wp-site-query.php	(working copy)
@@ -95,6 +95,8 @@
 	 */
 	public $max_num_pages = 0;
 
+	protected $dbh;
+
 	/**
 	 * Sets up the site query, based on the query vars passed.
 	 *
@@ -147,6 +149,8 @@
 	 * }
 	 */
 	public function __construct( $query = '' ) {
+		$this->dbh = WP::get( 'wpdb' );
+
 		$this->query_var_defaults = array(
 			'fields'            => '',
 			'ID'                => '',
@@ -325,13 +329,9 @@
 	 * @since 4.6.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @return int|array A single count of site IDs if a count query. An array of site IDs if a full query.
 	 */
 	protected function get_site_ids() {
-		global $wpdb;
-
 		$order = $this->parse_order( $this->query_vars['order'] );
 
 		// Disable ORDER BY with 'none', an empty array, or boolean false.
@@ -395,7 +395,7 @@
 		// Parse site IDs for an IN clause.
 		$site_id = absint( $this->query_vars['ID'] );
 		if ( ! empty( $site_id ) ) {
-			$this->sql_clauses['where']['ID'] = $wpdb->prepare( 'blog_id = %d', $site_id );
+			$this->sql_clauses['where']['ID'] = $this->dbh->prepare( 'blog_id = %d', $site_id );
 		}
 
 		// Parse site IDs for an IN clause.
@@ -411,7 +411,7 @@
 		$network_id = absint( $this->query_vars['network_id'] );
 
 		if ( ! empty( $network_id ) ) {
-			$this->sql_clauses['where']['network_id'] = $wpdb->prepare( 'site_id = %d', $network_id );
+			$this->sql_clauses['where']['network_id'] = $this->dbh->prepare( 'site_id = %d', $network_id );
 		}
 
 		// Parse site network IDs for an IN clause.
@@ -425,56 +425,56 @@
 		}
 
 		if ( ! empty( $this->query_vars['domain'] ) ) {
-			$this->sql_clauses['where']['domain'] = $wpdb->prepare( 'domain = %s', $this->query_vars['domain'] );
+			$this->sql_clauses['where']['domain'] = $this->dbh->prepare( 'domain = %s', $this->query_vars['domain'] );
 		}
 
 		// Parse site domain for an IN clause.
 		if ( is_array( $this->query_vars['domain__in'] ) ) {
-			$this->sql_clauses['where']['domain__in'] = "domain IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['domain__in'] ) ) . "' )";
+			$this->sql_clauses['where']['domain__in'] = "domain IN ( '" . implode( "', '", $this->dbh->_escape( $this->query_vars['domain__in'] ) ) . "' )";
 		}
 
 		// Parse site domain for a NOT IN clause.
 		if ( is_array( $this->query_vars['domain__not_in'] ) ) {
-			$this->sql_clauses['where']['domain__not_in'] = "domain NOT IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['domain__not_in'] ) ) . "' )";
+			$this->sql_clauses['where']['domain__not_in'] = "domain NOT IN ( '" . implode( "', '", $this->dbh->_escape( $this->query_vars['domain__not_in'] ) ) . "' )";
 		}
 
 		if ( ! empty( $this->query_vars['path'] ) ) {
-			$this->sql_clauses['where']['path'] = $wpdb->prepare( 'path = %s', $this->query_vars['path'] );
+			$this->sql_clauses['where']['path'] = $this->dbh->prepare( 'path = %s', $this->query_vars['path'] );
 		}
 
 		// Parse site path for an IN clause.
 		if ( is_array( $this->query_vars['path__in'] ) ) {
-			$this->sql_clauses['where']['path__in'] = "path IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['path__in'] ) ) . "' )";
+			$this->sql_clauses['where']['path__in'] = "path IN ( '" . implode( "', '", $this->dbh->_escape( $this->query_vars['path__in'] ) ) . "' )";
 		}
 
 		// Parse site path for a NOT IN clause.
 		if ( is_array( $this->query_vars['path__not_in'] ) ) {
-			$this->sql_clauses['where']['path__not_in'] = "path NOT IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['path__not_in'] ) ) . "' )";
+			$this->sql_clauses['where']['path__not_in'] = "path NOT IN ( '" . implode( "', '", $this->dbh->_escape( $this->query_vars['path__not_in'] ) ) . "' )";
 		}
 
 		if ( is_numeric( $this->query_vars['archived'] ) ) {
 			$archived = absint( $this->query_vars['archived'] );
-			$this->sql_clauses['where']['archived'] = $wpdb->prepare( "archived = %d ", $archived );
+			$this->sql_clauses['where']['archived'] = $this->dbh->prepare( "archived = %d ", $archived );
 		}
 
 		if ( is_numeric( $this->query_vars['mature'] ) ) {
 			$mature = absint( $this->query_vars['mature'] );
-			$this->sql_clauses['where']['mature'] = $wpdb->prepare( "mature = %d ", $mature );
+			$this->sql_clauses['where']['mature'] = $this->dbh->prepare( "mature = %d ", $mature );
 		}
 
 		if ( is_numeric( $this->query_vars['spam'] ) ) {
 			$spam = absint( $this->query_vars['spam'] );
-			$this->sql_clauses['where']['spam'] = $wpdb->prepare( "spam = %d ", $spam );
+			$this->sql_clauses['where']['spam'] = $this->dbh->prepare( "spam = %d ", $spam );
 		}
 
 		if ( is_numeric( $this->query_vars['deleted'] ) ) {
 			$deleted = absint( $this->query_vars['deleted'] );
-			$this->sql_clauses['where']['deleted'] = $wpdb->prepare( "deleted = %d ", $deleted );
+			$this->sql_clauses['where']['deleted'] = $this->dbh->prepare( "deleted = %d ", $deleted );
 		}
 
 		if ( is_numeric( $this->query_vars['public'] ) ) {
 			$public = absint( $this->query_vars['public'] );
-			$this->sql_clauses['where']['public'] = $wpdb->prepare( "public = %d ", $public );
+			$this->sql_clauses['where']['public'] = $this->dbh->prepare( "public = %d ", $public );
 		}
 
 		// Falsey search strings are ignored.
@@ -550,7 +550,7 @@
 		}
 
 		$this->sql_clauses['select']  = "SELECT $found_rows $fields";
-		$this->sql_clauses['from']    = "FROM $wpdb->blogs $join";
+		$this->sql_clauses['from']    = "FROM {$this->dbh->blogs} $join";
 		$this->sql_clauses['groupby'] = $groupby;
 		$this->sql_clauses['orderby'] = $orderby;
 		$this->sql_clauses['limits']  = $limits;
@@ -558,10 +558,10 @@
 		$this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
 
 		if ( $this->query_vars['count'] ) {
-			return intval( $wpdb->get_var( $this->request ) );
+			return intval( $this->dbh->get_var( $this->request ) );
 		}
 
-		$site_ids = $wpdb->get_col( $this->request );
+		$site_ids = $this->dbh->get_col( $this->request );
 
 		return array_map( 'intval', $site_ids );
 	}
@@ -572,12 +572,8 @@
 	 *
 	 * @since 4.6.0
 	 * @access private
-	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	private function set_found_sites() {
-		global $wpdb;
-
 		if ( $this->query_vars['number'] && ! $this->query_vars['no_found_rows'] ) {
 			/**
 			 * Filters the query used to retrieve found site count.
@@ -589,7 +585,7 @@
 			 */
 			$found_sites_query = apply_filters( 'found_sites_query', 'SELECT FOUND_ROWS()', $this );
 
-			$this->found_sites = (int) $wpdb->get_var( $found_sites_query );
+			$this->found_sites = (int) $this->dbh->get_var( $found_sites_query );
 		}
 	}
 
@@ -599,24 +595,20 @@
 	 * @since 4.6.0
 	 * @access protected
 	 *
-	 * @global wpdb  $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $string  Search string.
 	 * @param array  $columns Columns to search.
 	 * @return string Search SQL.
 	 */
 	protected function get_search_sql( $string, $columns ) {
-		global $wpdb;
-
 		if ( false !== strpos( $string, '*' ) ) {
-			$like = '%' . implode( '%', array_map( array( $wpdb, 'esc_like' ), explode( '*', $string ) ) ) . '%';
+			$like = '%' . implode( '%', array_map( array( $this->dbh, 'esc_like' ), explode( '*', $string ) ) ) . '%';
 		} else {
-			$like = '%' . $wpdb->esc_like( $string ) . '%';
+			$like = '%' . $this->dbh->esc_like( $string ) . '%';
 		}
 
 		$searches = array();
 		foreach ( $columns as $column ) {
-			$searches[] = $wpdb->prepare( "$column LIKE %s", $like );
+			$searches[] = $this->dbh->prepare( "$column LIKE %s", $like );
 		}
 
 		return '(' . implode( ' OR ', $searches ) . ')';
@@ -628,24 +620,20 @@
 	 * @since 4.6.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $orderby Alias for the field to order by.
 	 * @return string|false Value to used in the ORDER clause. False otherwise.
 	 */
 	protected function parse_orderby( $orderby ) {
-		global $wpdb;
-
 		$parsed = false;
 
 		switch ( $orderby ) {
 			case 'site__in':
 				$site__in = implode( ',', array_map( 'absint', $this->query_vars['site__in'] ) );
-				$parsed = "FIELD( {$wpdb->blogs}.blog_id, $site__in )";
+				$parsed = "FIELD( {$this->dbh->blogs}.blog_id, $site__in )";
 				break;
 			case 'network__in':
 				$network__in = implode( ',', array_map( 'absint', $this->query_vars['network__in'] ) );
-				$parsed = "FIELD( {$wpdb->blogs}.site_id, $network__in )";
+				$parsed = "FIELD( {$this->dbh->blogs}.site_id, $network__in )";
 				break;
 			case 'domain':
 			case 'last_updated':
Index: src/wp-includes/class-wp-site.php
===================================================================
--- src/wp-includes/class-wp-site.php	(revision 38271)
+++ src/wp-includes/class-wp-site.php	(working copy)
@@ -157,14 +157,10 @@
 	 * @since 4.5.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int $site_id The ID of the site to retrieve.
 	 * @return WP_Site|false The site's object if found. False if not.
 	 */
 	public static function get_instance( $site_id ) {
-		global $wpdb;
-
 		$site_id = (int) $site_id;
 		if ( ! $site_id ) {
 			return false;
@@ -173,6 +169,7 @@
 		$_site = wp_cache_get( $site_id, 'sites' );
 
 		if ( ! $_site ) {
+			$wpdb = WP::get( 'wpdb' );
 			$_site = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->blogs} WHERE blog_id = %d LIMIT 1", $site_id ) );
 
 			if ( empty( $_site ) || is_wp_error( $_site ) ) {
Index: src/wp-includes/class-wp-tax-query.php
===================================================================
--- src/wp-includes/class-wp-tax-query.php	(revision 38271)
+++ src/wp-includes/class-wp-tax-query.php	(working copy)
@@ -91,6 +91,8 @@
 	 */
 	public $primary_id_column;
 
+	protected $dbh;
+
 	/**
 	 * Constructor.
 	 *
@@ -125,6 +127,8 @@
 			$this->relation = 'AND';
 		}
 
+		$this->dbh = WP::get( 'wpdb' );
+
 		$this->queries = $this->sanitize_query( $tax_query );
 	}
 
@@ -387,8 +391,6 @@
 	 * @since 4.1.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb The WordPress database abstraction object.
-	 *
 	 * @param array $clause       Query clause, passed by reference.
 	 * @param array $parent_query Parent query array.
 	 * @return array {
@@ -399,8 +401,6 @@
 	 * }
 	 */
 	public function get_sql_for_clause( &$clause, $parent_query ) {
-		global $wpdb;
-
 		$sql = array(
 			'where' => array(),
 			'join'  => array(),
@@ -432,7 +432,7 @@
 			$alias = $this->find_compatible_table_alias( $clause, $parent_query );
 			if ( false === $alias ) {
 				$i = count( $this->table_aliases );
-				$alias = $i ? 'tt' . $i : $wpdb->term_relationships;
+				$alias = $i ? 'tt' . $i : $this->dbh->term_relationships;
 
 				// Store the alias as part of a flat array to build future iterators.
 				$this->table_aliases[] = $alias;
@@ -440,7 +440,7 @@
 				// Store the alias with this clause, so later siblings can use it.
 				$clause['alias'] = $alias;
 
-				$join .= " LEFT JOIN $wpdb->term_relationships";
+				$join .= " LEFT JOIN {$this->dbh->term_relationships}";
 				$join .= $i ? " AS $alias" : '';
 				$join .= " ON ($this->primary_table.$this->primary_id_column = $alias.object_id)";
 			}
@@ -458,7 +458,7 @@
 
 			$where = "$this->primary_table.$this->primary_id_column NOT IN (
 				SELECT object_id
-				FROM $wpdb->term_relationships
+				FROM {$this->dbh->term_relationships}
 				WHERE term_taxonomy_id IN ($terms)
 			)";
 
@@ -474,7 +474,7 @@
 
 			$where = "(
 				SELECT COUNT(1)
-				FROM $wpdb->term_relationships
+				FROM {$this->dbh->term_relationships}
 				WHERE term_taxonomy_id IN ($terms)
 				AND object_id = $this->primary_table.$this->primary_id_column
 			) = $num_terms";
@@ -481,13 +481,13 @@
 
 		} elseif ( 'NOT EXISTS' === $operator || 'EXISTS' === $operator ) {
 
-			$where = $wpdb->prepare( "$operator (
+			$where = $this->dbh->prepare( "$operator (
 				SELECT 1
-				FROM $wpdb->term_relationships
-				INNER JOIN $wpdb->term_taxonomy
-				ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id
-				WHERE $wpdb->term_taxonomy.taxonomy = %s
-				AND $wpdb->term_relationships.object_id = $this->primary_table.$this->primary_id_column
+				FROM {$this->dbh->term_relationships}
+				INNER JOIN {$this->dbh->term_taxonomy}
+				ON {$this->dbh->term_taxonomy}.term_taxonomy_id = {$this->dbh->term_relationships}.term_taxonomy_id
+				WHERE {$this->dbh->term_taxonomy}.taxonomy = %s
+				AND {$this->dbh->term_relationships}.object_id = {$this->primary_table}.{$this->primary_id_column}
 			)", $clause['taxonomy'] );
 
 		}
@@ -597,15 +597,11 @@
 	 *
 	 * @since 3.2.0
 	 *
-	 * @global wpdb $wpdb The WordPress database abstraction object.
-	 *
 	 * @param array  $query           The single query. Passed by reference.
 	 * @param string $resulting_field The resulting field. Accepts 'slug', 'name', 'term_taxonomy_id',
 	 *                                or 'term_id'. Default 'term_id'.
 	 */
 	public function transform_query( &$query, $resulting_field ) {
-		global $wpdb;
-
 		if ( empty( $query['terms'] ) )
 			return;
 
@@ -628,27 +624,27 @@
 
 				$terms = implode( ",", $query['terms'] );
 
-				$terms = $wpdb->get_col( "
-					SELECT $wpdb->term_taxonomy.$resulting_field
-					FROM $wpdb->term_taxonomy
-					INNER JOIN $wpdb->terms USING (term_id)
+				$terms = $this->dbh->get_col( "
+					SELECT {$this->dbh->term_taxonomy}.$resulting_field
+					FROM {$this->dbh->term_taxonomy}
+					INNER JOIN {$this->dbh->terms} USING (term_id)
 					WHERE taxonomy = '{$query['taxonomy']}'
-					AND $wpdb->terms.{$query['field']} IN ($terms)
+					AND {$this->dbh->terms}.{$query['field']} IN ($terms)
 				" );
 				break;
 			case 'term_taxonomy_id':
 				$terms = implode( ',', array_map( 'intval', $query['terms'] ) );
-				$terms = $wpdb->get_col( "
+				$terms = $this->dbh->get_col( "
 					SELECT $resulting_field
-					FROM $wpdb->term_taxonomy
+					FROM {$this->dbh->term_taxonomy}
 					WHERE term_taxonomy_id IN ($terms)
 				" );
 				break;
 			default:
 				$terms = implode( ',', array_map( 'intval', $query['terms'] ) );
-				$terms = $wpdb->get_col( "
+				$terms = $this->dbh->get_col( "
 					SELECT $resulting_field
-					FROM $wpdb->term_taxonomy
+					FROM {$this->dbh->term_taxonomy}
 					WHERE taxonomy = '{$query['taxonomy']}'
 					AND term_id IN ($terms)
 				" );
Index: src/wp-includes/class-wp-term-query.php
===================================================================
--- src/wp-includes/class-wp-term-query.php	(revision 38271)
+++ src/wp-includes/class-wp-term-query.php	(working copy)
@@ -86,6 +86,8 @@
 	 */
 	public $terms;
 
+	protected $dbh;
+
 	/**
 	 * Constructor.
 	 *
@@ -201,6 +203,8 @@
 			'meta_query'             => '',
 		);
 
+		$this->dbh = WP::get( 'wpdb' );
+
 		if ( ! empty( $query ) ) {
 			$this->query( $query );
 		}
@@ -293,13 +297,9 @@
 	 * @param 4.6.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @return array
 	 */
 	public function get_terms() {
-		global $wpdb;
-
 		$this->parse_query( $this->query_vars );
 		$args = $this->query_vars;
 
@@ -486,16 +486,16 @@
 				$tt_ids = implode( ',', array_map( 'intval', $args['term_taxonomy_id'] ) );
 				$this->sql_clauses['where']['term_taxonomy_id'] = "tt.term_taxonomy_id IN ({$tt_ids})";
 			} else {
-				$this->sql_clauses['where']['term_taxonomy_id'] = $wpdb->prepare( "tt.term_taxonomy_id = %d", $args['term_taxonomy_id'] );
+				$this->sql_clauses['where']['term_taxonomy_id'] = $this->dbh->prepare( "tt.term_taxonomy_id = %d", $args['term_taxonomy_id'] );
 			}
 		}
 
 		if ( ! empty( $args['name__like'] ) ) {
-			$this->sql_clauses['where']['name__like'] = $wpdb->prepare( "t.name LIKE %s", '%' . $wpdb->esc_like( $args['name__like'] ) . '%' );
+			$this->sql_clauses['where']['name__like'] = $this->dbh->prepare( "t.name LIKE %s", '%' . $this->dbh->esc_like( $args['name__like'] ) . '%' );
 		}
 
 		if ( ! empty( $args['description__like'] ) ) {
-			$this->sql_clauses['where']['description__like'] = $wpdb->prepare( "tt.description LIKE %s", '%' . $wpdb->esc_like( $args['description__like'] ) . '%' );
+			$this->sql_clauses['where']['description__like'] = $this->dbh->prepare( "tt.description LIKE %s", '%' . $this->dbh->esc_like( $args['description__like'] ) . '%' );
 		}
 
 		if ( '' !== $parent ) {
@@ -591,7 +591,7 @@
 		 */
 		$fields = implode( ', ', apply_filters( 'get_terms_fields', $selects, $args, $taxonomies ) );
 
-		$join .= " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id";
+		$join .= " INNER JOIN {$this->dbh->term_taxonomy} AS tt ON t.term_id = tt.term_id";
 
 		$where = implode( ' AND ', $this->sql_clauses['where'] );
 
@@ -621,7 +621,7 @@
 		}
 
 		$this->sql_clauses['select']  = "SELECT $distinct $fields";
-		$this->sql_clauses['from']    = "FROM $wpdb->terms AS t $join";
+		$this->sql_clauses['from']    = "FROM {$this->dbh->terms} AS t $join";
 		$this->sql_clauses['orderby'] = $orderby ? "$orderby $order" : '';
 		$this->sql_clauses['limits']  = $limits;
 
@@ -646,10 +646,10 @@
 		}
 
 		if ( 'count' == $_fields ) {
-			return $wpdb->get_var( $this->request );
+			return $this->dbh->get_var( $this->request );
 		}
 
-		$terms = $wpdb->get_results( $this->request );
+		$terms = $this->dbh->get_results( $this->request );
 		if ( 'all' == $_fields ) {
 			update_term_cache( $terms );
 		}
@@ -753,8 +753,6 @@
 	 * @since 4.6.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $orderby_raw Alias for the field to order by.
 	 * @return string|false Value to used in the ORDER clause. False otherwise.
 	 */
@@ -894,16 +892,12 @@
 	 * @since 4.6.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $string
 	 * @return string
 	 */
 	protected function get_search_sql( $string ) {
-		global $wpdb;
+		$like = '%' . $this->dbh->esc_like( $string ) . '%';
 
-		$like = '%' . $wpdb->esc_like( $string ) . '%';
-
-		return $wpdb->prepare( '((t.name LIKE %s) OR (t.slug LIKE %s))', $like, $like );
+		return $this->dbh->prepare( '((t.name LIKE %s) OR (t.slug LIKE %s))', $like, $like );
 	}
 }
Index: src/wp-includes/class-wp-term.php
===================================================================
--- src/wp-includes/class-wp-term.php	(revision 38271)
+++ src/wp-includes/class-wp-term.php	(working copy)
@@ -113,8 +113,6 @@
 	 * @access public
 	 * @static
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int    $term_id  Term ID.
 	 * @param string $taxonomy Optional. Limit matched terms to those matching `$taxonomy`. Only used for
 	 *                         disambiguating potentially shared terms.
@@ -123,8 +121,6 @@
 	 *                                False for other failures.
 	 */
 	public static function get_instance( $term_id, $taxonomy = null ) {
-		global $wpdb;
-
 		$term_id = (int) $term_id;
 		if ( ! $term_id ) {
 			return false;
@@ -134,6 +130,7 @@
 
 		// If there isn't a cached version, hit the database.
 		if ( ! $_term || ( $taxonomy && $taxonomy !== $_term->taxonomy ) ) {
+			$wpdb = WP::get( 'wpdb' );
 			// Grab all matching terms, in case any are shared between taxonomies.
 			$terms = $wpdb->get_results( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.term_id = %d", $term_id ) );
 			if ( ! $terms ) {
Index: src/wp-includes/class-wp-user-query.php
===================================================================
--- src/wp-includes/class-wp-user-query.php	(revision 38271)
+++ src/wp-includes/class-wp-user-query.php	(working copy)
@@ -70,6 +70,8 @@
 	public $query_orderby;
 	public $query_limit;
 
+	protected $dbh;
+
 	/**
 	 * PHP5 constructor.
 	 *
@@ -78,6 +80,8 @@
 	 * @param null|string|array $query Optional. The query variables.
 	 */
 	public function __construct( $query = null ) {
+		$this->dbh = WP::get( 'wpdb' );
+
 		if ( ! empty( $query ) ) {
 			$this->prepare_query( $query );
 			$this->query();
@@ -134,7 +138,6 @@
 	 *
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 * @global int  $blog_id
 	 *
 	 * @param string|array $query {
@@ -198,8 +201,6 @@
 	 * }
 	 */
 	public function prepare_query( $query = array() ) {
-		global $wpdb;
-
 		if ( empty( $this->query_vars ) || ! empty( $query ) ) {
 			$this->query_limit = null;
 			$this->query_vars = $this->fill_query_vars( $query );
@@ -228,19 +229,19 @@
 			$this->query_fields = array();
 			foreach ( $qv['fields'] as $field ) {
 				$field = 'ID' === $field ? 'ID' : sanitize_key( $field );
-				$this->query_fields[] = "$wpdb->users.$field";
+				$this->query_fields[] = "{$this->dbh->users}.$field";
 			}
 			$this->query_fields = implode( ',', $this->query_fields );
 		} elseif ( 'all' == $qv['fields'] ) {
-			$this->query_fields = "$wpdb->users.*";
+			$this->query_fields = "{$this->dbh->users}.*";
 		} else {
-			$this->query_fields = "$wpdb->users.ID";
+			$this->query_fields = "{$this->dbh->users}.ID";
 		}
 
 		if ( isset( $qv['count_total'] ) && $qv['count_total'] )
 			$this->query_fields = 'SQL_CALC_FOUND_ROWS ' . $this->query_fields;
 
-		$this->query_from = "FROM $wpdb->users";
+		$this->query_from = "FROM {$this->dbh->users}";
 		$this->query_where = "WHERE 1=1";
 
 		// Parse and sanitize 'include', for use by 'orderby' as well as 'include' below.
@@ -263,11 +264,11 @@
 			}
 
 			foreach ( $post_types as &$post_type ) {
-				$post_type = $wpdb->prepare( '%s', $post_type );
+				$post_type = $this->dbh->prepare( '%s', $post_type );
 			}
 
-			$posts_table = $wpdb->get_blog_prefix( $blog_id ) . 'posts';
-			$this->query_where .= " AND $wpdb->users.ID IN ( SELECT DISTINCT $posts_table.post_author FROM $posts_table WHERE $posts_table.post_status = 'publish' AND $posts_table.post_type IN ( " . join( ", ", $post_types ) . " ) )";
+			$posts_table = $this->dbh->get_blog_prefix( $blog_id ) . 'posts';
+			$this->query_where .= " AND {$this->dbh->users}.ID IN ( SELECT DISTINCT $posts_table.post_author FROM $posts_table WHERE $posts_table.post_status = 'publish' AND $posts_table.post_type IN ( " . join( ", ", $post_types ) . " ) )";
 		}
 
 		// Meta query.
@@ -276,7 +277,7 @@
 
 		if ( isset( $qv['who'] ) && 'authors' == $qv['who'] && $blog_id ) {
 			$who_query = array(
-				'key' => $wpdb->get_blog_prefix( $blog_id ) . 'user_level',
+				'key' => $this->dbh->get_blog_prefix( $blog_id ) . 'user_level',
 				'value' => 0,
 				'compare' => '!=',
 			);
@@ -323,7 +324,7 @@
 			if ( ! empty( $roles ) ) {
 				foreach ( $roles as $role ) {
 					$roles_clauses[] = array(
-						'key'     => $wpdb->get_blog_prefix( $blog_id ) . 'capabilities',
+						'key'     => $this->dbh->get_blog_prefix( $blog_id ) . 'capabilities',
 						'value'   => '"' . $role . '"',
 						'compare' => 'LIKE',
 					);
@@ -336,7 +337,7 @@
 			if ( ! empty( $role__in ) ) {
 				foreach ( $role__in as $role ) {
 					$role__in_clauses[] = array(
-						'key'     => $wpdb->get_blog_prefix( $blog_id ) . 'capabilities',
+						'key'     => $this->dbh->get_blog_prefix( $blog_id ) . 'capabilities',
 						'value'   => '"' . $role . '"',
 						'compare' => 'LIKE',
 					);
@@ -349,7 +350,7 @@
 			if ( ! empty( $role__not_in ) ) {
 				foreach ( $role__not_in as $role ) {
 					$role__not_in_clauses[] = array(
-						'key'     => $wpdb->get_blog_prefix( $blog_id ) . 'capabilities',
+						'key'     => $this->dbh->get_blog_prefix( $blog_id ) . 'capabilities',
 						'value'   => '"' . $role . '"',
 						'compare' => 'NOT LIKE',
 					);
@@ -361,7 +362,7 @@
 			// If there are no specific roles named, make sure the user is a member of the site.
 			if ( empty( $role_queries ) ) {
 				$role_queries[] = array(
-					'key' => $wpdb->get_blog_prefix( $blog_id ) . 'capabilities',
+					'key' => $this->dbh->get_blog_prefix( $blog_id ) . 'capabilities',
 					'compare' => 'EXISTS',
 				);
 			}
@@ -383,7 +384,7 @@
 		}
 
 		if ( ! empty( $this->meta_query->queries ) ) {
-			$clauses = $this->meta_query->get_sql( 'user', $wpdb->users, 'ID', $this );
+			$clauses = $this->meta_query->get_sql( 'user', $this->dbh->users, 'ID', $this );
 			$this->query_from .= $clauses['join'];
 			$this->query_where .= $clauses['where'];
 
@@ -441,9 +442,9 @@
 		// limit
 		if ( isset( $qv['number'] ) && $qv['number'] > 0 ) {
 			if ( $qv['offset'] ) {
-				$this->query_limit = $wpdb->prepare("LIMIT %d, %d", $qv['offset'], $qv['number']);
+				$this->query_limit = $this->dbh->prepare("LIMIT %d, %d", $qv['offset'], $qv['number']);
 			} else {
-				$this->query_limit = $wpdb->prepare( "LIMIT %d, %d", $qv['number'] * ( $qv['paged'] - 1 ), $qv['number'] );
+				$this->query_limit = $this->dbh->prepare( "LIMIT %d, %d", $qv['number'] * ( $qv['paged'] - 1 ), $qv['number'] );
 			}
 		}
 
@@ -499,10 +500,10 @@
 		if ( ! empty( $include ) ) {
 			// Sanitized earlier.
 			$ids = implode( ',', $include );
-			$this->query_where .= " AND $wpdb->users.ID IN ($ids)";
+			$this->query_where .= " AND {$this->dbh->users}.ID IN ($ids)";
 		} elseif ( ! empty( $qv['exclude'] ) ) {
 			$ids = implode( ',', wp_parse_id_list( $qv['exclude'] ) );
-			$this->query_where .= " AND $wpdb->users.ID NOT IN ($ids)";
+			$this->query_where .= " AND {$this->dbh->users}.ID NOT IN ($ids)";
 		}
 
 		// Date queries are allowed for the user_registered field.
@@ -530,20 +531,16 @@
 	 * Execute the query, with the current variables.
 	 *
 	 * @since 3.1.0
-	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	public function query() {
-		global $wpdb;
-
 		$qv =& $this->query_vars;
 
 		$this->request = "SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit";
 
 		if ( is_array( $qv['fields'] ) || 'all' == $qv['fields'] ) {
-			$this->results = $wpdb->get_results( $this->request );
+			$this->results = $this->dbh->get_results( $this->request );
 		} else {
-			$this->results = $wpdb->get_col( $this->request );
+			$this->results = $this->dbh->get_col( $this->request );
 		}
 
 		/**
@@ -551,12 +548,10 @@
 		 *
 		 * @since 3.2.0
 		 *
-		 * @global wpdb $wpdb WordPress database abstraction object.
-		 *
 		 * @param string $sql The SELECT FOUND_ROWS() query for the current WP_User_Query.
 		 */
 		if ( isset( $qv['count_total'] ) && $qv['count_total'] )
-			$this->total_users = $wpdb->get_var( apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()' ) );
+			$this->total_users = $this->dbh->get_var( apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()' ) );
 
 		if ( !$this->results )
 			return;
@@ -611,8 +606,6 @@
 	 * @access protected
 	 * @since 3.1.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $string
 	 * @param array  $cols
 	 * @param bool   $wild   Whether to allow wildcard searches. Default is false for Network Admin, true for single site.
@@ -620,18 +613,16 @@
 	 * @return string
 	 */
 	protected function get_search_sql( $string, $cols, $wild = false ) {
-		global $wpdb;
-
 		$searches = array();
 		$leading_wild = ( 'leading' == $wild || 'both' == $wild ) ? '%' : '';
 		$trailing_wild = ( 'trailing' == $wild || 'both' == $wild ) ? '%' : '';
-		$like = $leading_wild . $wpdb->esc_like( $string ) . $trailing_wild;
+		$like = $leading_wild . $this->dbh->esc_like( $string ) . $trailing_wild;
 
 		foreach ( $cols as $col ) {
 			if ( 'ID' == $col ) {
-				$searches[] = $wpdb->prepare( "$col = %s", $string );
+				$searches[] = $this->dbh->prepare( "$col = %s", $string );
 			} else {
-				$searches[] = $wpdb->prepare( "$col LIKE %s", $like );
+				$searches[] = $this->dbh->prepare( "$col LIKE %s", $like );
 			}
 		}
 
@@ -668,14 +659,10 @@
 	 * @since 4.2.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $orderby Alias for the field to order by.
 	 * @return string Value to used in the ORDER clause, if `$orderby` is valid.
 	 */
 	protected function parse_orderby( $orderby ) {
-		global $wpdb;
-
 		$meta_query_clauses = $this->meta_query->get_clauses();
 
 		$_orderby = '';
@@ -690,22 +677,22 @@
 			$where = get_posts_by_author_sql( 'post' );
 			$this->query_from .= " LEFT OUTER JOIN (
 				SELECT post_author, COUNT(*) as post_count
-				FROM $wpdb->posts
+				FROM {$this->dbh->posts}
 				$where
 				GROUP BY post_author
-			) p ON ({$wpdb->users}.ID = p.post_author)
+			) p ON ({$this->dbh->users}.ID = p.post_author)
 			";
 			$_orderby = 'post_count';
 		} elseif ( 'ID' == $orderby || 'id' == $orderby ) {
 			$_orderby = 'ID';
 		} elseif ( 'meta_value' == $orderby || $this->get( 'meta_key' ) == $orderby ) {
-			$_orderby = "$wpdb->usermeta.meta_value";
+			$_orderby = "{$this->dbh->usermeta}.meta_value";
 		} elseif ( 'meta_value_num' == $orderby ) {
-			$_orderby = "$wpdb->usermeta.meta_value+0";
+			$_orderby = "{$this->dbh->usermeta}.meta_value+0";
 		} elseif ( 'include' === $orderby && ! empty( $this->query_vars['include'] ) ) {
 			$include = wp_parse_id_list( $this->query_vars['include'] );
 			$include_sql = implode( ',', $include );
-			$_orderby = "FIELD( $wpdb->users.ID, $include_sql )";
+			$_orderby = "FIELD( {$this->dbh->users}.ID, $include_sql )";
 		} elseif ( isset( $meta_query_clauses[ $orderby ] ) ) {
 			$meta_clause = $meta_query_clauses[ $orderby ];
 			$_orderby = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) );
Index: src/wp-includes/class-wp-user.php
===================================================================
--- src/wp-includes/class-wp-user.php	(revision 38271)
+++ src/wp-includes/class-wp-user.php	(working copy)
@@ -101,6 +101,8 @@
 	 */
 	private static $back_compat_keys;
 
+	protected $dbh;
+
 	/**
 	 * Constructor.
 	 *
@@ -109,15 +111,15 @@
 	 * @since 2.0.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int|string|stdClass|WP_User $id User's ID, a WP_User object, or a user object from the DB.
 	 * @param string $name Optional. User's username
 	 * @param int $blog_id Optional Site ID, defaults to current site.
 	 */
 	public function __construct( $id = 0, $name = '', $blog_id = '' ) {
+		$this->dbh = WP::get( 'wpdb' );
+
 		if ( ! isset( self::$back_compat_keys ) ) {
-			$prefix = $GLOBALS['wpdb']->prefix;
+			$prefix = $this->dbh->prefix;
 			self::$back_compat_keys = array(
 				'user_firstname' => 'first_name',
 				'user_lastname' => 'last_name',
@@ -175,15 +177,11 @@
 	 *
 	 * @static
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $field The field to query against: 'id', 'ID', 'slug', 'email' or 'login'.
 	 * @param string|int $value The field value
 	 * @return object|false Raw user object
 	 */
 	public static function get_data_by( $field, $value ) {
-		global $wpdb;
-
 		// 'ID' is an alias of 'id'.
 		if ( 'ID' === $field ) {
 			$field = 'id';
@@ -231,6 +229,7 @@
 				return $user;
 		}
 
+		$wpdb = WP::get( 'wpdb' );
 		if ( !$user = $wpdb->get_row( $wpdb->prepare(
 			"SELECT * FROM $wpdb->users WHERE $db_field = %s", $value
 		) ) )
@@ -442,15 +441,11 @@
 	 * @access protected
 	 * @since 2.1.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $cap_key Optional capability key
 	 */
 	protected function _init_caps( $cap_key = '' ) {
-		global $wpdb;
-
 		if ( empty($cap_key) )
-			$this->cap_key = $wpdb->get_blog_prefix() . 'capabilities';
+			$this->cap_key = $this->dbh->get_blog_prefix() . 'capabilities';
 		else
 			$this->cap_key = $cap_key;
 
@@ -631,13 +626,10 @@
 	 *
 	 * @since 2.0.0
 	 * @access public
-	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	public function update_user_level_from_caps() {
-		global $wpdb;
 		$this->user_level = array_reduce( array_keys( $this->allcaps ), array( $this, 'level_reduction' ), 0 );
-		update_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level', $this->user_level );
+		update_user_meta( $this->ID, $this->dbh->get_blog_prefix() . 'user_level', $this->user_level );
 	}
 
 	/**
@@ -679,14 +671,11 @@
 	 *
 	 * @since 2.1.0
 	 * @access public
-	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 */
 	public function remove_all_caps() {
-		global $wpdb;
 		$this->caps = array();
 		delete_user_meta( $this->ID, $this->cap_key );
-		delete_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level' );
+		delete_user_meta( $this->ID, $this->dbh->get_blog_prefix() . 'user_level' );
 		$this->get_role_caps();
 	}
 
@@ -772,14 +761,11 @@
 	 *
 	 * @since 3.0.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int $blog_id Optional. Site ID, defaults to current site.
 	 */
 	public function for_blog( $blog_id = '' ) {
-		global $wpdb;
 		if ( ! empty( $blog_id ) )
-			$cap_key = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities';
+			$cap_key = $this->dbh->get_blog_prefix( $blog_id ) . 'capabilities';
 		else
 			$cap_key = '';
 		$this->_init_caps( $cap_key );
Index: src/wp-includes/class-wp-xmlrpc-server.php
===================================================================
--- src/wp-includes/class-wp-xmlrpc-server.php	(revision 38271)
+++ src/wp-includes/class-wp-xmlrpc-server.php	(working copy)
@@ -53,6 +53,8 @@
 	 */
 	protected $auth_failed = false;
 
+	protected $dbh;
+
 	/**
 	 * Registers all of the XMLRPC methods that XMLRPC server understands.
 	 *
@@ -63,6 +65,8 @@
 	 * @since 1.5.0
 	 */
 	public function __construct() {
+		$this->dbh = WP::get( 'wpdb' );
+
 		$this->methods = array(
 			// WordPress API
 			'wp.getUsersBlogs'		=> 'this:wp_getUsersBlogs',
@@ -2882,8 +2886,6 @@
 	 *
 	 * @since 2.2.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param array  $args {
 	 *     Method arguments. Note: arguments must be ordered as documented.
 	 *
@@ -2894,8 +2896,6 @@
 	 * @return array|IXR_Error
 	 */
 	public function wp_getPageList( $args ) {
-		global $wpdb;
-
 		$this->escape( $args );
 
 		$username = $args[1];
@@ -2911,7 +2911,7 @@
 		do_action( 'xmlrpc_call', 'wp.getPageList' );
 
 		// Get list of pages ids and titles
-		$page_list = $wpdb->get_results("
+		$page_list = $this->dbh->get_results("
 			SELECT ID page_id,
 				post_title page_title,
 				post_parent page_parent_id,
@@ -2918,7 +2918,7 @@
 				post_date_gmt,
 				post_date,
 				post_status
-			FROM {$wpdb->posts}
+			FROM {$this->dbh->posts}
 			WHERE post_type = 'page'
 			ORDER BY ID
 		");
@@ -5130,20 +5130,17 @@
 	 *
 	 * @since 2.1.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int $post_ID Post ID.
 	 * @param string $post_content Post Content for attachment.
 	 */
 	public function attach_uploads( $post_ID, $post_content ) {
-		global $wpdb;
-
 		// find any unattached files
-		$attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '0' AND post_type = 'attachment'" );
+		$attachments = $this->dbh->get_results( "SELECT ID, guid FROM {$this->dbh->posts} WHERE post_parent = '0' AND post_type = 'attachment'" );
 		if ( is_array( $attachments ) ) {
 			foreach ( $attachments as $file ) {
-				if ( ! empty( $file->guid ) && strpos( $post_content, $file->guid ) !== false )
-					$wpdb->update($wpdb->posts, array('post_parent' => $post_ID), array('ID' => $file->ID) );
+				if ( ! empty( $file->guid ) && strpos( $post_content, $file->guid ) !== false ) {
+					$this->dbh->update($this->dbh->posts, array('post_parent' => $post_ID), array('ID' => $file->ID) );
+				}
 			}
 		}
 	}
@@ -5763,8 +5760,6 @@
 	 *
 	 * @since 1.5.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param array  $args {
 	 *     Method arguments. Note: arguments must be ordered as documented.
 	 *
@@ -5776,8 +5771,6 @@
 	 * @return array|IXR_Error
 	 */
 	public function mw_newMediaObject( $args ) {
-		global $wpdb;
-
 		$username = $this->escape( $args[1] );
 		$password = $this->escape( $args[2] );
 		$data     = $args[3];
@@ -6102,14 +6095,10 @@
 	 *
 	 * @since 1.5.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param int $post_ID
 	 * @return array|IXR_Error
 	 */
 	public function mt_getTrackbackPings( $post_ID ) {
-		global $wpdb;
-
 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
 		do_action( 'xmlrpc_call', 'mt.getTrackbackPings' );
 
@@ -6118,7 +6107,7 @@
 		if ( !$actual_post )
 			return new IXR_Error(404, __('Sorry, no such post.'));
 
-		$comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) );
+		$comments = $this->dbh->get_results( $this->dbh->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM {$this->dbh->comments} WHERE comment_post_ID = %d", $post_ID) );
 
 		if ( !$comments )
 			return array();
@@ -6192,7 +6181,6 @@
 	 *
 	 * @since 1.5.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
 	 * @global string $wp_version
 	 *
 	 * @param array  $args {
@@ -6204,7 +6192,7 @@
 	 * @return string|IXR_Error
 	 */
 	public function pingback_ping( $args ) {
-		global $wpdb, $wp_version;
+		global $wp_version;
 
 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
 		do_action( 'xmlrpc_call', 'pingback.ping' );
@@ -6258,8 +6246,8 @@
 			} elseif ( is_string($urltest['fragment']) ) {
 				// ...or a string #title, a little more complicated
 				$title = preg_replace('/[^a-z0-9]/i', '.', $urltest['fragment']);
-				$sql = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", $title );
-				if (! ($post_ID = $wpdb->get_var($sql)) ) {
+				$sql = $this->dbh->prepare("SELECT ID FROM {$this->dbh->posts} WHERE post_title RLIKE %s", $title );
+				if (! ($post_ID = $this->dbh->get_var($sql)) ) {
 					// returning unknown error '0' is better than die()ing
 			  		return $this->pingback_error( 0, '' );
 				}
@@ -6283,7 +6271,7 @@
 	  		return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either doesn&#8217;t exist, or it is not a pingback-enabled resource.' ) );
 
 		// Let's check that the remote site didn't already pingback this entry
-		if ( $wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s", $post_ID, $pagelinkedfrom) ) )
+		if ( $this->dbh->get_results( $this->dbh->prepare("SELECT * FROM {$this->dbh->comments} WHERE comment_post_ID = %d AND comment_author_url = %s", $post_ID, $pagelinkedfrom) ) )
 			return $this->pingback_error( 48, __( 'The pingback has already been registered.' ) );
 
 		// very stupid, but gives time to the 'from' server to publish !
@@ -6408,14 +6396,10 @@
 	 *
 	 * @since 1.5.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $url
 	 * @return array|IXR_Error
 	 */
 	public function pingback_extensions_getPingbacks( $url ) {
-		global $wpdb;
-
 		/** This action is documented in wp-includes/class-wp-xmlrpc-server.php */
 		do_action( 'xmlrpc_call', 'pingback.extensions.getPingbacks' );
 
@@ -6434,7 +6418,7 @@
 	  		return $this->pingback_error( 32, __('The specified target URL does not exist.' ) );
 		}
 
-		$comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) );
+		$comments = $this->dbh->get_results( $this->dbh->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM {$this->dbh->comments} WHERE comment_post_ID = %d", $post_ID) );
 
 		if ( !$comments )
 			return array();
Index: src/wp-includes/class-wp.php
===================================================================
--- src/wp-includes/class-wp.php	(revision 38271)
+++ src/wp-includes/class-wp.php	(working copy)
@@ -91,6 +91,14 @@
 	 */
 	public $did_permalink = false;
 
+	public static function get( $key, $global = false ) {
+		return WP_Registry::instance()->get( $key, $global );
+	}
+
+	public static function set( $key, $value = null, $global = false ) {
+		return WP_Registry::instance()->set( $key, $value, $global );
+	}
+
 	/**
 	 * Add name to list of public query variables.
 	 *
Index: src/wp-includes/comment-template.php
===================================================================
--- src/wp-includes/comment-template.php	(revision 38271)
+++ src/wp-includes/comment-template.php	(working copy)
@@ -1275,7 +1275,6 @@
  *
  * @global WP_Query   $wp_query
  * @global WP_Post    $post
- * @global wpdb       $wpdb
  * @global int        $id
  * @global WP_Comment $comment
  * @global string     $user_login
@@ -1289,8 +1288,10 @@
  *                                  Default false.
  */
 function comments_template( $file = '/comments.php', $separate_comments = false ) {
-	global $wp_query, $withcomments, $post, $wpdb, $id, $comment, $user_login, $user_ID, $user_identity, $overridden_cpage;
+	global $wp_query, $withcomments, $post, $id, $comment, $user_login, $user_ID, $user_identity, $overridden_cpage;
 
+	$wpdb = WP::get( 'wpdb' );
+
 	if ( !(is_single() || is_page() || $withcomments) || empty($post) )
 		return;
 
Index: src/wp-includes/comment.php
===================================================================
--- src/wp-includes/comment.php	(revision 38271)
+++ src/wp-includes/comment.php	(working copy)
@@ -24,8 +24,6 @@
  *
  * @since 1.2.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $author       Comment author name.
  * @param string $email        Comment author email.
  * @param string $url          Comment author URL.
@@ -37,8 +35,6 @@
  * @return bool If all checks pass, true, otherwise false.
  */
 function check_comment($author, $email, $url, $comment, $user_ip, $user_agent, $comment_type) {
-	global $wpdb;
-
 	// If manual moderation is enabled, skip all checks and return false.
 	if ( 1 == get_option('comment_moderation') )
 		return false;
@@ -110,6 +106,7 @@
 	 */
 	if ( 1 == get_option('comment_whitelist')) {
 		if ( 'trackback' != $comment_type && 'pingback' != $comment_type && $author != '' && $email != '' ) {
+			$wpdb = WP::get( 'wpdb' );
 			// expected_slashed ($author, $email)
 			$ok_to_comment = $wpdb->get_var("SELECT comment_approved FROM $wpdb->comments WHERE comment_author = '$author' AND comment_author_email = '$email' and comment_approved = '1' LIMIT 1");
 			if ( ( 1 == $ok_to_comment ) &&
@@ -287,7 +284,6 @@
  *
  * @since 1.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
  * @staticvar array $cache_lastcommentmodified
  *
  * @param string $timezone Which timezone to use in reference to 'gmt', 'blog',
@@ -295,7 +291,6 @@
  * @return string Last comment modified date.
  */
 function get_lastcommentmodified($timezone = 'server') {
-	global $wpdb;
 	static $cache_lastcommentmodified = array();
 
 	if ( isset($cache_lastcommentmodified[$timezone]) )
@@ -303,6 +298,7 @@
 
 	$add_seconds_server = date('Z');
 
+	$wpdb = WP::get( 'wpdb' );
 	switch ( strtolower($timezone)) {
 		case 'gmt':
 			$lastcommentmodified = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1");
@@ -328,14 +324,11 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $post_id Optional. Comment amount in post if > 0, else total comments blog wide.
  * @return array The amount of spam, approved, awaiting moderation, and total comments.
  */
 function get_comment_count( $post_id = 0 ) {
-	global $wpdb;
-
+	$wpdb = WP::get( 'wpdb' );
 	$post_id = (int) $post_id;
 
 	$where = '';
@@ -582,13 +575,11 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array $commentdata Contains information on the comment
  * @return int|string Signifies the approval status (0|1|'spam')
  */
 function wp_allow_comment( $commentdata ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	// Simple duplicate check
 	// expected_slashed ($comment_post_ID, $comment_author, $comment_author_email, $comment_content)
@@ -715,14 +706,11 @@
  *
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $ip Comment IP.
  * @param string $email Comment author email address.
  * @param string $date MySQL time string.
  */
 function check_comment_flood_db( $ip, $email, $date ) {
-	global $wpdb;
 	// don't throttle admins or moderators
 	if ( current_user_can( 'manage_options' ) || current_user_can( 'moderate_comments' ) ) {
 		return;
@@ -737,6 +725,7 @@
 		$check_column = '`comment_author_IP`';
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$sql = $wpdb->prepare(
 		"SELECT `comment_date_gmt` FROM `$wpdb->comments` WHERE `comment_date_gmt` >= %s AND ( $check_column = %s OR `comment_author_email` = %s ) ORDER BY `comment_date_gmt` DESC LIMIT 1",
 		$hour_ago,
@@ -854,8 +843,6 @@
  *
  * @since 2.7.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int   $comment_ID Comment ID.
  * @param array $args {
  *      Array of optional arguments.
@@ -870,8 +857,6 @@
  * @return int|null Comment page number or null on error.
  */
 function get_page_of_comment( $comment_ID, $args = array() ) {
-	global $wpdb;
-
 	$page = null;
 
 	if ( !$comment = get_comment( $comment_ID ) )
@@ -913,6 +898,7 @@
 		if ( $args['max_depth'] > 1 && 0 != $comment->comment_parent )
 			return get_page_of_comment( $comment->comment_parent, $args );
 
+		$wpdb = WP::get( 'wpdb' );
 		$comment_args = array(
 			'type'       => $args['type'],
 			'post_id'    => $comment->comment_post_ID,
@@ -974,13 +960,10 @@
  *
  * @since 4.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @return array Maximum character length for the comment form fields.
  */
 function wp_get_comment_fields_max_lengths() {
-	global $wpdb;
-
+	$wpdb = WP::get( 'wpdb' );
 	$lengths = array(
 		'comment_author'       => 245,
 		'comment_author_email' => 100,
@@ -1144,14 +1127,11 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|WP_Comment $comment_id   Comment ID or WP_Comment object.
  * @param bool           $force_delete Whether to bypass trash and force deletion. Default is false.
  * @return bool True on success, false on failure.
  */
 function wp_delete_comment($comment_id, $force_delete = false) {
-	global $wpdb;
 	if (!$comment = get_comment($comment_id))
 		return false;
 
@@ -1167,6 +1147,7 @@
 	 */
 	do_action( 'delete_comment', $comment->comment_ID );
 
+	$wpdb = WP::get( 'wpdb' );
 	// Move children up a level.
 	$children = $wpdb->get_col( $wpdb->prepare("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent = %d", $comment->comment_ID) );
 	if ( !empty($children) ) {
@@ -1532,8 +1513,6 @@
  * @since 2.0.0
  * @since 4.4.0 Introduced `$comment_meta` argument.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array $commentdata {
  *     Array of arguments for inserting a new comment.
  *
@@ -1562,7 +1541,6 @@
  * @return int|false The new comment's ID on success, false on failure.
  */
 function wp_insert_comment( $commentdata ) {
-	global $wpdb;
 	$data = wp_unslash( $commentdata );
 
 	$comment_author       = ! isset( $data['comment_author'] )       ? '' : $data['comment_author'];
@@ -1584,6 +1562,7 @@
 	$user_id  = ! isset( $data['user_id'] ) ? 0 : $data['user_id'];
 
 	$compacted = compact( 'comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_date', 'comment_date_gmt', 'comment_content', 'comment_karma', 'comment_approved', 'comment_agent', 'comment_type', 'comment_parent', 'user_id' );
+	$wpdb = WP::get( 'wpdb' );
 	if ( ! $wpdb->insert( $wpdb->comments, $compacted ) ) {
 		return false;
 	}
@@ -1717,7 +1696,6 @@
  * @since 4.3.0 'comment_agent' and 'comment_author_IP' can be set via `$commentdata`.
  *
  * @see wp_insert_comment()
- * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param array $commentdata {
  *     Comment data.
@@ -1741,8 +1719,6 @@
  * @return int|false The ID of the comment on success, false on failure.
  */
 function wp_new_comment( $commentdata ) {
-	global $wpdb;
-
 	if ( isset( $commentdata['user_ID'] ) ) {
 		$commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID'];
 	}
@@ -1797,6 +1773,7 @@
 
 		foreach ( $fields as $field ) {
 			if ( isset( $commentdata[ $field ] ) ) {
+				$wpdb = WP::get( 'wpdb' );
 				$commentdata[ $field ] = $wpdb->strip_invalid_text_for_column( $wpdb->comments, $field, $commentdata[ $field ] );
 			}
 		}
@@ -1901,8 +1878,6 @@
  *
  * @since 1.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|WP_Comment $comment_id     Comment ID or WP_Comment object.
  * @param string         $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'.
  * @param bool           $wp_error       Whether to return a WP_Error object if there is a failure. Default is false.
@@ -1909,8 +1884,6 @@
  * @return bool|WP_Error True on success, false or WP_Error on failure.
  */
 function wp_set_comment_status($comment_id, $comment_status, $wp_error = false) {
-	global $wpdb;
-
 	switch ( $comment_status ) {
 		case 'hold':
 		case '0':
@@ -1933,11 +1906,13 @@
 
 	$comment_old = clone get_comment($comment_id);
 
+	$wpdb = WP::get( 'wpdb' );
 	if ( !$wpdb->update( $wpdb->comments, array('comment_approved' => $status), array( 'comment_ID' => $comment_old->comment_ID ) ) ) {
-		if ( $wp_error )
+		if ( $wp_error ) {
 			return new WP_Error('db_update_error', __('Could not update comment status'), $wpdb->last_error);
-		else
+		} else {
 			return false;
+		}
 	}
 
 	clean_comment_cache( $comment_old->comment_ID );
@@ -1970,14 +1945,10 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array $commentarr Contains information on the comment.
  * @return int Comment was updated if value is 1, or was not updated if value is 0.
  */
 function wp_update_comment($commentarr) {
-	global $wpdb;
-
 	// First, get all of the original fields
 	$comment = get_comment($commentarr['comment_ID'], ARRAY_A);
 	if ( empty( $comment ) ) {
@@ -2025,6 +1996,7 @@
 	$comment_post_ID = $data['comment_post_ID'];
 	$keys = array( 'comment_post_ID', 'comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt', 'comment_type', 'comment_parent', 'user_id', 'comment_agent', 'comment_author_IP' );
 	$data = wp_array_slice_assoc( $data, $keys );
+	$wpdb = WP::get( 'wpdb' );
 	$rval = $wpdb->update( $wpdb->comments, $data, compact( 'comment_ID' ) );
 
 	clean_comment_cache( $comment_ID );
@@ -2125,13 +2097,10 @@
  *
  * @since 2.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $post_id Post ID
  * @return bool True on success, false on '0' $post_id or if post with ID does not exist.
  */
 function wp_update_comment_count_now($post_id) {
-	global $wpdb;
 	$post_id = (int) $post_id;
 	if ( !$post_id )
 		return false;
@@ -2155,6 +2124,7 @@
 	 */
 	$new = apply_filters( 'pre_wp_update_comment_count_now', null, $old, $post_id );
 
+	$wpdb = WP::get( 'wpdb' );
 	if ( is_null( $new ) ) {
 		$new = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id ) );
 	} else {
@@ -2260,11 +2230,9 @@
  * Perform all pingbacks, enclosures, trackbacks, and send to pingback services.
  *
  * @since 2.1.0
- *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function do_all_pings() {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	// Do pingbacks
 	while ($ping = $wpdb->get_row("SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_pingme' LIMIT 1")) {
@@ -2293,17 +2261,14 @@
  *
  * @since 1.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $post_id Post ID to do trackbacks on.
  */
 function do_trackbacks($post_id) {
-	global $wpdb;
-
 	$post = get_post( $post_id );
 	$to_ping = get_to_ping($post_id);
 	$pinged  = get_pung($post_id);
 	if ( empty($to_ping) ) {
+		$wpdb = WP::get( 'wpdb' );
 		$wpdb->update($wpdb->posts, array('to_ping' => ''), array('ID' => $post_id) );
 		return;
 	}
@@ -2330,6 +2295,7 @@
 				trackback($tb_ping, $post_title, $excerpt, $post_id);
 				$pinged[] = $tb_ping;
 			} else {
+				$wpdb = WP::get( 'wpdb' );
 				$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $tb_ping, $post_id) );
 			}
 		}
@@ -2469,8 +2435,6 @@
  *
  * @since 0.71
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $trackback_url URL to send trackbacks.
  * @param string $title Title of post.
  * @param string $excerpt Excerpt of post.
@@ -2478,8 +2442,6 @@
  * @return int|false|void Database query from update.
  */
 function trackback($trackback_url, $title, $excerpt, $ID) {
-	global $wpdb;
-
 	if ( empty($trackback_url) )
 		return;
 
@@ -2497,6 +2459,7 @@
 	if ( is_wp_error( $response ) )
 		return;
 
+	$wpdb = WP::get( 'wpdb' );
 	$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', %s) WHERE ID = %d", $trackback_url, $ID) );
 	return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $trackback_url, $ID) );
 }
@@ -2621,16 +2584,14 @@
  * @access private
  *
  * @see update_comment_cache()
- * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param array $comment_ids       Array of comment IDs.
  * @param bool  $update_meta_cache Optional. Whether to update the meta cache. Default true.
  */
 function _prime_comment_caches( $comment_ids, $update_meta_cache = true ) {
-	global $wpdb;
-
 	$non_cached_ids = _get_non_cached_ids( $comment_ids, 'comment' );
 	if ( !empty( $non_cached_ids ) ) {
+		$wpdb = WP::get( 'wpdb' );
 		$fresh_comments = $wpdb->get_results( sprintf( "SELECT $wpdb->comments.* FROM $wpdb->comments WHERE comment_ID IN (%s)", join( ",", array_map( 'intval', $non_cached_ids ) ) ) );
 
 		update_comment_cache( $fresh_comments, $update_meta_cache );
Index: src/wp-includes/date.php
===================================================================
--- src/wp-includes/date.php	(revision 38271)
+++ src/wp-includes/date.php	(working copy)
@@ -62,6 +62,8 @@
 	 */
 	public $time_keys = array( 'after', 'before', 'year', 'month', 'monthnum', 'week', 'w', 'dayofyear', 'day', 'dayofweek', 'dayofweek_iso', 'hour', 'minute', 'second' );
 
+	protected $dbh;
+
 	/**
 	 * Constructor.
 	 *
@@ -158,6 +160,8 @@
 			$this->relation = 'AND';
 		}
 
+		$this->dbh = WP::get( 'wpdb' );
+
 		if ( ! is_array( $date_query ) ) {
 			return;
 		}
@@ -486,8 +490,6 @@
 	 * @return string A validated column name value.
 	 */
 	public function validate_column( $column ) {
-		global $wpdb;
-
 		$valid_columns = array(
 			'post_date', 'post_date_gmt', 'post_modified',
 			'post_modified_gmt', 'comment_date', 'comment_date_gmt',
@@ -512,20 +514,20 @@
 			}
 
 			$known_columns = array(
-				$wpdb->posts => array(
+				$this->dbh->posts => array(
 					'post_date',
 					'post_date_gmt',
 					'post_modified',
 					'post_modified_gmt',
 				),
-				$wpdb->comments => array(
+				$this->dbh->comments => array(
 					'comment_date',
 					'comment_date_gmt',
 				),
-				$wpdb->users => array(
+				$this->dbh->users => array(
 					'user_registered',
 				),
-				$wpdb->blogs => array(
+				$this->dbh->blogs => array(
 					'registered',
 					'last_updated',
 				),
@@ -717,8 +719,6 @@
 	 * }
 	 */
 	protected function get_sql_for_clause( $query, $parent_query ) {
-		global $wpdb;
-
 		// The sub-parts of a $where part.
 		$where_parts = array();
 
@@ -741,10 +741,10 @@
 
 		// Range queries.
 		if ( ! empty( $query['after'] ) )
-			$where_parts[] = $wpdb->prepare( "$column $gt %s", $this->build_mysql_datetime( $query['after'], ! $inclusive ) );
+			$where_parts[] = $this->dbh->prepare( "$column $gt %s", $this->build_mysql_datetime( $query['after'], ! $inclusive ) );
 
 		if ( ! empty( $query['before'] ) )
-			$where_parts[] = $wpdb->prepare( "$column $lt %s", $this->build_mysql_datetime( $query['before'], $inclusive ) );
+			$where_parts[] = $this->dbh->prepare( "$column $lt %s", $this->build_mysql_datetime( $query['before'], $inclusive ) );
 
 		// Specific value queries.
 
@@ -958,8 +958,6 @@
 	 * @return string|false A query part or false on failure.
 	 */
 	public function build_time_query( $column, $compare, $hour = null, $minute = null, $second = null ) {
-		global $wpdb;
-
 		// Have to have at least one
 		if ( ! isset( $hour ) && ! isset( $minute ) && ! isset( $second ) )
 			return false;
@@ -1013,6 +1011,6 @@
 			$time   .= sprintf( '%02d', $second );
 		}
 
-		return $wpdb->prepare( "DATE_FORMAT( $column, %s ) $compare %f", $format, $time );
+		return $this->dbh->prepare( "DATE_FORMAT( $column, %s ) $compare %f", $format, $time );
 	}
 }
Index: src/wp-includes/deprecated.php
===================================================================
--- src/wp-includes/deprecated.php	(revision 38271)
+++ src/wp-includes/deprecated.php	(working copy)
@@ -2210,7 +2210,7 @@
  */
 function delete_usermeta( $user_id, $meta_key, $meta_value = '' ) {
 	_deprecated_function( __FUNCTION__, '3.0.0', 'delete_user_meta()' );
-	global $wpdb;
+
 	if ( !is_numeric( $user_id ) )
 		return false;
 	$meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key);
@@ -2219,6 +2219,7 @@
 		$meta_value = serialize($meta_value);
 	$meta_value = trim( $meta_value );
 
+	$wpdb = WP::get( 'wpdb' );
 	$cur = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) );
 
 	if ( $cur && $cur->umeta_id )
@@ -2256,12 +2257,14 @@
  */
 function get_usermeta( $user_id, $meta_key = '' ) {
 	_deprecated_function( __FUNCTION__, '3.0.0', 'get_user_meta()' );
-	global $wpdb;
+
 	$user_id = (int) $user_id;
 
 	if ( !$user_id )
 		return false;
 
+	$wpdb = WP::get( 'wpdb' );
+
 	if ( !empty($meta_key) ) {
 		$meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key);
 		$user = wp_cache_get($user_id, 'users');
@@ -2309,7 +2312,7 @@
  */
 function update_usermeta( $user_id, $meta_key, $meta_value ) {
 	_deprecated_function( __FUNCTION__, '3.0.0', 'update_user_meta()' );
-	global $wpdb;
+
 	if ( !is_numeric( $user_id ) )
 		return false;
 	$meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key);
@@ -2323,6 +2326,7 @@
 		return delete_usermeta($user_id, $meta_key);
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$cur = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) );
 
 	if ( $cur )
@@ -2356,7 +2360,6 @@
  * @deprecated 3.1.0 Use get_users()
  * @see get_users()
  *
- * @global wpdb $wpdb    WordPress database abstraction object.
  * @global int  $blog_id The site ID of the site for those that use more than one site.
  *
  * @param int $id Site ID.
@@ -2365,9 +2368,11 @@
 function get_users_of_blog( $id = '' ) {
 	_deprecated_function( __FUNCTION__, '3.1.0', 'get_users()' );
 
-	global $wpdb, $blog_id;
-	if ( empty($id) )
+	global $blog_id;
+	if ( empty( $id ) ) {
 		$id = (int) $blog_id;
+	}
+	$wpdb = WP::get( 'wpdb' );
 	$blog_prefix = $wpdb->get_blog_prefix($id);
 	$users = $wpdb->get_results( "SELECT user_id, user_id AS ID, user_login, display_name, user_email, meta_value FROM $wpdb->users, $wpdb->usermeta WHERE {$wpdb->users}.ID = {$wpdb->usermeta}.user_id AND meta_key = '{$blog_prefix}capabilities' ORDER BY {$wpdb->usermeta}.user_id" );
 	return $users;
Index: src/wp-includes/formatting.php
===================================================================
--- src/wp-includes/formatting.php	(revision 38271)
+++ src/wp-includes/formatting.php	(working copy)
@@ -3717,14 +3717,11 @@
  *
  * @since 2.8.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string|array $data Unescaped data
  * @return string|array Escaped data
  */
 function esc_sql( $data ) {
-	global $wpdb;
-	return $wpdb->_escape( $data );
+	return WP::get( 'wpdb' )->_escape( $data );
 }
 
 /**
@@ -4012,18 +4009,16 @@
  *
  * @since 2.0.5
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $option The name of the option.
  * @param string $value  The unsanitised value.
  * @return string Sanitized value.
  */
 function sanitize_option( $option, $value ) {
-	global $wpdb;
-
 	$original_value = $value;
 	$error = '';
 
+	$wpdb = WP::get( 'wpdb' );
+
 	switch ( $option ) {
 		case 'admin_email' :
 		case 'new_admin_email' :
Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 38271)
+++ src/wp-includes/functions.php	(working copy)
@@ -554,13 +554,11 @@
  *
  * @since 1.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $content Post Content.
  * @param int    $post_ID Post ID.
  */
 function do_enclose( $content, $post_ID ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	//TODO: Tidy this ghetto code up and make the debug code optional
 	include_once( ABSPATH . WPINC . '/class-IXR.php' );
@@ -1183,13 +1181,10 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @return int Number of database queries.
  */
 function get_num_queries() {
-	global $wpdb;
-	return $wpdb->num_queries;
+	return WP::get( 'wpdb' )->num_queries;
 }
 
 /**
@@ -1353,13 +1348,9 @@
  *
  * @since 2.1.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @return bool Whether the site is already installed.
  */
 function is_blog_installed() {
-	global $wpdb;
-
 	/*
 	 * Check cache first. If options table goes away and we have true
 	 * cached, oh well.
@@ -1367,6 +1358,7 @@
 	if ( wp_cache_get( 'is_blog_installed' ) )
 		return true;
 
+	$wpdb = WP::get( 'wpdb' );
 	$suppress = $wpdb->suppress_errors();
 	if ( ! wp_installing() ) {
 		$alloptions = wp_load_alloptions();
@@ -3612,11 +3604,9 @@
  * in WordPress 2.5.0.
  *
  * @since 2.3.2
- *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function dead_db() {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	wp_load_translations_early();
 
@@ -4285,13 +4275,9 @@
  *
  * @since 4.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @return int The ID of the main network.
  */
 function get_main_network_id() {
-	global $wpdb;
-
 	if ( ! is_multisite() ) {
 		return 1;
 	}
@@ -4307,6 +4293,7 @@
 		$main_network_id = wp_cache_get( 'primary_network_id', 'site-options' );
 
 		if ( false === $main_network_id ) {
+			$wpdb = WP::get( 'wpdb' );
 			$main_network_id = (int) $wpdb->get_var( "SELECT id FROM {$wpdb->site} ORDER BY id LIMIT 1" );
 			wp_cache_add( 'primary_network_id', $main_network_id, 'site-options' );
 		}
@@ -4580,11 +4567,9 @@
  * The default value of `EMPTY_TRASH_DAYS` is 30 (days).
  *
  * @since 2.9.0
- *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function wp_scheduled_delete() {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
 
Index: src/wp-includes/general-template.php
===================================================================
--- src/wp-includes/general-template.php	(revision 38271)
+++ src/wp-includes/general-template.php	(working copy)
@@ -1611,7 +1611,6 @@
  *
  * @see get_archives_link()
  *
- * @global wpdb      $wpdb
  * @global WP_Locale $wp_locale
  *
  * @param string|array $args {
@@ -1639,7 +1638,7 @@
  * @return string|void String when retrieving.
  */
 function wp_get_archives( $args = '' ) {
-	global $wpdb, $wp_locale;
+	global $wp_locale;
 
 	$defaults = array(
 		'type' => 'monthly', 'limit' => '',
@@ -1674,6 +1673,7 @@
 	// this is what will separate dates on weekly archive links
 	$archive_week_separator = '&#8211;';
 
+	$wpdb = WP::get( 'wpdb' );
 	$sql_where = $wpdb->prepare( "WHERE post_type = %s AND post_status = 'publish'", $r['post_type'] );
 
 	/**
@@ -1857,7 +1857,6 @@
  *
  * @since 1.0.0
  *
- * @global wpdb      $wpdb
  * @global int       $m
  * @global int       $monthnum
  * @global int       $year
@@ -1869,8 +1868,10 @@
  * @return string|void String when retrieving.
  */
 function get_calendar( $initial = true, $echo = true ) {
-	global $wpdb, $m, $monthnum, $year, $wp_locale, $posts;
+	global $m, $monthnum, $year, $wp_locale, $posts;
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$key = md5( $m . $monthnum . $year );
 	$cache = wp_cache_get( 'get_calendar', 'calendar' );
 
Index: src/wp-includes/http.php
===================================================================
--- src/wp-includes/http.php	(revision 38271)
+++ src/wp-includes/http.php	(working copy)
@@ -602,7 +602,6 @@
  *
  * @since 3.6.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
  * @staticvar array $queried
  *
  * @param bool   $is_external
@@ -610,7 +609,6 @@
  * @return bool
  */
 function ms_allowed_http_request_hosts( $is_external, $host ) {
-	global $wpdb;
 	static $queried = array();
 	if ( $is_external )
 		return $is_external;
@@ -618,6 +616,8 @@
 		return true;
 	if ( isset( $queried[ $host ] ) )
 		return $queried[ $host ];
+
+	$wpdb = WP::get( 'wpdb' );
 	$queried[ $host ] = (bool) $wpdb->get_var( $wpdb->prepare( "SELECT domain FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $host ) );
 	return $queried[ $host ];
 }
Index: src/wp-includes/link-template.php
===================================================================
--- src/wp-includes/link-template.php	(revision 38271)
+++ src/wp-includes/link-template.php	(working copy)
@@ -1576,8 +1576,6 @@
  *
  * @since 2.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param bool         $in_same_term   Optional. Whether post should be in a same taxonomy term. Default false.
  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty.
  * @param bool         $previous       Optional. Whether to retrieve previous post. Default true
@@ -1586,11 +1584,11 @@
  *                             corresponding post exists.
  */
 function get_adjacent_post( $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
-	global $wpdb;
-
 	if ( ( ! $post = get_post() ) || ! taxonomy_exists( $taxonomy ) )
 		return null;
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$current_post_date = $post->post_date;
 
 	$join = '';
Index: src/wp-includes/load.php
===================================================================
--- src/wp-includes/load.php	(revision 38271)
+++ src/wp-includes/load.php	(working copy)
@@ -388,20 +388,23 @@
  * Load the database class file and instantiate the `$wpdb` global.
  *
  * @since 2.5.0
- *
- * @global wpdb $wpdb The WordPress database class.
  */
 function require_wp_db() {
-	global $wpdb;
+	$wpdb = null;
 
 	require_once( ABSPATH . WPINC . '/wp-db.php' );
-	if ( file_exists( WP_CONTENT_DIR . '/db.php' ) )
+	if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) {
 		require_once( WP_CONTENT_DIR . '/db.php' );
+	}
 
-	if ( isset( $wpdb ) )
+	if ( isset( $wpdb ) ) {
+		WP::set( 'wpdb', $wpdb, true );
 		return;
+	}
 
-	$wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
+	$db = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
+
+	WP::set( 'wpdb', $db, true );
 }
 
 /**
Index: src/wp-includes/media.php
===================================================================
--- src/wp-includes/media.php	(revision 38271)
+++ src/wp-includes/media.php	(working copy)
@@ -3216,7 +3216,6 @@
  * @since 3.5.0
  *
  * @global int       $content_width
- * @global wpdb      $wpdb
  * @global WP_Locale $wp_locale
  *
  * @param array $args {
@@ -3230,7 +3229,7 @@
 	if ( did_action( 'wp_enqueue_media' ) )
 		return;
 
-	global $content_width, $wpdb, $wp_locale;
+	global $content_width, $wp_locale;
 
 	$defaults = array(
 		'post' => null,
@@ -3269,6 +3268,8 @@
 		}
 	}
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$has_audio = $wpdb->get_var( "
 		SELECT ID
 		FROM $wpdb->posts
@@ -3743,14 +3744,10 @@
  *
  * @since 4.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $url The URL to resolve.
  * @return int The found post ID, or 0 on failure.
  */
 function attachment_url_to_postid( $url ) {
-	global $wpdb;
-
 	$dir = wp_get_upload_dir();
 	$path = $url;
 
@@ -3766,6 +3763,7 @@
 		$path = substr( $path, strlen( $dir['baseurl'] . '/' ) );
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$sql = $wpdb->prepare(
 		"SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = %s",
 		$path
Index: src/wp-includes/meta.php
===================================================================
--- src/wp-includes/meta.php	(revision 38271)
+++ src/wp-includes/meta.php	(working copy)
@@ -15,8 +15,6 @@
  *
  * @since 2.9.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $meta_type  Type of object metadata is for (e.g., comment, post, or user)
  * @param int    $object_id  ID of the object metadata is for
  * @param string $meta_key   Metadata key
@@ -28,8 +26,6 @@
  * @return int|false The meta ID on success, false on failure.
  */
 function add_metadata($meta_type, $object_id, $meta_key, $meta_value, $unique = false) {
-	global $wpdb;
-
 	if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
 		return false;
 	}
@@ -71,6 +67,7 @@
 	if ( null !== $check )
 		return $check;
 
+	$wpdb = WP::get( 'wpdb' );
 	if ( $unique && $wpdb->get_var( $wpdb->prepare(
 		"SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d",
 		$meta_key, $object_id ) ) )
@@ -130,8 +127,6 @@
  *
  * @since 2.9.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $meta_type  Type of object metadata is for (e.g., comment, post, or user)
  * @param int    $object_id  ID of the object metadata is for
  * @param string $meta_key   Metadata key
@@ -141,8 +136,6 @@
  * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
  */
 function update_metadata($meta_type, $object_id, $meta_key, $meta_value, $prev_value = '') {
-	global $wpdb;
-
 	if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
 		return false;
 	}
@@ -197,6 +190,7 @@
 		}
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s AND $column = %d", $meta_key, $object_id ) );
 	if ( empty( $meta_ids ) ) {
 		return add_metadata( $meta_type, $object_id, $raw_meta_key, $passed_value );
@@ -289,8 +283,6 @@
  *
  * @since 2.9.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $meta_type  Type of object metadata is for (e.g., comment, post, or user)
  * @param int    $object_id  ID of the object metadata is for
  * @param string $meta_key   Metadata key
@@ -305,8 +297,6 @@
  * @return bool True on successful delete, false on failure.
  */
 function delete_metadata($meta_type, $object_id, $meta_key, $meta_value = '', $delete_all = false) {
-	global $wpdb;
-
 	if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) && ! $delete_all ) {
 		return false;
 	}
@@ -351,6 +341,8 @@
 	$_meta_value = $meta_value;
 	$meta_value = maybe_serialize( $meta_value );
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$query = $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s", $meta_key );
 
 	if ( !$delete_all )
@@ -558,15 +550,11 @@
  *
  * @since 3.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
  * @param int    $meta_id   ID for a specific meta row
  * @return object|false Meta object or false.
  */
 function get_metadata_by_mid( $meta_type, $meta_id ) {
-	global $wpdb;
-
 	if ( ! $meta_type || ! is_numeric( $meta_id ) ) {
 		return false;
 	}
@@ -583,6 +571,7 @@
 
 	$id_column = ( 'user' == $meta_type ) ? 'umeta_id' : 'meta_id';
 
+	$wpdb = WP::get( 'wpdb' );
 	$meta = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table WHERE $id_column = %d", $meta_id ) );
 
 	if ( empty( $meta ) )
@@ -599,8 +588,6 @@
  *
  * @since 3.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $meta_type  Type of object metadata is for (e.g., comment, post, or user)
  * @param int    $meta_id    ID for a specific meta row
  * @param string $meta_value Metadata value
@@ -608,8 +595,6 @@
  * @return bool True on successful update, false on failure.
  */
 function update_metadata_by_mid( $meta_type, $meta_id, $meta_value, $meta_key = false ) {
-	global $wpdb;
-
 	// Make sure everything is valid.
 	if ( ! $meta_type || ! is_numeric( $meta_id ) ) {
 		return false;
@@ -664,6 +649,7 @@
 			do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
 		}
 
+		$wpdb = WP::get( 'wpdb' );
 		// Run the update query, all fields in $data are %s, $where is a %d.
 		$result = $wpdb->update( $table, $data, $where, '%s', '%d' );
 		if ( ! $result )
@@ -692,15 +678,11 @@
  *
  * @since 3.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
  * @param int    $meta_id   ID for a specific meta row
  * @return bool True on successful delete, false on failure.
  */
 function delete_metadata_by_mid( $meta_type, $meta_id ) {
-	global $wpdb;
-
 	// Make sure everything is valid.
 	if ( ! $meta_type || ! is_numeric( $meta_id ) ) {
 		return false;
@@ -742,6 +724,7 @@
 			do_action( "delete_{$meta_type}meta", $meta_id );
 		}
 
+		$wpdb = WP::get( 'wpdb' );
 		// Run the query, will return true if deleted, false otherwise
 		$result = (bool) $wpdb->delete( $table, array( $id_column => $meta_id ) );
 
@@ -779,15 +762,11 @@
  *
  * @since 2.9.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string    $meta_type  Type of object metadata is for (e.g., comment, post, or user)
  * @param int|array $object_ids Array or comma delimited list of object IDs to update cache for
  * @return array|false Metadata cache for the specified objects, or false on failure.
  */
 function update_meta_cache($meta_type, $object_ids) {
-	global $wpdb;
-
 	if ( ! $meta_type || ! $object_ids ) {
 		return false;
 	}
@@ -823,6 +802,8 @@
 	// Get meta info
 	$id_list = join( ',', $ids );
 	$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
+
+	$wpdb = WP::get( 'wpdb' );
 	$meta_list = $wpdb->get_results( "SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC", ARRAY_A );
 
 	if ( !empty($meta_list) ) {
@@ -892,13 +873,11 @@
  *
  * @since 2.9.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $type Type of object to get metadata table for (e.g., comment, post, or user)
  * @return string|false Metadata table name, or false if no metadata table exists
  */
 function _get_meta_table($type) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$table_name = $type . 'meta';
 
Index: src/wp-includes/ms-blogs.php
===================================================================
--- src/wp-includes/ms-blogs.php	(revision 38271)
+++ src/wp-includes/ms-blogs.php	(working copy)
@@ -12,11 +12,9 @@
  * Update the last_updated field for the current site.
  *
  * @since MU
- *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function wpmu_update_blogs_date() {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	update_blog_details( $wpdb->blogid, array('last_updated' => current_time('mysql', true)) );
 	/**
@@ -76,14 +74,10 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $slug
  * @return int A blog id
  */
 function get_id_from_blogname( $slug ) {
-	global $wpdb;
-
 	$current_site = get_current_site();
 	$slug = trim( $slug, '/' );
 
@@ -99,6 +93,7 @@
 		$path = $current_site->path . $slug . '/';
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$blog_id = $wpdb->get_var( $wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE domain = %s AND path = %s", $domain, $path) );
 	wp_cache_set( 'get_id_from_blogname_' . $slug, $blog_id, 'blog-details' );
 	return $blog_id;
@@ -109,8 +104,6 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|string|array $fields  Optional. A blog ID, a blog slug, or an array of fields to query against.
  *                                  If not specified the current blog ID is used.
  * @param bool             $get_all Whether to retrieve all details or only the details in the blogs table.
@@ -118,7 +111,7 @@
  * @return WP_Site|false Blog details on success. False on failure.
  */
 function get_blog_details( $fields = null, $get_all = true ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	if ( is_array($fields ) ) {
 		if ( isset($fields['blog_id']) ) {
@@ -293,15 +286,11 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int   $blog_id Blog ID
  * @param array $details Array of details keyed by blogs table field names.
  * @return bool True if update succeeds, false otherwise.
  */
 function update_blog_details( $blog_id, $details = array() ) {
-	global $wpdb;
-
 	if ( empty($details) )
 		return false;
 
@@ -327,6 +316,7 @@
 		$update_details[ $field ] = $details[ $field ];
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$result = $wpdb->update( $wpdb->blogs, $update_details, array('blog_id' => $blog_id) );
 
 	if ( false === $result )
@@ -517,15 +507,13 @@
  * @access private
  *
  * @see update_site_cache()
- * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param array $ids ID list.
  */
 function _prime_site_caches( $ids ) {
-	global $wpdb;
-
 	$non_cached_ids = _get_non_cached_ids( $ids, 'sites' );
 	if ( ! empty( $non_cached_ids ) ) {
+		$wpdb = WP::get( 'wpdb' );
 		$fresh_sites = $wpdb->get_results( sprintf( "SELECT * FROM $wpdb->blogs WHERE blog_id IN (%s)", join( ",", array_map( 'intval', $non_cached_ids ) ) ) );
 
 		update_site_cache( $fresh_sites );
@@ -752,7 +740,6 @@
  * @see restore_current_blog()
  * @since MU
  *
- * @global wpdb            $wpdb
  * @global int             $blog_id
  * @global array           $_wp_switched_stack
  * @global bool            $switched
@@ -764,8 +751,6 @@
  * @return true Always returns True.
  */
 function switch_to_blog( $new_blog, $deprecated = null ) {
-	global $wpdb;
-
 	if ( empty( $new_blog ) )
 		$new_blog = $GLOBALS['blog_id'];
 
@@ -790,6 +775,7 @@
 		return true;
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$wpdb->set_blog_id( $new_blog );
 	$GLOBALS['table_prefix'] = $wpdb->get_blog_prefix();
 	$prev_blog_id = $GLOBALS['blog_id'];
@@ -836,7 +822,6 @@
  * @see switch_to_blog()
  * @since MU
  *
- * @global wpdb            $wpdb
  * @global array           $_wp_switched_stack
  * @global int             $blog_id
  * @global bool            $switched
@@ -846,8 +831,6 @@
  * @return bool True on success, false if we're already on the current blog
  */
 function restore_current_blog() {
-	global $wpdb;
-
 	if ( empty( $GLOBALS['_wp_switched_stack'] ) )
 		return false;
 
@@ -861,6 +844,7 @@
 		return true;
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$wpdb->set_blog_id( $blog );
 	$prev_blog_id = $GLOBALS['blog_id'];
 	$GLOBALS['blog_id'] = $blog;
@@ -947,8 +931,6 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int    $blog_id BLog ID
  * @param string $pref    A field name
  * @param string $value   Value for $pref
@@ -956,8 +938,6 @@
  * @return string|false $value
  */
 function update_blog_status( $blog_id, $pref, $value, $deprecated = null ) {
-	global $wpdb;
-
 	if ( null !== $deprecated  )
 		_deprecated_argument( __FUNCTION__, '3.1.0' );
 
@@ -964,6 +944,7 @@
 	if ( ! in_array( $pref, array( 'site_id', 'domain', 'path', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id') ) )
 		return $value;
 
+	$wpdb = WP::get( 'wpdb' );
 	$result = $wpdb->update( $wpdb->blogs, array($pref => $value, 'last_updated' => current_time('mysql', true)), array('blog_id' => $blog_id) );
 
 	if ( false === $result )
@@ -1023,19 +1004,16 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int    $id   The blog id
  * @param string $pref A field name
  * @return bool|string|null $value
  */
 function get_blog_status( $id, $pref ) {
-	global $wpdb;
-
 	$details = get_blog_details( $id, false );
 	if ( $details )
 		return $details->$pref;
 
+	$wpdb = WP::get( 'wpdb' );
 	return $wpdb->get_var( $wpdb->prepare("SELECT %s FROM {$wpdb->blogs} WHERE blog_id = %d", $pref, $id) );
 }
 
@@ -1044,8 +1022,6 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param mixed $deprecated Not used
  * @param int   $start      The offset
  * @param int   $quantity   The maximum number of blogs to retrieve. Default is 40.
@@ -1052,11 +1028,10 @@
  * @return array The list of blogs
  */
 function get_last_updated( $deprecated = '', $start = 0, $quantity = 40 ) {
-	global $wpdb;
-
 	if ( ! empty( $deprecated ) )
 		_deprecated_argument( __FUNCTION__, 'MU' ); // never used
 
+	$wpdb = WP::get( 'wpdb' );
 	return $wpdb->get_results( $wpdb->prepare("SELECT blog_id, domain, path FROM $wpdb->blogs WHERE site_id = %d AND public = '1' AND archived = '0' AND mature = '0' AND spam = '0' AND deleted = '0' AND last_updated != '0000-00-00 00:00:00' ORDER BY last_updated DESC limit %d, %d", $wpdb->siteid, $start, $quantity ) , ARRAY_A );
 }
 
@@ -1166,15 +1141,13 @@
  * @access private
  *
  * @see update_network_cache()
- * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param array $network_ids Array of network IDs.
  */
 function _prime_network_caches( $network_ids ) {
-	global $wpdb;
-
 	$non_cached_ids = _get_non_cached_ids( $network_ids, 'networks' );
 	if ( !empty( $non_cached_ids ) ) {
+		$wpdb = WP::get( 'wpdb' );
 		$fresh_networks = $wpdb->get_results( sprintf( "SELECT $wpdb->site.* FROM $wpdb->site WHERE id IN (%s)", join( ",", array_map( 'intval', $non_cached_ids ) ) ) );
 
 		update_network_cache( $fresh_networks );
Index: src/wp-includes/ms-default-constants.php
===================================================================
--- src/wp-includes/ms-default-constants.php	(revision 38271)
+++ src/wp-includes/ms-default-constants.php	(working copy)
@@ -14,12 +14,8 @@
  * wp-includes/ms-files.php (wp-content/blogs.php in MU).
  *
  * @since 3.0.0
- *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function ms_upload_constants() {
-	global $wpdb;
-
 	// This filter is attached in ms-default-filters.php but that file is not included during SHORTINIT.
 	add_filter( 'default_site_option_ms_files_rewriting', '__return_true' );
 
@@ -33,6 +29,7 @@
 	// Note, the main site in a post-MU network uses wp-content/uploads.
 	// This is handled in wp_upload_dir() by ignoring UPLOADS for this case.
 	if ( ! defined( 'UPLOADS' ) ) {
+		$wpdb = WP::get( 'wpdb' );
 		define( 'UPLOADS', UPLOADBLOGSDIR . "/{$wpdb->blogid}/files/" );
 
 		// Uploads dir relative to ABSPATH
Index: src/wp-includes/ms-deprecated.php
===================================================================
--- src/wp-includes/ms-deprecated.php	(revision 38271)
+++ src/wp-includes/ms-deprecated.php	(working copy)
@@ -185,7 +185,7 @@
 function get_blog_list( $start = 0, $num = 10, $deprecated = '' ) {
 	_deprecated_function( __FUNCTION__, '3.0.0', 'wp_get_sites()' );
 
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 	$blogs = $wpdb->get_results( $wpdb->prepare("SELECT blog_id, domain, path FROM $wpdb->blogs WHERE site_id = %d AND public = '1' AND archived = '0' AND mature = '0' AND spam = '0' AND deleted = '0' ORDER BY registered DESC", $wpdb->siteid), ARRAY_A );
 
 	$blog_list = array();
@@ -417,8 +417,6 @@
  * @since MU 1.0
  * @deprecated 4.4.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $sitedomain Optional. Site domain.
  * @param string $path       Optional. Site path.
  * @return array|false The network admins
@@ -426,7 +424,7 @@
 function get_admin_users_for_domain( $sitedomain = '', $path = '' ) {
 	_deprecated_function( __FUNCTION__, '4.4.0' );
 
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	if ( ! $sitedomain )
 		$site_id = $wpdb->siteid;
@@ -446,8 +444,6 @@
  * @deprecated 4.6.0
  * @see get_sites()
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array $args {
  *     Array of default arguments. Optional.
  *
@@ -467,13 +463,13 @@
  *               values for whether the site is public, archived, mature, spam, and/or deleted.
  */
 function wp_get_sites( $args = array() ) {
-	global $wpdb;
-
 	_deprecated_function( __FUNCTION__, '4.6.0', 'get_sites()' );
 
 	if ( wp_is_large_network() )
 		return array();
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$defaults = array(
 		'network_id' => $wpdb->siteid,
 		'public'     => null,
Index: src/wp-includes/ms-functions.php
===================================================================
--- src/wp-includes/ms-functions.php	(revision 38271)
+++ src/wp-includes/ms-functions.php	(working copy)
@@ -34,17 +34,15 @@
  *
  * @since MU 1.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $user_id The unique ID of the user
  * @return WP_Site|void The blog object
  */
 function get_active_blog_for_user( $user_id ) {
-	global $wpdb;
 	$blogs = get_blogs_of_user( $user_id );
 	if ( empty( $blogs ) )
 		return;
 
+	$wpdb = WP::get( 'wpdb' );
 	if ( !is_multisite() )
 		return $blogs[$wpdb->blogid];
 
@@ -194,8 +192,6 @@
  *
  * @since MU 1.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int    $user_id  ID of the user you're removing.
  * @param int    $blog_id  ID of the blog you're removing the user from.
  * @param string $reassign Optional. A user to whom to reassign posts.
@@ -202,7 +198,6 @@
  * @return true|WP_Error
  */
 function remove_user_from_blog($user_id, $blog_id = '', $reassign = '') {
-	global $wpdb;
 	switch_to_blog($blog_id);
 	$user_id = (int) $user_id;
 	/**
@@ -250,6 +245,7 @@
 	}
 
 	if ( $reassign != '' ) {
+		$wpdb = WP::get( 'wpdb' );
 		$reassign = (int) $reassign;
 		$post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $user_id ) );
 		$link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $user_id ) );
@@ -297,8 +293,6 @@
  *
  * @since MU 2.6.5
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $domain
  * @param string $path   Optional. Not required for subdomain installations.
  * @return int 0 if no blog found, otherwise the ID of the matching blog
@@ -401,15 +395,11 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $user_name  The login name provided by the user.
  * @param string $user_email The email provided by the user.
  * @return array Contains username, email, and error messages.
  */
 function wpmu_validate_user_signup($user_name, $user_email) {
-	global $wpdb;
-
 	$errors = new WP_Error();
 
 	$orig_username = $user_name;
@@ -474,6 +464,7 @@
 	if ( email_exists($user_email) )
 		$errors->add( 'user_email', __( 'Sorry, that email address is already used!' ) );
 
+	$wpdb = WP::get( 'wpdb' );
 	// Has someone already signed up for this username?
 	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_login = %s", $user_name) );
 	if ( $signup != null ) {
@@ -535,7 +526,6 @@
  *
  * @since MU
  *
- * @global wpdb   $wpdb
  * @global string $domain
  *
  * @param string         $blogname   The blog name provided by the user. Must be unique.
@@ -544,7 +534,7 @@
  * @return array Contains the new site data and error messages.
  */
 function wpmu_validate_blog_signup( $blogname, $blog_title, $user = '' ) {
-	global $wpdb, $domain;
+	global $domain;
 
 	$current_site = get_current_site();
 	$base = $current_site->path;
@@ -579,6 +569,7 @@
 	if ( strlen( $blogname ) < 4 && !is_super_admin() )
 		$errors->add('blogname',  __( 'Site name must be at least 4 characters.' ) );
 
+	$wpdb = WP::get( 'wpdb' );
 	// do not allow users to create a blog that conflicts with a page on the main blog.
 	if ( !is_subdomain_install() && $wpdb->get_var( $wpdb->prepare( "SELECT post_name FROM " . $wpdb->get_blog_prefix( $current_site->blog_id ) . "posts WHERE post_type = 'page' AND post_name = %s", $blogname ) ) )
 		$errors->add( 'blogname', __( 'Sorry, you may not use that site name.' ) );
@@ -657,8 +648,6 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $domain     The requested domain.
  * @param string $path       The requested path.
  * @param string $title      The requested site title.
@@ -667,11 +656,10 @@
  * @param array  $meta       By default, contains the requested privacy setting and lang_id.
  */
 function wpmu_signup_blog( $domain, $path, $title, $user, $user_email, $meta = array() )  {
-	global $wpdb;
-
 	$key = substr( md5( time() . rand() . $domain ), 0, 16 );
 	$meta = serialize($meta);
 
+	$wpdb = WP::get( 'wpdb' );
 	$wpdb->insert( $wpdb->signups, array(
 		'domain' => $domain,
 		'path' => $path,
@@ -707,15 +695,11 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $user       The user's requested login name.
  * @param string $user_email The user's email address.
  * @param array  $meta       By default, this is an empty array.
  */
 function wpmu_signup_user( $user, $user_email, $meta = array() ) {
-	global $wpdb;
-
 	// Format data
 	$user = preg_replace( '/\s+/', '', sanitize_user( $user, true ) );
 	$user_email = sanitize_email( $user_email );
@@ -722,6 +706,7 @@
 	$key = substr( md5( time() . rand() . $user_email ), 0, 16 );
 	$meta = serialize($meta);
 
+	$wpdb = WP::get( 'wpdb' );
 	$wpdb->insert( $wpdb->signups, array(
 		'domain' => '',
 		'path' => '',
@@ -947,13 +932,11 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $key The activation key provided to the user.
  * @return array|WP_Error An array containing information about the activated user and/or blog
  */
 function wpmu_activate_signup($key) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE activation_key = %s", $key) );
 
@@ -1252,8 +1235,6 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $domain  The domain to be checked.
  * @param string $path    The path to be checked.
  * @param int    $site_id Optional. Relevant only on multi-network installs.
@@ -1291,8 +1272,6 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $domain  The domain of the new site.
  * @param string $path    The path of the new site.
  * @param int    $site_id Unless you're running a multi-network install, be sure to set this value to 1.
@@ -1299,7 +1278,7 @@
  * @return int|false The ID of the new row
  */
 function insert_blog($domain, $path, $site_id) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$path = trailingslashit($path);
 	$site_id = (int) $site_id;
@@ -1325,7 +1304,6 @@
  *
  * @since MU
  *
- * @global wpdb     $wpdb
  * @global WP_Roles $wp_roles
  *
  * @param int    $blog_id    The value returned by insert_blog().
@@ -1332,8 +1310,10 @@
  * @param string $blog_title The title of the new site.
  */
 function install_blog( $blog_id, $blog_title = '' ) {
-	global $wpdb, $wp_roles, $current_site;
+	global $wp_roles, $current_site;
 
+	$wpdb = WP::get( 'wpdb' );
+
 	// Cast for security
 	$blog_id = (int) $blog_id;
 
@@ -1393,13 +1373,11 @@
  * @deprecated MU
  * @deprecated Use wp_install_defaults()
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $blog_id Ignored in this function.
  * @param int $user_id
  */
 function install_blog_defaults($blog_id, $user_id) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
 
@@ -1618,13 +1596,11 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $user_id
  * @return array Contains the blog_id, post_id, post_date_gmt, and post_gmt_ts
  */
 function get_most_recent_post_of_user( $user_id ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$user_blogs = get_blogs_of_user( (int) $user_id );
 	$most_recent_post = array();
@@ -1765,12 +1741,10 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $deprecated Not used.
  */
 function update_posts_count( $deprecated = '' ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 	update_option( 'post_count', (int) $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_status = 'publish' and post_type = 'post'" ) );
 }
 
@@ -1779,16 +1753,15 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $blog_id
  * @param int $user_id
  */
 function wpmu_log_new_registrations( $blog_id, $user_id ) {
-	global $wpdb;
 	$user = get_userdata( (int) $user_id );
-	if ( $user )
+	if ( $user ) {
+		$wpdb = WP::get( 'wpdb' );
 		$wpdb->insert( $wpdb->registration_log, array('email' => $user->user_email, 'IP' => preg_replace( '/[^0-9., ]/', '', wp_unslash( $_SERVER['REMOTE_ADDR'] ) ), 'blog_id' => $blog_id, 'date_registered' => current_time('mysql')) );
+	}
 }
 
 /**
@@ -1798,7 +1771,6 @@
  *
  * @see term_id_filter
  *
- * @global wpdb $wpdb WordPress database abstraction object.
  * @staticvar int $global_terms_recurse
  *
  * @param int    $term_id    An ID for a term on the current blog.
@@ -1806,7 +1778,6 @@
  * @return int An ID from the global terms table mapped from $term_id.
  */
 function global_terms( $term_id, $deprecated = '' ) {
-	global $wpdb;
 	static $global_terms_recurse = null;
 
 	if ( !global_terms_enabled() )
@@ -1822,6 +1793,7 @@
 	}
 
 	$term_id = intval( $term_id );
+	$wpdb = WP::get( 'wpdb' );
 	$c = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->terms WHERE term_id = %d", $term_id ) );
 
 	$global_id = $wpdb->get_var( $wpdb->prepare( "SELECT cat_ID FROM $wpdb->sitecategories WHERE category_nicename = %s", $c->slug ) );
@@ -2082,8 +2054,6 @@
  *
  * @since MU
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $key
  * @param int    $user_id Optional. Defaults to current user.
  * @param int    $blog_id Optional. Defaults to current blog.
@@ -2090,8 +2060,7 @@
  * @return bool
  */
 function is_user_option_local( $key, $user_id = 0, $blog_id = 0 ) {
-	global $wpdb;
-
+	$wpdb = WP::get( 'wpdb' );
 	$current_user = wp_get_current_user();
 	if ( $blog_id == 0 ) {
 		$blog_id = $wpdb->blogid;
@@ -2257,11 +2226,9 @@
  * Update the network-wide site count.
  *
  * @since 3.7.0
- *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function wp_update_network_site_counts() {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$count = get_sites( array(
 		'network_id' => $wpdb->siteid,
@@ -2278,11 +2245,9 @@
  * Update the network-wide user count.
  *
  * @since 3.7.0
- *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function wp_update_network_user_counts() {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$count = $wpdb->get_var( "SELECT COUNT(ID) as c FROM $wpdb->users WHERE spam = '0' AND deleted = '0'" );
 	update_site_option( 'user_count', $count );
Index: src/wp-includes/ms-load.php
===================================================================
--- src/wp-includes/ms-load.php	(revision 38271)
+++ src/wp-includes/ms-load.php	(working copy)
@@ -157,8 +157,6 @@
  *
  * @since 3.9.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string   $domain   Domain to check.
  * @param string   $path     Path to check.
  * @param int|null $segments Path segments to use. Defaults to null, or the full path.
@@ -277,7 +275,6 @@
  * @since 4.6.0
  * @access private
  *
- * @global wpdb       $wpdb         WordPress database abstraction object.
  * @global WP_Network $current_site The current network.
  * @global WP_Site    $current_blog The current site.
  *
@@ -290,8 +287,10 @@
  *                     Redirect URL if parts exist, but the request as a whole can not be fulfilled.
  */
 function ms_load_current_site_and_network( $domain, $path, $subdomain = false ) {
-	global $wpdb, $current_site, $current_blog;
+	global $current_site, $current_blog;
 
+	$wpdb = WP::get( 'wpdb' );
+
 	// If the network is defined in wp-config.php, we can simply use that.
 	if ( defined( 'DOMAIN_CURRENT_SITE' ) && defined( 'PATH_CURRENT_SITE' ) ) {
 		$current_site = new stdClass;
@@ -454,14 +453,10 @@
  * @since 3.0.0
  * @since 4.4.0 The `$domain` and `$path` parameters were added.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $domain The requested domain for the error to reference.
  * @param string $path   The requested path for the error to reference.
  */
 function ms_not_installed( $domain, $path ) {
-	global $wpdb;
-
 	if ( ! is_admin() ) {
 		dead_db();
 	}
@@ -473,6 +468,8 @@
 	$msg  = '<h1>' . $title . '</h1>';
 	$msg .= '<p>' . __( 'If your site does not display, please contact the owner of this network.' ) . '';
 	$msg .= ' ' . __( 'If you are the owner of this network please check that MySQL is running properly and all tables are error free.' ) . '</p>';
+
+	$wpdb = WP::get( 'wpdb' );
 	$query = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $wpdb->site ) );
 	if ( ! $wpdb->get_var( $query ) ) {
 		$msg .= '<p>' . sprintf(
Index: src/wp-includes/ms-settings.php
===================================================================
--- src/wp-includes/ms-settings.php	(revision 38271)
+++ src/wp-includes/ms-settings.php	(working copy)
@@ -85,6 +85,8 @@
 	wp_load_core_site_options( $site_id );
 }
 
+$wpdb = WP::get( 'wpdb' );
+
 $wpdb->set_prefix( $table_prefix, false ); // $table_prefix can be set in sunrise.php
 $wpdb->set_blog_id( $current_blog->blog_id, $current_blog->site_id );
 $table_prefix = $wpdb->get_blog_prefix();
Index: src/wp-includes/option.php
===================================================================
--- src/wp-includes/option.php	(revision 38271)
+++ src/wp-includes/option.php	(working copy)
@@ -21,15 +21,11 @@
  *
  * @since 1.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $option  Name of option to retrieve. Expected to not be SQL-escaped.
  * @param mixed  $default Optional. Default value to return if the option does not exist.
  * @return mixed Value set for the option.
  */
 function get_option( $option, $default = false ) {
-	global $wpdb;
-
 	$option = trim( $option );
 	if ( empty( $option ) )
 		return false;
@@ -83,6 +79,7 @@
 			$value = wp_cache_get( $option, 'options' );
 
 			if ( false === $value ) {
+				$wpdb = WP::get( 'wpdb' );
 				$row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 
 				// Has to be get_row instead of get_var because of funkiness with 0, false, null values
@@ -102,6 +99,7 @@
 			}
 		}
 	} else {
+		$wpdb = WP::get( 'wpdb' );
 		$suppress = $wpdb->suppress_errors();
 		$row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 		$wpdb->suppress_errors( $suppress );
@@ -167,13 +165,9 @@
  *
  * @since 2.2.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @return array List of all options.
  */
 function wp_load_alloptions() {
-	global $wpdb;
-
 	if ( ! wp_installing() || ! is_multisite() )
 		$alloptions = wp_cache_get( 'alloptions', 'options' );
 	else
@@ -180,6 +174,7 @@
 		$alloptions = false;
 
 	if ( !$alloptions ) {
+		$wpdb = WP::get( 'wpdb' );
 		$suppress = $wpdb->suppress_errors();
 		if ( !$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" ) )
 			$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
@@ -200,16 +195,13 @@
  *
  * @since 3.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $site_id Optional site ID for which to query the options. Defaults to the current site.
  */
 function wp_load_core_site_options( $site_id = null ) {
-	global $wpdb;
-
 	if ( ! is_multisite() || wp_using_ext_object_cache() || wp_installing() )
 		return;
 
+	$wpdb = WP::get( 'wpdb' );
 	if ( empty($site_id) )
 		$site_id = $wpdb->siteid;
 
@@ -240,8 +232,6 @@
  * @since 1.0.0
  * @since 4.2.0 The `$autoload` parameter was added.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string      $option   Option name. Expected to not be SQL-escaped.
  * @param mixed       $value    Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
  * @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. For existing options,
@@ -251,8 +241,6 @@
  * @return bool False if value was not updated and true if value was updated.
  */
 function update_option( $option, $value, $autoload = null ) {
-	global $wpdb;
-
 	$option = trim($option);
 	if ( empty($option) )
 		return false;
@@ -325,6 +313,7 @@
 		$update_args['autoload'] = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
 	if ( ! $result )
 		return false;
@@ -386,8 +375,6 @@
  *
  * @since 1.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string         $option      Name of option to add. Expected to not be SQL-escaped.
  * @param mixed          $value       Optional. Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
  * @param string         $deprecated  Optional. Description. Not used anymore.
@@ -396,8 +383,6 @@
  * @return bool False if option was not added and true if option was added.
  */
 function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) {
-	global $wpdb;
-
 	if ( !empty( $deprecated ) )
 		_deprecated_argument( __FUNCTION__, '2.3.0' );
 
@@ -432,6 +417,7 @@
 	 */
 	do_action( 'add_option', $option, $value );
 
+	$wpdb = WP::get( 'wpdb' );
 	$result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $serialized_value, $autoload ) );
 	if ( ! $result )
 		return false;
@@ -483,14 +469,10 @@
  *
  * @since 1.2.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $option Name of option to remove. Expected to not be SQL-escaped.
  * @return bool True, if option is successfully deleted. False on failure.
  */
 function delete_option( $option ) {
-	global $wpdb;
-
 	$option = trim( $option );
 	if ( empty( $option ) )
 		return false;
@@ -497,6 +479,7 @@
 
 	wp_protect_special_option( $option );
 
+	$wpdb = WP::get( 'wpdb' );
 	// Get the ID, if no ID then return
 	$row = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option ) );
 	if ( is_null( $row ) )
@@ -1069,7 +1052,6 @@
  *
  * @see get_option()
  *
- * @global wpdb   $wpdb
  * @global object $current_site
  *
  * @param int      $network_id ID of the network. Can be null to default to the current network ID.
@@ -1078,7 +1060,7 @@
  * @return mixed Value set for the option.
  */
 function get_network_option( $network_id, $option, $default = false ) {
-	global $wpdb, $current_site;
+	global $current_site;
 
 	if ( $network_id && ! is_numeric( $network_id ) ) {
 		return false;
@@ -1142,6 +1124,7 @@
 		$value = wp_cache_get( $cache_key, 'site-options' );
 
 		if ( ! isset( $value ) || false === $value ) {
+			$wpdb = WP::get( 'wpdb' );
 			$row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
 
 			// Has to be get_row instead of get_var because of funkiness with 0, false, null values
@@ -1186,7 +1169,6 @@
  *
  * @see add_option()
  *
- * @global wpdb   $wpdb
  * @global object $current_site
  *
  * @param int    $network_id ID of the network. Can be null to default to the current network ID.
@@ -1195,7 +1177,7 @@
  * @return bool False if option was not added and true if option was added.
  */
 function add_network_option( $network_id, $option, $value ) {
-	global $wpdb, $current_site;
+	global $current_site;
 
 	if ( $network_id && ! is_numeric( $network_id ) ) {
 		return false;
@@ -1242,6 +1224,7 @@
 		$value = sanitize_option( $option, $value );
 
 		$serialized_value = maybe_serialize( $value );
+		$wpdb = WP::get( 'wpdb' );
 		$result = $wpdb->insert( $wpdb->sitemeta, array( 'site_id'    => $network_id, 'meta_key'   => $option, 'meta_value' => $serialized_value ) );
 
 		if ( ! $result ) {
@@ -1296,7 +1279,6 @@
  *
  * @see delete_option()
  *
- * @global wpdb   $wpdb
  * @global object $current_site
  *
  * @param int    $network_id ID of the network. Can be null to default to the current network ID.
@@ -1304,7 +1286,7 @@
  * @return bool True, if succeed. False, if failure.
  */
 function delete_network_option( $network_id, $option ) {
-	global $wpdb, $current_site;
+	global $current_site;
 
 	if ( $network_id && ! is_numeric( $network_id ) ) {
 		return false;
@@ -1332,6 +1314,7 @@
 	if ( ! is_multisite() ) {
 		$result = delete_option( $option );
 	} else {
+		$wpdb = WP::get( 'wpdb' );
 		$row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
 		if ( is_null( $row ) || ! $row->meta_id ) {
 			return false;
@@ -1378,7 +1361,6 @@
  *
  * @see update_option()
  *
- * @global wpdb   $wpdb
  * @global object $current_site
  *
  * @param int      $network_id ID of the network. Can be null to default to the current network ID.
@@ -1387,7 +1369,7 @@
  * @return bool False if value was not updated and true if value was updated.
  */
 function update_network_option( $network_id, $option, $value ) {
-	global $wpdb, $current_site;
+	global $current_site;
 
 	if ( $network_id && ! is_numeric( $network_id ) ) {
 		return false;
@@ -1440,6 +1422,7 @@
 		$value = sanitize_option( $option, $value );
 
 		$serialized_value = maybe_serialize( $value );
+		$wpdb = WP::get( 'wpdb' );
 		$result = $wpdb->update( $wpdb->sitemeta, array( 'meta_value' => $serialized_value ), array( 'site_id' => $network_id, 'meta_key' => $option ) );
 
 		if ( $result ) {
Index: src/wp-includes/pluggable.php
===================================================================
--- src/wp-includes/pluggable.php	(revision 38271)
+++ src/wp-includes/pluggable.php	(working copy)
@@ -114,13 +114,9 @@
  *
  * @since 3.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array $user_ids User ID numbers list
  */
 function cache_users( $user_ids ) {
-	global $wpdb;
-
 	$clean = _get_non_cached_ids( $user_ids, 'users' );
 
 	if ( empty( $clean ) )
@@ -128,6 +124,7 @@
 
 	$list = implode( ',', $clean );
 
+	$wpdb = WP::get( 'wpdb' );
 	$users = $wpdb->get_results( "SELECT * FROM $wpdb->users WHERE ID IN ($list)" );
 
 	$ids = array();
@@ -1528,8 +1525,6 @@
  *
  * @since 1.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * Uses the {@see 'notify_moderator'} filter to determine whether the site moderator
  * should be notified, overriding the site setting.
  *
@@ -1537,8 +1532,6 @@
  * @return true Always returns true.
  */
 function wp_notify_moderator($comment_id) {
-	global $wpdb;
-
 	$maybe_notify = get_option( 'moderation_notify' );
 
 	/**
@@ -1566,6 +1559,7 @@
 	}
 
 	$comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
+	$wpdb = WP::get( 'wpdb' );
 	$comments_waiting = $wpdb->get_var("SELECT count(comment_ID) FROM $wpdb->comments WHERE comment_approved = '0'");
 
 	// The blogname option is escaped with esc_html on the way into the database in sanitize_option
@@ -1698,7 +1692,6 @@
  * @since 4.3.1 The `$plaintext_pass` parameter was deprecated. `$notify` added as a third parameter.
  * @since 4.6.0 The `$notify` parameter accepts 'user' for sending notification only to the user created.
  *
- * @global wpdb         $wpdb      WordPress database object for queries.
  * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
  *
  * @param int    $user_id    User ID.
@@ -1711,7 +1704,7 @@
 		_deprecated_argument( __FUNCTION__, '4.3.1' );
 	}
 
-	global $wpdb, $wp_hasher;
+	global $wp_hasher;
 	$user = get_userdata( $user_id );
 
 	// The blogname option is escaped with esc_html on the way into the database in sanitize_option
@@ -1743,6 +1736,7 @@
 		$wp_hasher = new PasswordHash( 8, true );
 	}
 	$hashed = time() . ':' . $wp_hasher->HashPassword( $key );
+	$wpdb = WP::get( 'wpdb' );
 	$wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
 
 	$message = sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
@@ -2213,13 +2207,11 @@
  *
  * @since 2.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $password The plaintext new user password
  * @param int    $user_id  User ID
  */
 function wp_set_password( $password, $user_id ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$hash = wp_hash_password( $password );
 	$wpdb->update($wpdb->users, array('user_pass' => $hash, 'user_activation_key' => ''), array('ID' => $user_id) );
Index: src/wp-includes/post.php
===================================================================
--- src/wp-includes/post.php	(revision 38271)
+++ src/wp-includes/post.php	(working copy)
@@ -1498,8 +1498,6 @@
  *
  * @since 2.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int    $post_id   Optional. Post ID to change post type. Default 0.
  * @param string $post_type Optional. Post type. Accepts 'post' or 'page' to
  *                          name a few. Default 'post'.
@@ -1506,7 +1504,7 @@
  * @return int|false Amount of rows changed. Should be 1 for success and 0 for failure.
  */
 function set_post_type( $post_id = 0, $post_type = 'post' ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$post_type = sanitize_post_field('post_type', $post_type, $post_id, 'db');
 	$return = $wpdb->update( $wpdb->posts, array('post_type' => $post_type), array('ID' => $post_id) );
@@ -2085,15 +2083,11 @@
  *
  * @since 2.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $type Optional. Post type to retrieve count. Default 'post'.
  * @param string $perm Optional. 'readable' or empty. Default empty.
  * @return object Number of posts for each status.
  */
 function wp_count_posts( $type = 'post', $perm = '' ) {
-	global $wpdb;
-
 	if ( ! post_type_exists( $type ) )
 		return new stdClass;
 
@@ -2105,6 +2099,7 @@
 		return apply_filters( 'wp_count_posts', $counts, $type, $perm );
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
 	if ( 'readable' == $perm && is_user_logged_in() ) {
 		$post_type_object = get_post_type_object($type);
@@ -2150,14 +2145,12 @@
  *
  * @since 2.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string|array $mime_type Optional. Array or comma-separated list of
  *                                MIME patterns. Default empty.
  * @return object An object containing the attachment counts by mime type.
  */
 function wp_count_attachments( $mime_type = '' ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$and = wp_post_mime_type_where( $mime_type );
 	$count = $wpdb->get_results( "SELECT post_mime_type, COUNT( * ) AS num_posts FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' $and GROUP BY post_mime_type", ARRAY_A );
@@ -2319,7 +2312,6 @@
  *
  * @since 1.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
  * @see wp_delete_attachment()
  * @see wp_trash_post()
  *
@@ -2329,7 +2321,7 @@
  * @return array|false|WP_Post False on failure.
  */
 function wp_delete_post( $postid = 0, $force_delete = false ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );;
 
 	if ( !$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $postid)) )
 		return $post;
@@ -2582,14 +2574,10 @@
  *
  * @since 2.9.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post.
  * @return mixed|void False on failure.
  */
 function wp_trash_post_comments( $post = null ) {
-	global $wpdb;
-
 	$post = get_post($post);
 	if ( empty($post) )
 		return;
@@ -2605,6 +2593,7 @@
 	 */
 	do_action( 'trash_post_comments', $post_id );
 
+	$wpdb = WP::get( 'wpdb' );
 	$comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_ID, comment_approved FROM $wpdb->comments WHERE comment_post_ID = %d", $post_id) );
 	if ( empty($comments) )
 		return;
@@ -2638,14 +2627,10 @@
  *
  * @since 2.9.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post.
  * @return true|void
  */
 function wp_untrash_post_comments( $post = null ) {
-	global $wpdb;
-
 	$post = get_post($post);
 	if ( empty($post) )
 		return;
@@ -2671,6 +2656,7 @@
 	foreach ( $statuses as $comment_id => $comment_status )
 		$group_by_status[$comment_status][] = $comment_id;
 
+	$wpdb = WP::get( 'wpdb' );
 	foreach ( $group_by_status as $status => $comments ) {
 		// Sanity check. This shouldn't happen.
 		if ( 'post-trashed' == $status ) {
@@ -2824,7 +2810,6 @@
  * @since 4.4.0 A 'meta_input' array can now be passed to `$postarr` to add post meta data.
  *
  * @see sanitize_post()
- * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param array $postarr {
  *     An array of elements that make up a post to update or insert.
@@ -2870,8 +2855,6 @@
  * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
  */
 function wp_insert_post( $postarr, $wp_error = false ) {
-	global $wpdb;
-
 	$user_id = get_current_user_id();
 
 	$defaults = array(
@@ -3154,6 +3137,7 @@
 
 	$emoji_fields = array( 'post_title', 'post_content', 'post_excerpt' );
 
+	$wpdb = WP::get( 'wpdb' );
 	foreach ( $emoji_fields as $emoji_field ) {
 		if ( isset( $data[ $emoji_field ] ) ) {
 			$charset = $wpdb->get_col_charset( $wpdb->posts, $emoji_field );
@@ -3487,13 +3471,9 @@
  *
  * @since 2.1.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|WP_Post $post Post ID or post object.
  */
 function wp_publish_post( $post ) {
-	global $wpdb;
-
 	if ( ! $post = get_post( $post ) )
 		return;
 
@@ -3500,6 +3480,7 @@
 	if ( 'publish' == $post->post_status )
 		return;
 
+	$wpdb = WP::get( 'wpdb' );
 	$wpdb->update( $wpdb->posts, array( 'post_status' => 'publish' ), array( 'ID' => $post->ID ) );
 
 	clean_post_cache( $post->ID );
@@ -3558,7 +3539,6 @@
  *
  * @since 2.8.0
  *
- * @global wpdb       $wpdb WordPress database abstraction object.
  * @global WP_Rewrite $wp_rewrite
  *
  * @param string $slug        The desired slug (post_name).
@@ -3572,7 +3552,7 @@
 	if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) || ( 'inherit' == $post_status && 'revision' == $post_type ) )
 		return $slug;
 
-	global $wpdb, $wp_rewrite;
+	global $wp_rewrite;
 
 	$original_slug = $slug;
 
@@ -3580,6 +3560,7 @@
 	if ( ! is_array( $feeds ) )
 		$feeds = array();
 
+	$wpdb = WP::get( 'wpdb' );
 	if ( 'attachment' == $post_type ) {
 		// Attachment slugs must be unique across all types.
 		$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
@@ -3906,14 +3887,13 @@
  *
  * @since 1.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int    $post_id Post ID.
  * @param string $uri     Ping URI.
  * @return int|false How many rows were updated.
  */
 function add_ping( $post_id, $uri ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
+
 	$pung = $wpdb->get_var( $wpdb->prepare( "SELECT pinged FROM $wpdb->posts WHERE ID = %d", $post_id ));
 	$pung = trim($pung);
 	$pung = preg_split('/\s/', $pung);
@@ -3973,13 +3953,12 @@
  *
  * @since 1.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $post_id Post ID.
  * @return array
  */
 function get_pung( $post_id ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
+
 	$pung = $wpdb->get_var( $wpdb->prepare( "SELECT pinged FROM $wpdb->posts WHERE ID = %d", $post_id ));
 	$pung = trim($pung);
 	$pung = preg_split('/\s/', $pung);
@@ -3999,13 +3978,12 @@
  *
  * @since 1.5.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int $post_id Post ID
  * @return array
  */
 function get_to_ping( $post_id ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
+
 	$to_ping = $wpdb->get_var( $wpdb->prepare( "SELECT to_ping FROM $wpdb->posts WHERE ID = %d", $post_id ));
 	$to_ping = sanitize_trackback_urls( $to_ping );
 	$to_ping = preg_split('/\s/', $to_ping, -1, PREG_SPLIT_NO_EMPTY);
@@ -4057,15 +4035,12 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @return array List of page IDs.
  */
 function get_all_page_ids() {
-	global $wpdb;
-
 	$page_ids = wp_cache_get('all_page_ids', 'posts');
 	if ( ! is_array( $page_ids ) ) {
+		$wpdb = WP::get( 'wpdb' );
 		$page_ids = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_type = 'page'");
 		wp_cache_add('all_page_ids', $page_ids, 'posts');
 	}
@@ -4097,8 +4072,6 @@
  *
  * @since 2.1.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string       $page_path Page path.
  * @param string       $output    Optional. Output type. Accepts OBJECT, ARRAY_N, or ARRAY_A.
  *                                Default OBJECT.
@@ -4106,8 +4079,6 @@
  * @return WP_Post|array|void WP_Post on success.
  */
 function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {
-	global $wpdb;
-
 	$last_changed = wp_cache_get( 'last_changed', 'posts' );
 	if ( false === $last_changed ) {
 		$last_changed = microtime();
@@ -4143,6 +4114,8 @@
 
 	$post_types = esc_sql( $post_types );
 	$post_type_in_string = "'" . implode( "','", $post_types ) . "'";
+
+	$wpdb = WP::get( 'wpdb' );
 	$sql = "
 		SELECT ID, post_name, post_parent, post_type
 		FROM $wpdb->posts
@@ -4193,8 +4166,6 @@
  *
  * @since 2.1.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string       $page_title Page title
  * @param string       $output     Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A.
  *                                 Default OBJECT.
@@ -4202,8 +4173,7 @@
  * @return WP_Post|array|void WP_Post on success or null on failure
  */
 function get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' ) {
-	global $wpdb;
-
+	$wpdb = WP::get( 'wpdb' );
 	if ( is_array( $post_type ) ) {
 		$post_type = esc_sql( $post_type );
 		$post_type_in_string = "'" . implode( "','", $post_type ) . "'";
@@ -4362,8 +4332,6 @@
 /**
  * Retrieve a list of pages.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @since 1.5.0
  *
  * @param array|string $args {
@@ -4402,8 +4370,6 @@
  * @return array|false List of pages matching defaults or `$args`.
  */
 function get_pages( $args = array() ) {
-	global $wpdb;
-
 	$defaults = array(
 		'child_of' => 0, 'sort_order' => 'ASC',
 		'sort_column' => 'post_title', 'hierarchical' => 1,
@@ -4483,6 +4449,8 @@
 		}
 	}
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$author_query = '';
 	if ( ! empty( $r['authors'] ) ) {
 		$post_authors = preg_split( '/[\s,]+/', $r['authors'] );
@@ -4731,8 +4699,6 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int  $post_id      Attachment ID.
  * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
  *                           Default false.
@@ -4739,7 +4705,7 @@
  * @return mixed False on failure. Post data on success.
  */
 function wp_delete_attachment( $post_id, $force_delete = false ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	if ( !$post = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id) ) )
 		return $post;
@@ -5316,7 +5282,6 @@
  * @since 4.3.0 Introduced the ability to pass an array of post types to `$post_type`.
  *
  * @see get_private_posts_cap_sql()
- * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param array|string   $post_type   Single post type or an array of post types.
  * @param bool           $full        Optional. Returns a full WHERE statement instead of just
@@ -5327,8 +5292,6 @@
  * @return string SQL WHERE code that can be added to a query.
  */
 function get_posts_by_author_sql( $post_type, $full = true, $post_author = null, $public_only = false ) {
-	global $wpdb;
-
 	if ( is_array( $post_type ) ) {
 		$post_types = $post_type;
 	} else {
@@ -5382,6 +5345,7 @@
 	$sql = '( '. implode( ' OR ', $post_type_clauses ) . ' )';
 
 	if ( null !== $post_author ) {
+		$wpdb = WP::get( 'wpdb' );
 		$sql .= $wpdb->prepare( ' AND post_author = %d', $post_author );
 	}
 
@@ -5482,8 +5446,6 @@
  * @since 4.4.0 The `$post_type` argument was added.
  * @access private
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $timezone  The timezone for the timestamp. See get_lastpostdate().
  *                          for information on accepted values.
  * @param string $field     Post field to check. Accepts 'date' or 'modified'.
@@ -5491,8 +5453,6 @@
  * @return string|false The timestamp.
  */
 function _get_last_post_time( $timezone, $field, $post_type = 'any' ) {
-	global $wpdb;
-
 	if ( ! in_array( $field, array( 'date', 'modified' ) ) ) {
 		return false;
 	}
@@ -5506,6 +5466,8 @@
 
 	$date = wp_cache_get( $key, 'timeinfo' );
 
+	$wpdb = WP::get( 'wpdb' );
+
 	if ( ! $date ) {
 		if ( 'any' === $post_type ) {
 			$post_types = get_post_types( array( 'public' => true ) );
@@ -5722,20 +5684,19 @@
  * @access private
  *
  * @see wp_clear_scheduled_hook()
- * @global wpdb $wpdb WordPress database abstraction object.
  *
+ *
  * @param string  $new_status New post status.
  * @param string  $old_status Previous post status.
  * @param WP_Post $post       Post object.
  */
 function _transition_post_status( $new_status, $old_status, $post ) {
-	global $wpdb;
-
 	if ( $old_status != 'publish' && $new_status == 'publish' ) {
 		// Reset GUID if transitioning to publish and it is empty.
-		if ( '' == get_the_guid($post->ID) )
+		if ( '' == get_the_guid($post->ID) ) {
+			$wpdb = WP::get( 'wpdb' );
 			$wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post->ID ) ), array( 'ID' => $post->ID ) );
-
+		}
 		/**
 		 * Fires when a post's status is transitioned from private to published.
 		 *
@@ -5913,11 +5874,9 @@
  * Delete auto-drafts for new posts that are > 7 days old.
  *
  * @since 3.4.0
- *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function wp_delete_auto_drafts() {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	// Cleanup old auto-drafts more than 7 days old.
 	$old_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_status = 'auto-draft' AND DATE_SUB( NOW(), INTERVAL 7 DAY ) > post_date" );
@@ -5993,17 +5952,14 @@
  *
  * @see update_post_caches()
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array $ids               ID list.
  * @param bool  $update_term_cache Optional. Whether to update the term cache. Default true.
  * @param bool  $update_meta_cache Optional. Whether to update the meta cache. Default true.
  */
 function _prime_post_caches( $ids, $update_term_cache = true, $update_meta_cache = true ) {
-	global $wpdb;
-
 	$non_cached_ids = _get_non_cached_ids( $ids, 'posts' );
 	if ( !empty( $non_cached_ids ) ) {
+		$wpdb = WP::get( 'wpdb' );
 		$fresh_posts = $wpdb->get_results( sprintf( "SELECT $wpdb->posts.* FROM $wpdb->posts WHERE ID IN (%s)", join( ",", $non_cached_ids ) ) );
 
 		update_post_caches( $fresh_posts, 'any', $update_term_cache, $update_meta_cache );
@@ -6055,8 +6011,6 @@
  * @return string New slug for the post.
  */
 function wp_add_trashed_suffix_to_post_name_for_post( $post ) {
-	global $wpdb;
-
 	$post = get_post( $post );
 
 	if ( '__trashed' === substr( $post->post_name, -9 ) ) {
@@ -6064,6 +6018,7 @@
 	}
 	add_post_meta( $post->ID, '_wp_desired_post_slug', $post->post_name );
 	$post_name = _truncate_post_slug( $post->post_name, 191 ) . '__trashed';
+	$wpdb = WP::get( 'wpdb' );
 	$wpdb->update( $wpdb->posts, array( 'post_name' => $post_name ), array( 'ID' => $post->ID ) );
 	clean_post_cache( $post->ID );
 	return $post_name;
Index: src/wp-includes/query.php
===================================================================
--- src/wp-includes/query.php	(revision 38271)
+++ src/wp-includes/query.php	(working copy)
@@ -1320,6 +1320,8 @@
 
 	private $compat_methods = array( 'init_query_flags', 'parse_tax_query' );
 
+	protected $dbh;
+
 	/**
 	 * Resets query flags to false.
 	 *
@@ -2114,14 +2116,10 @@
 	 *
 	 * @since 3.7.0
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param array $q Query variables.
 	 * @return string WHERE clause.
 	 */
 	protected function parse_search( &$q ) {
-		global $wpdb;
-
 		$search = '';
 
 		// added slashes screw with quote grouping when done early, so done later
@@ -2161,12 +2159,12 @@
 			}
 
 			if ( $n && $include ) {
-				$like = '%' . $wpdb->esc_like( $term ) . '%';
-				$q['search_orderby_title'][] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $like );
+				$like = '%' . $this->dbh->esc_like( $term ) . '%';
+				$q['search_orderby_title'][] = $this->dbh->prepare( "{$this->dbh->posts}.post_title LIKE %s", $like );
 			}
 
-			$like = $n . $wpdb->esc_like( $term ) . $n;
-			$search .= $wpdb->prepare( "{$searchand}(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_excerpt $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like, $like );
+			$like = $n . $this->dbh->esc_like( $term ) . $n;
+			$search .= $this->dbh->prepare( "{$searchand}(({$this->dbh->posts}.post_title $like_op %s) $andor_op ({$this->dbh->posts}.post_excerpt $like_op %s) $andor_op ({$this->dbh->posts}.post_content $like_op %s))", $like, $like, $like );
 			$searchand = ' AND ';
 		}
 
@@ -2173,7 +2171,7 @@
 		if ( ! empty( $search ) ) {
 			$search = " AND ({$search}) ";
 			if ( ! is_user_logged_in() )
-				$search .= " AND ($wpdb->posts.post_password = '') ";
+				$search .= " AND ({$this->dbh->posts}.post_password = '') ";
 		}
 
 		return $search;
@@ -2256,14 +2254,10 @@
 	/**
 	 * Generate SQL for the ORDER BY condition based on passed search terms.
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param array $q Query variables.
 	 * @return string ORDER BY clause.
 	 */
 	protected function parse_search_order( &$q ) {
-		global $wpdb;
-
 		if ( $q['search_terms_count'] > 1 ) {
 			$num_terms = count( $q['search_orderby_title'] );
 
@@ -2270,7 +2264,7 @@
 			// If the search terms contain negative queries, don't bother ordering by sentence matches.
 			$like = '';
 			if ( ! preg_match( '/(?:\s|^)\-/', $q['s'] ) ) {
-				$like = '%' . $wpdb->esc_like( $q['s'] ) . '%';
+				$like = '%' . $this->dbh->esc_like( $q['s'] ) . '%';
 			}
 
 			$search_orderby = '';
@@ -2277,7 +2271,7 @@
 
 			// sentence match in 'post_title'
 			if ( $like ) {
-				$search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_title LIKE %s THEN 1 ", $like );
+				$search_orderby .= $this->dbh->prepare( "WHEN {$this->dbh->posts}.post_title LIKE %s THEN 1 ", $like );
 			}
 
 			// sanity limit, sort as sentence when more than 6 terms
@@ -2292,8 +2286,8 @@
 
 			// Sentence match in 'post_content' and 'post_excerpt'.
 			if ( $like ) {
-				$search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_excerpt LIKE %s THEN 4 ", $like );
-				$search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_content LIKE %s THEN 5 ", $like );
+				$search_orderby .= $this->dbh->prepare( "WHEN {$this->dbh->posts}.post_excerpt LIKE %s THEN 4 ", $like );
+				$search_orderby .= $this->dbh->prepare( "WHEN {$this->dbh->posts}.post_content LIKE %s THEN 5 ", $like );
 			}
 
 			if ( $search_orderby ) {
@@ -2314,14 +2308,10 @@
 	 * @since 4.0.0
 	 * @access protected
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param string $orderby Alias for the field to order by.
 	 * @return string|false Table-prefixed value to used in the ORDER clause. False otherwise.
 	 */
 	protected function parse_orderby( $orderby ) {
-		global $wpdb;
-
 		// Used to filter values.
 		$allowed_keys = array(
 			'post_name', 'post_author', 'post_date', 'post_title', 'post_modified',
@@ -2368,7 +2358,7 @@
 			case 'ID':
 			case 'menu_order':
 			case 'comment_count':
-				$orderby_clause = "$wpdb->posts.{$orderby}";
+				$orderby_clause = "{$this->dbh->posts}.{$orderby}";
 				break;
 			case 'rand':
 				$orderby_clause = 'RAND()';
@@ -2393,7 +2383,7 @@
 					$orderby_clause = $orderby;
 				} else {
 					// Default: order by post field.
-					$orderby_clause = "$wpdb->posts.post_" . sanitize_key( $orderby );
+					$orderby_clause = "{$this->dbh->posts}.post_" . sanitize_key( $orderby );
 				}
 
 				break;
@@ -2480,13 +2470,9 @@
 	 * @since 1.5.0
 	 * @access public
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @return array List of posts.
 	 */
 	public function get_posts() {
-		global $wpdb;
-
 		$this->parse_query();
 
 		/**
@@ -2622,31 +2608,31 @@
 
 		switch ( $q['fields'] ) {
 			case 'ids':
-				$fields = "$wpdb->posts.ID";
+				$fields = "{$this->dbh->posts}.ID";
 				break;
 			case 'id=>parent':
-				$fields = "$wpdb->posts.ID, $wpdb->posts.post_parent";
+				$fields = "{$this->dbh->posts}.ID, {$this->dbh->posts}.post_parent";
 				break;
 			default:
-				$fields = "$wpdb->posts.*";
+				$fields = "{$this->dbh->posts}.*";
 		}
 
 		if ( '' !== $q['menu_order'] )
-			$where .= " AND $wpdb->posts.menu_order = " . $q['menu_order'];
+			$where .= " AND {$this->dbh->posts}.menu_order = " . $q['menu_order'];
 
 		// The "m" parameter is meant for months but accepts datetimes of varying specificity
 		if ( $q['m'] ) {
-			$where .= " AND YEAR($wpdb->posts.post_date)=" . substr($q['m'], 0, 4);
+			$where .= " AND YEAR({$this->dbh->posts}.post_date)=" . substr($q['m'], 0, 4);
 			if ( strlen($q['m']) > 5 )
-				$where .= " AND MONTH($wpdb->posts.post_date)=" . substr($q['m'], 4, 2);
+				$where .= " AND MONTH({$this->dbh->posts}.post_date)=" . substr($q['m'], 4, 2);
 			if ( strlen($q['m']) > 7 )
-				$where .= " AND DAYOFMONTH($wpdb->posts.post_date)=" . substr($q['m'], 6, 2);
+				$where .= " AND DAYOFMONTH({$this->dbh->posts}.post_date)=" . substr($q['m'], 6, 2);
 			if ( strlen($q['m']) > 9 )
-				$where .= " AND HOUR($wpdb->posts.post_date)=" . substr($q['m'], 8, 2);
+				$where .= " AND HOUR({$this->dbh->posts}.post_date)=" . substr($q['m'], 8, 2);
 			if ( strlen($q['m']) > 11 )
-				$where .= " AND MINUTE($wpdb->posts.post_date)=" . substr($q['m'], 10, 2);
+				$where .= " AND MINUTE({$this->dbh->posts}.post_date)=" . substr($q['m'], 10, 2);
 			if ( strlen($q['m']) > 13 )
-				$where .= " AND SECOND($wpdb->posts.post_date)=" . substr($q['m'], 12, 2);
+				$where .= " AND SECOND({$this->dbh->posts}.post_date)=" . substr($q['m'], 12, 2);
 		}
 
 		// Handle the other individual date parameters
@@ -2709,13 +2695,13 @@
 		}
 
 		if ( '' !== $q['title'] ) {
-			$where .= $wpdb->prepare( " AND $wpdb->posts.post_title = %s", stripslashes( $q['title'] ) );
+			$where .= $this->dbh->prepare( " AND {$this->dbh->posts}.post_title = %s", stripslashes( $q['title'] ) );
 		}
 
 		// Parameters related to 'post_name'.
 		if ( '' != $q['name'] ) {
 			$q['name'] = sanitize_title_for_query( $q['name'] );
-			$where .= " AND $wpdb->posts.post_name = '" . $q['name'] . "'";
+			$where .= " AND {$this->dbh->posts}.post_name = '" . $q['name'] . "'";
 		} elseif ( '' != $q['pagename'] ) {
 			if ( isset($this->queried_object_id) ) {
 				$reqpage = $this->queried_object_id;
@@ -2744,7 +2730,7 @@
 			if  ( ('page' != get_option('show_on_front') ) || empty($page_for_posts) || ( $reqpage != $page_for_posts ) ) {
 				$q['pagename'] = sanitize_title_for_query( wp_basename( $q['pagename'] ) );
 				$q['name'] = $q['pagename'];
-				$where .= " AND ($wpdb->posts.ID = '$reqpage')";
+				$where .= " AND ({$this->dbh->posts}.ID = '$reqpage')";
 				$reqpage_obj = get_post( $reqpage );
 				if ( is_object($reqpage_obj) && 'attachment' == $reqpage_obj->post_type ) {
 					$this->is_attachment = true;
@@ -2756,11 +2742,11 @@
 		} elseif ( '' != $q['attachment'] ) {
 			$q['attachment'] = sanitize_title_for_query( wp_basename( $q['attachment'] ) );
 			$q['name'] = $q['attachment'];
-			$where .= " AND $wpdb->posts.post_name = '" . $q['attachment'] . "'";
+			$where .= " AND {$this->dbh->posts}.post_name = '" . $q['attachment'] . "'";
 		} elseif ( is_array( $q['post_name__in'] ) && ! empty( $q['post_name__in'] ) ) {
 			$q['post_name__in'] = array_map( 'sanitize_title_for_query', $q['post_name__in'] );
 			$post_name__in = "'" . implode( "','", $q['post_name__in'] ) . "'";
-			$where .= " AND $wpdb->posts.post_name IN ($post_name__in)";
+			$where .= " AND {$this->dbh->posts}.post_name IN ($post_name__in)";
 		}
 
 		// If an attachment is requested by number, let it supersede any post number.
@@ -2769,29 +2755,29 @@
 
 		// If a post number is specified, load that post
 		if ( $q['p'] ) {
-			$where .= " AND {$wpdb->posts}.ID = " . $q['p'];
+			$where .= " AND {$this->dbh->posts}.ID = " . $q['p'];
 		} elseif ( $q['post__in'] ) {
 			$post__in = implode(',', array_map( 'absint', $q['post__in'] ));
-			$where .= " AND {$wpdb->posts}.ID IN ($post__in)";
+			$where .= " AND {$this->dbh->posts}.ID IN ($post__in)";
 		} elseif ( $q['post__not_in'] ) {
 			$post__not_in = implode(',',  array_map( 'absint', $q['post__not_in'] ));
-			$where .= " AND {$wpdb->posts}.ID NOT IN ($post__not_in)";
+			$where .= " AND {$this->dbh->posts}.ID NOT IN ($post__not_in)";
 		}
 
 		if ( is_numeric( $q['post_parent'] ) ) {
-			$where .= $wpdb->prepare( " AND $wpdb->posts.post_parent = %d ", $q['post_parent'] );
+			$where .= $this->dbh->prepare( " AND {$this->dbh->posts}.post_parent = %d ", $q['post_parent'] );
 		} elseif ( $q['post_parent__in'] ) {
 			$post_parent__in = implode( ',', array_map( 'absint', $q['post_parent__in'] ) );
-			$where .= " AND {$wpdb->posts}.post_parent IN ($post_parent__in)";
+			$where .= " AND {$this->dbh->posts}.post_parent IN ($post_parent__in)";
 		} elseif ( $q['post_parent__not_in'] ) {
 			$post_parent__not_in = implode( ',',  array_map( 'absint', $q['post_parent__not_in'] ) );
-			$where .= " AND {$wpdb->posts}.post_parent NOT IN ($post_parent__not_in)";
+			$where .= " AND {$this->dbh->posts}.post_parent NOT IN ($post_parent__not_in)";
 		}
 
 		if ( $q['page_id'] ) {
 			if  ( ('page' != get_option('show_on_front') ) || ( $q['page_id'] != get_option('page_for_posts') ) ) {
 				$q['p'] = $q['page_id'];
-				$where = " AND {$wpdb->posts}.ID = " . $q['page_id'];
+				$where = " AND {$this->dbh->posts}.ID = " . $q['page_id'];
 			}
 		}
 
@@ -2816,7 +2802,7 @@
 		if ( !$this->is_singular ) {
 			$this->parse_tax_query( $q );
 
-			$clauses = $this->tax_query->get_sql( $wpdb->posts, 'ID' );
+			$clauses = $this->tax_query->get_sql( $this->dbh->posts, 'ID' );
 
 			$join .= $clauses['join'];
 			$where .= $clauses['where'];
@@ -2900,7 +2886,7 @@
 		}
 
 		if ( !empty( $this->tax_query->queries ) || !empty( $this->meta_query->queries ) ) {
-			$groupby = "{$wpdb->posts}.ID";
+			$groupby = "{$this->dbh->posts}.ID";
 		}
 
 		// Author/user stuff
@@ -2917,10 +2903,10 @@
 
 		if ( ! empty( $q['author__not_in'] ) ) {
 			$author__not_in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__not_in'] ) ) );
-			$where .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) ";
+			$where .= " AND {$this->dbh->posts}.post_author NOT IN ($author__not_in) ";
 		} elseif ( ! empty( $q['author__in'] ) ) {
 			$author__in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__in'] ) ) );
-			$where .= " AND {$wpdb->posts}.post_author IN ($author__in) ";
+			$where .= " AND {$this->dbh->posts}.post_author IN ($author__in) ";
 		}
 
 		// Author stuff for nice URLs
@@ -2938,18 +2924,18 @@
 			$q['author'] = get_user_by('slug', $q['author_name']);
 			if ( $q['author'] )
 				$q['author'] = $q['author']->ID;
-			$whichauthor .= " AND ($wpdb->posts.post_author = " . absint($q['author']) . ')';
+			$whichauthor .= " AND ({$this->dbh->posts}.post_author = " . absint($q['author']) . ')';
 		}
 
 		// MIME-Type stuff for attachment browsing
 
 		if ( isset( $q['post_mime_type'] ) && '' != $q['post_mime_type'] )
-			$whichmimetype = wp_post_mime_type_where( $q['post_mime_type'], $wpdb->posts );
+			$whichmimetype = wp_post_mime_type_where( $q['post_mime_type'], $this->dbh->posts );
 
 		$where .= $search . $whichauthor . $whichmimetype;
 
 		if ( ! empty( $this->meta_query->queries ) ) {
-			$clauses = $this->meta_query->get_sql( 'post', $wpdb->posts, 'ID', $this );
+			$clauses = $this->meta_query->get_sql( 'post', $this->dbh->posts, 'ID', $this );
 			$join   .= $clauses['join'];
 			$where  .= $clauses['where'];
 		}
@@ -2970,16 +2956,16 @@
 			if ( isset( $q['orderby'] ) && ( is_array( $q['orderby'] ) || false === $q['orderby'] ) ) {
 				$orderby = '';
 			} else {
-				$orderby = "$wpdb->posts.post_date " . $q['order'];
+				$orderby = "{$this->dbh->posts}.post_date " . $q['order'];
 			}
 		} elseif ( 'none' == $q['orderby'] ) {
 			$orderby = '';
 		} elseif ( $q['orderby'] == 'post__in' && ! empty( $post__in ) ) {
-			$orderby = "FIELD( {$wpdb->posts}.ID, $post__in )";
+			$orderby = "FIELD( {$this->dbh->posts}.ID, $post__in )";
 		} elseif ( $q['orderby'] == 'post_parent__in' && ! empty( $post_parent__in ) ) {
-			$orderby = "FIELD( {$wpdb->posts}.post_parent, $post_parent__in )";
+			$orderby = "FIELD( {$this->dbh->posts}.post_parent, $post_parent__in )";
 		} elseif ( $q['orderby'] == 'post_name__in' && ! empty( $post_name__in ) ) {
-			$orderby = "FIELD( {$wpdb->posts}.post_name, $post_name__in )";
+			$orderby = "FIELD( {$this->dbh->posts}.post_name, $post_name__in )";
 		} else {
 			$orderby_array = array();
 			if ( is_array( $q['orderby'] ) ) {
@@ -3011,7 +2997,7 @@
 				$orderby = implode( ' ' . $q['order'] . ', ', $orderby_array );
 
 				if ( empty( $orderby ) ) {
-					$orderby = "$wpdb->posts.post_date " . $q['order'];
+					$orderby = "{$this->dbh->posts}.post_date " . $q['order'];
 				} elseif ( ! empty( $q['order'] ) ) {
 					$orderby .= " {$q['order']}";
 				}
@@ -3051,20 +3037,20 @@
 		}
 
 		if ( isset( $q['post_password'] ) ) {
-			$where .= $wpdb->prepare( " AND $wpdb->posts.post_password = %s", $q['post_password'] );
+			$where .= $this->dbh->prepare( " AND {$this->dbh->posts}.post_password = %s", $q['post_password'] );
 			if ( empty( $q['perm'] ) ) {
 				$q['perm'] = 'readable';
 			}
 		} elseif ( isset( $q['has_password'] ) ) {
-			$where .= sprintf( " AND $wpdb->posts.post_password %s ''", $q['has_password'] ? '!=' : '=' );
+			$where .= sprintf( " AND {$this->dbh->posts}.post_password %s ''", $q['has_password'] ? '!=' : '=' );
 		}
 
 		if ( ! empty( $q['comment_status'] ) ) {
-			$where .= $wpdb->prepare( " AND $wpdb->posts.comment_status = %s ", $q['comment_status'] );
+			$where .= $this->dbh->prepare( " AND {$this->dbh->posts}.comment_status = %s ", $q['comment_status'] );
 		}
 
 		if ( ! empty( $q['ping_status'] ) )  {
-			$where .= $wpdb->prepare( " AND $wpdb->posts.ping_status = %s ", $q['ping_status'] );
+			$where .= $this->dbh->prepare( " AND {$this->dbh->posts}.ping_status = %s ", $q['ping_status'] );
 		}
 
 		if ( 'any' == $post_type ) {
@@ -3072,20 +3058,20 @@
 			if ( empty( $in_search_post_types ) )
 				$where .= ' AND 1=0 ';
 			else
-				$where .= " AND $wpdb->posts.post_type IN ('" . join("', '", $in_search_post_types ) . "')";
+				$where .= " AND {$this->dbh->posts}.post_type IN ('" . join("', '", $in_search_post_types ) . "')";
 		} elseif ( !empty( $post_type ) && is_array( $post_type ) ) {
-			$where .= " AND $wpdb->posts.post_type IN ('" . join("', '", $post_type) . "')";
+			$where .= " AND {$this->dbh->posts}.post_type IN ('" . join("', '", $post_type) . "')";
 		} elseif ( ! empty( $post_type ) ) {
-			$where .= " AND $wpdb->posts.post_type = '$post_type'";
+			$where .= " AND {$this->dbh->posts}.post_type = '$post_type'";
 			$post_type_object = get_post_type_object ( $post_type );
 		} elseif ( $this->is_attachment ) {
-			$where .= " AND $wpdb->posts.post_type = 'attachment'";
+			$where .= " AND {$this->dbh->posts}.post_type = 'attachment'";
 			$post_type_object = get_post_type_object ( 'attachment' );
 		} elseif ( $this->is_page ) {
-			$where .= " AND $wpdb->posts.post_type = 'page'";
+			$where .= " AND {$this->dbh->posts}.post_type = 'page'";
 			$post_type_object = get_post_type_object ( 'page' );
 		} else {
-			$where .= " AND $wpdb->posts.post_type = 'post'";
+			$where .= " AND {$this->dbh->posts}.post_type = 'post'";
 			$post_type_object = get_post_type_object ( 'post' );
 		}
 
@@ -3114,7 +3100,7 @@
 			if ( in_array( 'any', $q_status ) ) {
 				foreach ( get_post_stati( array( 'exclude_from_search' => true ) ) as $status ) {
 					if ( ! in_array( $status, $q_status ) ) {
-						$e_status[] = "$wpdb->posts.post_status <> '$status'";
+						$e_status[] = "{$this->dbh->posts}.post_status <> '$status'";
 					}
 				}
 			} else {
@@ -3121,9 +3107,9 @@
 				foreach ( get_post_stati() as $status ) {
 					if ( in_array( $status, $q_status ) ) {
 						if ( 'private' == $status )
-							$p_status[] = "$wpdb->posts.post_status = '$status'";
+							$p_status[] = "{$this->dbh->posts}.post_status = '$status'";
 						else
-							$r_status[] = "$wpdb->posts.post_status = '$status'";
+							$r_status[] = "{$this->dbh->posts}.post_status = '$status'";
 					}
 				}
 			}
@@ -3138,20 +3124,20 @@
 			}
 			if ( !empty($r_status) ) {
 				if ( !empty($q['perm'] ) && 'editable' == $q['perm'] && !current_user_can($edit_others_cap) )
-					$statuswheres[] = "($wpdb->posts.post_author = $user_id " . "AND (" . join( ' OR ', $r_status ) . "))";
+					$statuswheres[] = "({$this->dbh->posts}.post_author = $user_id " . "AND (" . join( ' OR ', $r_status ) . "))";
 				else
 					$statuswheres[] = "(" . join( ' OR ', $r_status ) . ")";
 			}
 			if ( !empty($p_status) ) {
 				if ( !empty($q['perm'] ) && 'readable' == $q['perm'] && !current_user_can($read_private_cap) )
-					$statuswheres[] = "($wpdb->posts.post_author = $user_id " . "AND (" . join( ' OR ', $p_status ) . "))";
+					$statuswheres[] = "({$this->dbh->posts}.post_author = $user_id " . "AND (" . join( ' OR ', $p_status ) . "))";
 				else
 					$statuswheres[] = "(" . join( ' OR ', $p_status ) . ")";
 			}
 			if ( $post_status_join ) {
-				$join .= " LEFT JOIN $wpdb->posts AS p2 ON ($wpdb->posts.post_parent = p2.ID) ";
+				$join .= " LEFT JOIN {$this->dbh->posts} AS p2 ON ({$this->dbh->posts}.post_parent = p2.ID) ";
 				foreach ( $statuswheres as $index => $statuswhere )
-					$statuswheres[$index] = "($statuswhere OR ($wpdb->posts.post_status = 'inherit' AND " . str_replace($wpdb->posts, 'p2', $statuswhere) . "))";
+					$statuswheres[$index] = "($statuswhere OR ({$this->dbh->posts}.post_status = 'inherit' AND " . str_replace($this->dbh->posts, 'p2', $statuswhere) . "))";
 			}
 			$where_status = implode( ' OR ', $statuswheres );
 			if ( ! empty( $where_status ) ) {
@@ -3158,7 +3144,7 @@
 				$where .= " AND ($where_status)";
 			}
 		} elseif ( !$this->is_singular ) {
-			$where .= " AND ($wpdb->posts.post_status = 'publish'";
+			$where .= " AND ({$this->dbh->posts}.post_status = 'publish'";
 
 			// Add public states.
 			$public_states = get_post_stati( array('public' => true) );
@@ -3165,7 +3151,7 @@
 			foreach ( (array) $public_states as $state ) {
 				if ( 'publish' == $state ) // Publish is hard-coded above.
 					continue;
-				$where .= " OR $wpdb->posts.post_status = '$state'";
+				$where .= " OR {$this->dbh->posts}.post_status = '$state'";
 			}
 
 			if ( $this->is_admin ) {
@@ -3172,7 +3158,7 @@
 				// Add protected states that should show in the admin all list.
 				$admin_all_states = get_post_stati( array('protected' => true, 'show_in_admin_all_list' => true) );
 				foreach ( (array) $admin_all_states as $state )
-					$where .= " OR $wpdb->posts.post_status = '$state'";
+					$where .= " OR {$this->dbh->posts}.post_status = '$state'";
 			}
 
 			if ( is_user_logged_in() ) {
@@ -3179,7 +3165,7 @@
 				// Add private states that are limited to viewing by the author of a post or someone who has caps to read private states.
 				$private_states = get_post_stati( array('private' => true) );
 				foreach ( (array) $private_states as $state )
-					$where .= current_user_can( $read_private_cap ) ? " OR $wpdb->posts.post_status = '$state'" : " OR $wpdb->posts.post_author = $user_id AND $wpdb->posts.post_status = '$state'";
+					$where .= current_user_can( $read_private_cap ) ? " OR {$this->dbh->posts}.post_status = '$state'" : " OR {$this->dbh->posts}.post_author = $user_id AND {$this->dbh->posts}.post_status = '$state'";
 			}
 
 			$where .= ')';
@@ -3230,11 +3216,11 @@
 		// Comments feeds
 		if ( $this->is_comment_feed && ! $this->is_singular ) {
 			if ( $this->is_archive || $this->is_search ) {
-				$cjoin = "JOIN $wpdb->posts ON ($wpdb->comments.comment_post_ID = $wpdb->posts.ID) $join ";
+				$cjoin = "JOIN {$this->dbh->posts} ON ({$this->dbh->comments}.comment_post_ID = {$this->dbh->posts}.ID) $join ";
 				$cwhere = "WHERE comment_approved = '1' $where";
-				$cgroupby = "$wpdb->comments.comment_id";
+				$cgroupby = "{$this->dbh->comments}.comment_id";
 			} else { // Other non singular e.g. front
-				$cjoin = "JOIN $wpdb->posts ON ( $wpdb->comments.comment_post_ID = $wpdb->posts.ID )";
+				$cjoin = "JOIN {$this->dbh->posts} ON ( {$this->dbh->comments}.comment_post_ID = {$this->dbh->posts}.ID )";
 				$cwhere = "WHERE ( post_status = 'publish' OR ( post_status = 'inherit' && post_type = 'attachment' ) ) AND comment_approved = '1'";
 				$cgroupby = '';
 			}
@@ -3293,7 +3279,7 @@
 			$cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
 			$corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
 
-			$comments = (array) $wpdb->get_results("SELECT $distinct $wpdb->comments.* FROM $wpdb->comments $cjoin $cwhere $cgroupby $corderby $climits");
+			$comments = (array) $this->dbh->get_results("SELECT $distinct {$this->dbh->comments}.* FROM {$this->dbh->comments} $cjoin $cwhere $cgroupby $corderby $climits");
 			// Convert to WP_Comment
 			$this->comments = array_map( 'get_comment', $comments );
 			$this->comment_count = count($this->comments);
@@ -3306,7 +3292,7 @@
 			$post_ids = join(',', $post_ids);
 			$join = '';
 			if ( $post_ids )
-				$where = "AND $wpdb->posts.ID IN ($post_ids) ";
+				$where = "AND {$this->dbh->posts}.ID IN ($post_ids) ";
 			else
 				$where = "AND 0";
 		}
@@ -3547,7 +3533,7 @@
 		if ( !$q['no_found_rows'] && !empty($limits) )
 			$found_rows = 'SQL_CALC_FOUND_ROWS';
 
-		$this->request = $old_request = "SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
+		$this->request = $old_request = "SELECT $found_rows $distinct $fields FROM {$this->dbh->posts} $join WHERE 1=1 $where $groupby $orderby $limits";
 
 		if ( !$q['suppress_filters'] ) {
 			/**
@@ -3581,7 +3567,7 @@
 
 		if ( 'ids' == $q['fields'] ) {
 			if ( null === $this->posts ) {
-				$this->posts = $wpdb->get_col( $this->request );
+				$this->posts = $this->dbh->get_col( $this->request );
 			}
 
 			$this->posts = array_map( 'intval', $this->posts );
@@ -3593,7 +3579,7 @@
 
 		if ( 'id=>parent' == $q['fields'] ) {
 			if ( null === $this->posts ) {
-				$this->posts = $wpdb->get_results( $this->request );
+				$this->posts = $this->dbh->get_results( $this->request );
 			}
 
 			$this->post_count = count( $this->posts );
@@ -3611,7 +3597,7 @@
 		}
 
 		if ( null === $this->posts ) {
-			$split_the_query = ( $old_request == $this->request && "$wpdb->posts.*" == $fields && !empty( $limits ) && $q['posts_per_page'] < 500 );
+			$split_the_query = ( $old_request == $this->request && "{$this->dbh->posts}.*" == $fields && !empty( $limits ) && $q['posts_per_page'] < 500 );
 
 			/**
 			 * Filters whether to split the query.
@@ -3630,7 +3616,7 @@
 			if ( $split_the_query ) {
 				// First get the IDs and then fill in the objects
 
-				$this->request = "SELECT $found_rows $distinct $wpdb->posts.ID FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
+				$this->request = "SELECT $found_rows $distinct {$this->dbh->posts}.ID FROM {$this->dbh->posts} $join WHERE 1=1 $where $groupby $orderby $limits";
 
 				/**
 				 * Filters the Post IDs SQL request before sending.
@@ -3642,7 +3628,7 @@
 				 */
 				$this->request = apply_filters( 'posts_request_ids', $this->request, $this );
 
-				$ids = $wpdb->get_col( $this->request );
+				$ids = $this->dbh->get_col( $this->request );
 
 				if ( $ids ) {
 					$this->posts = $ids;
@@ -3652,7 +3638,7 @@
 					$this->posts = array();
 				}
 			} else {
-				$this->posts = $wpdb->get_results( $this->request );
+				$this->posts = $this->dbh->get_results( $this->request );
 				$this->set_found_posts( $q, $limits );
 			}
 		}
@@ -3692,8 +3678,8 @@
 			/** This filter is documented in wp-includes/query.php */
 			$climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) );
 
-			$comments_request = "SELECT $wpdb->comments.* FROM $wpdb->comments $cjoin $cwhere $cgroupby $corderby $climits";
-			$comments = $wpdb->get_results($comments_request);
+			$comments_request = "SELECT {$this->dbh->comments}.* FROM {$this->dbh->comments} $cjoin $cwhere $cgroupby $corderby $climits";
+			$comments = $this->dbh->get_results($comments_request);
 			// Convert to WP_Comment
 			$this->comments = array_map( 'get_comment', $comments );
 			$this->comment_count = count($this->comments);
@@ -3836,14 +3822,10 @@
 	 * @since 3.5.0
 	 * @access private
 	 *
-	 * @global wpdb $wpdb WordPress database abstraction object.
-	 *
 	 * @param array  $q      Query variables.
 	 * @param string $limits LIMIT clauses of the query.
 	 */
 	private function set_found_posts( $q, $limits ) {
-		global $wpdb;
-
 		// Bail if posts is an empty array. Continue if posts is an empty string,
 		// null, or false to accommodate caching plugins that fill posts later.
 		if ( $q['no_found_rows'] || ( is_array( $this->posts ) && ! $this->posts ) )
@@ -3858,7 +3840,7 @@
 			 * @param string   $found_posts The query to run to find the found posts.
 			 * @param WP_Query &$this       The WP_Query instance (passed by reference).
 			 */
-			$this->found_posts = $wpdb->get_var( apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) ) );
+			$this->found_posts = $this->dbh->get_var( apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) ) );
 		} else {
 			$this->found_posts = count( $this->posts );
 		}
@@ -4157,6 +4139,8 @@
 	 * @param string|array $query URL query string or array of vars.
 	 */
 	public function __construct($query = '') {
+		$this->dbh = WP::get( 'wpdb' );
+
 		if ( ! empty($query) ) {
 			$this->query($query);
 		}
@@ -4928,13 +4912,12 @@
  * @since 2.1.0
  *
  * @global WP_Query   $wp_query   Global WP_Query instance.
- * @global wpdb       $wpdb       WordPress database abstraction object.
  */
 function wp_old_slug_redirect() {
 	global $wp_query;
 
 	if ( is_404() && '' !== $wp_query->query_vars['name'] ) :
-		global $wpdb;
+		$wpdb = WP::get( 'wpdb' );
 
 		// Guess the current post_type based on the query vars.
 		if ( get_query_var( 'post_type' ) ) {
Index: src/wp-includes/revision.php
===================================================================
--- src/wp-includes/revision.php	(revision 38271)
+++ src/wp-includes/revision.php	(working copy)
@@ -633,14 +633,12 @@
  * @since 3.6.0
  * @access private
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param WP_Post $post      Post object
  * @param array   $revisions Current revisions of the post
  * @return bool true if the revisions were upgraded, false if problems
  */
 function _wp_upgrade_revisions_of_post( $post, $revisions ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	// Add post option exclusively
 	$lock = "revision-upgrade-{$post->ID}";
Index: src/wp-includes/taxonomy.php
===================================================================
--- src/wp-includes/taxonomy.php	(revision 38271)
+++ src/wp-includes/taxonomy.php	(working copy)
@@ -717,8 +717,6 @@
  *
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|array    $term_ids   Term id or array of term ids of terms that will be used.
  * @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names.
  * @param array|string $args       Change the order of the object_ids, either ASC or DESC.
@@ -726,8 +724,6 @@
  *	the array can be empty meaning that there are no $object_ids found or it will return the $object_ids found.
  */
 function get_objects_in_term( $term_ids, $taxonomies, $args = array() ) {
-	global $wpdb;
-
 	if ( ! is_array( $term_ids ) ) {
 		$term_ids = array( $term_ids );
 	}
@@ -750,6 +746,7 @@
 	$taxonomies = "'" . implode( "', '", array_map( 'esc_sql', $taxonomies ) ) . "'";
 	$term_ids = "'" . implode( "', '", $term_ids ) . "'";
 
+	$wpdb = WP::get( 'wpdb' );
 	$object_ids = $wpdb->get_col("SELECT tr.object_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tt.term_id IN ($term_ids) ORDER BY tr.object_id $order");
 
 	if ( ! $object_ids ){
@@ -806,7 +803,6 @@
  * @since 4.4.0 Converted to return a WP_Term object if `$output` is `OBJECT`.
  *              The `$taxonomy` parameter was made optional.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
  * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param.
  *
  * @param int|WP_Term|object $term If integer, term data will be fetched from the database, or from the cache if
@@ -915,7 +911,6 @@
  * @since 4.4.0 `$taxonomy` is optional if `$field` is 'term_taxonomy_id'. Converted to return
  *              a WP_Term object if `$output` is `OBJECT`.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
  * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param.
  *
  * @param string     $field    Either 'slug', 'name', 'id' (term_id), or 'term_taxonomy_id'
@@ -927,13 +922,12 @@
  *                      or `$term` was not found.
  */
 function get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) {
-	global $wpdb;
-
 	// 'term_taxonomy_id' lookups don't require taxonomy checks.
 	if ( 'term_taxonomy_id' !== $field && ! taxonomy_exists( $taxonomy ) ) {
 		return false;
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$tax_clause = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy );
 
 	if ( 'slug' == $field ) {
@@ -1107,7 +1101,6 @@
  *
  * @internal The `$deprecated` parameter is parsed for backward compatibility only.
  *
- * @global wpdb  $wpdb WordPress database abstraction object.
  * @global array $wp_filter
  *
  * @param array|string $args {
@@ -1180,8 +1173,6 @@
  *                            do not exist.
  */
 function get_terms( $args = array(), $deprecated = '' ) {
-	global $wpdb;
-
 	$term_query = new WP_Term_Query();
 
 	/*
@@ -1377,8 +1368,6 @@
  *
  * @since 3.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|string $term     The term to check
  * @param string     $taxonomy The taxonomy name to use
  * @param int        $parent   Optional. ID of parent term under which to confine the exists search.
@@ -1388,8 +1377,7 @@
  *               is specified and the pairing exists.
  */
 function term_exists( $term, $taxonomy = '', $parent = null ) {
-	global $wpdb;
-
+	$wpdb = WP::get( 'wpdb' );
 	$select = "SELECT term_id FROM $wpdb->terms as t WHERE ";
 	$tax_select = "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE ";
 
@@ -1737,8 +1725,6 @@
  *
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int          $term     Term ID.
  * @param string       $taxonomy Taxonomy Name.
  * @param array|string $args {
@@ -1755,8 +1741,6 @@
  *                           deletion of default Category. WP_Error if the taxonomy does not exist.
  */
 function wp_delete_term( $term, $taxonomy, $args = array() ) {
-	global $wpdb;
-
 	$term = (int) $term;
 
 	if ( ! $ids = term_exists($term, $taxonomy) )
@@ -1797,6 +1781,7 @@
 	 */
 	do_action( 'pre_delete_term', $term, $taxonomy );
 
+	$wpdb = WP::get( 'wpdb' );
 	// Update children to point to new parent
 	if ( is_taxonomy_hierarchical($taxonomy) ) {
 		$term_obj = get_term($term, $taxonomy);
@@ -1942,8 +1927,6 @@
  * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
  *              'all_with_object_id', an array of `WP_Term` objects will be returned.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
  * @param string|array $taxonomies The taxonomies to retrieve terms from.
  * @param array|string $args {
@@ -1966,8 +1949,6 @@
  *                        WP_Error if any of the $taxonomies don't exist.
  */
 function wp_get_object_terms($object_ids, $taxonomies, $args = array()) {
-	global $wpdb;
-
 	if ( empty( $object_ids ) || empty( $taxonomies ) )
 		return array();
 
@@ -2059,6 +2040,8 @@
 		"tr.object_id IN ($object_ids)",
 	);
 
+	$wpdb = WP::get( 'wpdb' );
+
 	if ( '' !== $args['parent'] ) {
 		$where[] = $wpdb->prepare( 'tt.parent = %d', $args['parent'] );
 	}
@@ -2205,8 +2188,6 @@
  * If the term already exists on the same hierarchical level,
  * or the term slug and name are not unique, a WP_Error object will be returned.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @since 2.3.0
  *
  * @param string       $term     The term to add or update.
@@ -2224,8 +2205,6 @@
  *                        WP_Error otherwise.
  */
 function wp_insert_term( $term, $taxonomy, $args = array() ) {
-	global $wpdb;
-
 	if ( ! taxonomy_exists($taxonomy) ) {
 		return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
 	}
@@ -2254,6 +2233,8 @@
 		return new WP_Error( 'missing_parent', __( 'Parent term does not exist.' ) );
 	}
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$args['name'] = $term;
 	$args['taxonomy'] = $taxonomy;
 
@@ -2460,8 +2441,6 @@
  *
  * @since 2.3.0
  *
- * @global wpdb $wpdb The WordPress database abstraction object.
- *
  * @param int              $object_id The object to relate to.
  * @param array|int|string $terms     A single term slug, single term id, or array of either term slugs or ids.
  *                                    Will replace all existing related terms in this taxonomy.
@@ -2470,8 +2449,6 @@
  * @return array|WP_Error Term taxonomy IDs of the affected terms.
  */
 function wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) {
-	global $wpdb;
-
 	$object_id = (int) $object_id;
 
 	if ( ! taxonomy_exists( $taxonomy ) ) {
@@ -2490,6 +2467,8 @@
 	$term_ids = array();
 	$new_tt_ids = array();
 
+	$wpdb = WP::get( 'wpdb' );
+
 	foreach ( (array) $terms as $term) {
 		if ( !strlen(trim($term)) )
 			continue;
@@ -2600,8 +2579,6 @@
  *
  * @since 3.6.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int              $object_id The ID of the object from which the terms will be removed.
  * @param array|int|string $terms     The slug(s) or ID(s) of the term(s) to remove.
  * @param array|string     $taxonomy  Taxonomy name.
@@ -2608,8 +2585,6 @@
  * @return bool|WP_Error True on success, false or WP_Error on failure.
  */
 function wp_remove_object_terms( $object_id, $terms, $taxonomy ) {
-	global $wpdb;
-
 	$object_id = (int) $object_id;
 
 	if ( ! taxonomy_exists( $taxonomy ) ) {
@@ -2653,6 +2628,7 @@
 		 * @param array $tt_ids    An array of term taxonomy IDs.
 		 */
 		do_action( 'delete_term_relationships', $object_id, $tt_ids );
+		$wpdb = WP::get( 'wpdb' );
 		$deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) );
 
 		wp_cache_delete( $object_id, $taxonomy . '_relationships' );
@@ -2692,15 +2668,11 @@
  *
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $slug The string that will be tried for a unique slug.
  * @param object $term The term object that the `$slug` will belong to.
  * @return string Will return a true unique slug.
  */
 function wp_unique_term_slug( $slug, $term ) {
-	global $wpdb;
-
 	$needs_suffix = true;
 	$original_slug = $slug;
 
@@ -2746,6 +2718,8 @@
 		if ( $parent_suffix ) {
 			$slug .= $parent_suffix;
 		} else {
+			$wpdb = WP::get( 'wpdb' );
+
 			if ( ! empty( $term->term_id ) )
 				$query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s AND term_id != %d", $slug, $term->term_id );
 			else
@@ -2798,8 +2772,6 @@
  *
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int          $term_id  The ID of the term
  * @param string       $taxonomy The context in which to relate the term to the object.
  * @param array|string $args     Optional. Array of get_terms() arguments. Default empty array.
@@ -2806,8 +2778,6 @@
  * @return array|WP_Error Returns Term ID and Taxonomy Term ID
  */
 function wp_update_term( $term_id, $taxonomy, $args = array() ) {
-	global $wpdb;
-
 	if ( ! taxonomy_exists( $taxonomy ) ) {
 		return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
 	}
@@ -2853,6 +2823,8 @@
 		return new WP_Error( 'missing_parent', __( 'Parent term does not exist.' ) );
 	}
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$empty_slug = false;
 	if ( empty( $args['slug'] ) ) {
 		$empty_slug = true;
@@ -3178,7 +3150,6 @@
  *
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
  * @global bool $_wp_suspend_cache_invalidation
  *
  * @param int|array $ids            Single or list of Term IDs.
@@ -3188,7 +3159,7 @@
  *                                  term object caches (false). Default true.
  */
 function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) {
-	global $wpdb, $_wp_suspend_cache_invalidation;
+	global $_wp_suspend_cache_invalidation;
 
 	if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
 		return;
@@ -3202,6 +3173,7 @@
 	if ( empty($taxonomy) ) {
 		$tt_ids = array_map('intval', $ids);
 		$tt_ids = implode(', ', $tt_ids);
+		$wpdb = WP::get( 'wpdb' );
 		$terms = $wpdb->get_results("SELECT term_id, taxonomy FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ($tt_ids)");
 		$ids = array();
 		foreach ( (array) $terms as $term ) {
@@ -3482,14 +3454,10 @@
  * @access private
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array  $terms    List of term objects, passed by reference.
  * @param string $taxonomy Term context.
  */
 function _pad_term_counts( &$terms, $taxonomy ) {
-	global $wpdb;
-
 	// This function only works for hierarchical taxonomies like post categories.
 	if ( !is_taxonomy_hierarchical( $taxonomy ) )
 		return;
@@ -3499,6 +3467,8 @@
 	if ( empty($term_hier) )
 		return;
 
+	$wpdb = WP::get( 'wpdb' );
+
 	$term_items = array();
 	$terms_by_id = array();
 	$term_ids = array();
@@ -3547,16 +3517,13 @@
  * @since 4.6.0
  * @access private
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array $term_ids          Array of term IDs.
  * @param bool  $update_meta_cache Optional. Whether to update the meta cache. Default true.
  */
 function _prime_term_caches( $term_ids, $update_meta_cache = true ) {
-	global $wpdb;
-
 	$non_cached_ids = _get_non_cached_ids( $term_ids, 'terms' );
 	if ( ! empty( $non_cached_ids ) ) {
+		$wpdb = WP::get( 'wpdb' );
 		$fresh_terms = $wpdb->get_results( sprintf( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.term_id IN (%s)", join( ",", array_map( 'intval', $non_cached_ids ) ) ) );
 
 		update_term_cache( $fresh_terms, $update_meta_cache );
@@ -3580,14 +3547,10 @@
  * @access private
  * @since 2.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array  $terms    List of Term taxonomy IDs.
  * @param object $taxonomy Current taxonomy object of terms.
  */
 function _update_post_term_count( $terms, $taxonomy ) {
-	global $wpdb;
-
 	$object_types = (array) $taxonomy->object_type;
 
 	foreach ( $object_types as &$object_type )
@@ -3603,6 +3566,7 @@
 	if ( $object_types )
 		$object_types = esc_sql( array_filter( $object_types, 'post_type_exists' ) );
 
+	$wpdb = WP::get( 'wpdb' );
 	foreach ( (array) $terms as $term ) {
 		$count = 0;
 
@@ -3629,13 +3593,11 @@
  *
  * @since 3.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array  $terms    List of term taxonomy IDs.
  * @param object $taxonomy Current taxonomy object of terms.
  */
 function _update_generic_term_count( $terms, $taxonomy ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	foreach ( (array) $terms as $term ) {
 		$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term ) );
@@ -3658,8 +3620,6 @@
  * @since 4.3.0 Introduced `$record` parameter. Also, `$term_id` and
  *              `$term_taxonomy_id` can now accept objects.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int|object $term_id          ID of the shared term, or the shared term object.
  * @param int|object $term_taxonomy_id ID of the term_taxonomy item to receive a new term, or the term_taxonomy object
  *                                     (corresponding to a row from the term_taxonomy table).
@@ -3673,8 +3633,6 @@
  *                      new term_id is returned. A WP_Error is returned for miscellaneous errors.
  */
 function _split_shared_term( $term_id, $term_taxonomy_id, $record = true ) {
-	global $wpdb;
-
 	if ( is_object( $term_id ) ) {
 		$shared_term = $term_id;
 		$term_id = intval( $shared_term->term_id );
@@ -3685,6 +3643,7 @@
 		$term_taxonomy_id = intval( $term_taxonomy->term_taxonomy_id );
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	// If there are no shared term_taxonomy rows, there's nothing to do here.
 	$shared_tt_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy tt WHERE tt.term_id = %d AND tt.term_taxonomy_id != %d", $term_id, $term_taxonomy_id ) );
 
@@ -3794,10 +3753,9 @@
  *
  * @since 4.3.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
  */
 function _wp_batch_split_terms() {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$lock_name = 'term_split.lock';
 
@@ -3926,8 +3884,6 @@
  * @ignore
  * @since 4.2.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int    $term_id          ID of the formerly shared term.
  * @param int    $new_term_id      ID of the new term created for the $term_taxonomy_id.
  * @param int    $term_taxonomy_id ID for the term_taxonomy row affected by the split.
@@ -3934,7 +3890,7 @@
  * @param string $taxonomy         Taxonomy for the split term.
  */
 function _wp_check_split_terms_in_menus( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 	$post_ids = $wpdb->get_col( $wpdb->prepare(
 		"SELECT m1.post_id
 		FROM {$wpdb->postmeta} AS m1
@@ -4033,12 +3989,11 @@
  * @return bool
  */
 function wp_term_is_shared( $term_id ) {
-	global $wpdb;
-
 	if ( get_option( 'finished_splitting_shared_terms' ) ) {
 		return false;
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$tt_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) );
 
 	return $tt_count > 1;
Index: src/wp-includes/template.php
===================================================================
--- src/wp-includes/template.php	(revision 38271)
+++ src/wp-includes/template.php	(working copy)
@@ -547,7 +547,6 @@
  * @global bool       $wp_did_header
  * @global WP_Query   $wp_query
  * @global WP_Rewrite $wp_rewrite
- * @global wpdb       $wpdb
  * @global string     $wp_version
  * @global WP         $wp
  * @global int        $id
@@ -558,8 +557,10 @@
  * @param bool   $require_once   Whether to require_once or require. Default true.
  */
 function load_template( $_template_file, $require_once = true ) {
-	global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;
+	global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wp_version, $wp, $id, $comment, $user_ID;
 
+	$wpdb = WP::get( 'wpdb' );
+
 	if ( is_array( $wp_query->query_vars ) ) {
 		extract( $wp_query->query_vars, EXTR_SKIP );
 	}
Index: src/wp-includes/update.php
===================================================================
--- src/wp-includes/update.php	(revision 38271)
+++ src/wp-includes/update.php	(working copy)
@@ -15,7 +15,6 @@
  *
  * @since 2.3.0
  * @global string $wp_version Used to check against the newest WordPress version.
- * @global wpdb   $wpdb
  * @global string $wp_local_package
  *
  * @param array $extra_stats Extra statistics to report to the WordPress.org API.
@@ -26,7 +25,9 @@
 		return;
 	}
 
-	global $wpdb, $wp_local_package;
+	global $wp_local_package;
+	$wpdb = WP::get( 'wpdb' );
+
 	// include an unmodified $wp_version
 	include( ABSPATH . WPINC . '/version.php' );
 	$php_version = phpversion();
Index: src/wp-includes/user.php
===================================================================
--- src/wp-includes/user.php	(revision 38271)
+++ src/wp-includes/user.php	(working copy)
@@ -347,8 +347,6 @@
  * @since 4.3.0 Added `$public_only` argument. Added the ability to pass an array
  *              of post types to `$post_type`.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int          $userid      User ID.
  * @param array|string $post_type   Optional. Single post type or array of post types to count the number of posts for. Default 'post'.
  * @param bool         $public_only Optional. Whether to only return counts for public posts. Default false.
@@ -355,7 +353,7 @@
  * @return string Number of posts the user has written in this post type.
  */
 function count_user_posts( $userid, $post_type = 'post', $public_only = false ) {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	$where = get_posts_by_author_sql( $post_type, true, $userid, $public_only );
 
@@ -381,8 +379,6 @@
  *
  * @since 3.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array        $users       Array of user IDs.
  * @param string|array $post_type   Optional. Single post type or array of post types to check. Defaults to 'post'.
  * @param bool         $public_only Optional. Only return counts for public posts.  Defaults to false.
@@ -389,8 +385,6 @@
  * @return array Amount of posts each user has written.
  */
 function count_many_users_posts( $users, $post_type = 'post', $public_only = false ) {
-	global $wpdb;
-
 	$count = array();
 	if ( empty( $users ) || ! is_array( $users ) )
 		return $count;
@@ -398,6 +392,7 @@
 	$userlist = implode( ',', array_map( 'absint', $users ) );
 	$where = get_posts_by_author_sql( $post_type, true, null, $public_only );
 
+	$wpdb = WP::get( 'wpdb' );
 	$result = $wpdb->get_results( "SELECT post_author, COUNT(*) FROM $wpdb->posts $where AND post_author IN ($userlist) GROUP BY post_author", ARRAY_N );
 	foreach ( $result as $row ) {
 		$count[ $row[0] ] = $row[1];
@@ -441,8 +436,6 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $option     User option name.
  * @param int    $user       Optional. User ID.
  * @param string $deprecated Use get_option() to check for an option in the options table.
@@ -449,8 +442,6 @@
  * @return mixed User option value on success, false on failure.
  */
 function get_user_option( $option, $user = 0, $deprecated = '' ) {
-	global $wpdb;
-
 	if ( !empty( $deprecated ) )
 		_deprecated_argument( __FUNCTION__, '3.0.0' );
 
@@ -460,6 +451,7 @@
 	if ( ! $user = get_userdata( $user ) )
 		return false;
 
+	$wpdb = WP::get( 'wpdb' );
 	$prefix = $wpdb->get_blog_prefix();
 	if ( $user->has_prop( $prefix . $option ) ) // Blog specific
 		$result = $user->get( $prefix . $option );
@@ -493,8 +485,6 @@
  *
  * @since 2.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int    $user_id     User ID.
  * @param string $option_name User option name.
  * @param mixed  $newvalue    User option value.
@@ -504,11 +494,10 @@
  *                  false on failure.
  */
 function update_user_option( $user_id, $option_name, $newvalue, $global = false ) {
-	global $wpdb;
-
-	if ( !$global )
+	if ( ! $global ) {
+		$wpdb = WP::get( 'wpdb' );
 		$option_name = $wpdb->get_blog_prefix() . $option_name;
-
+	}
 	return update_user_meta( $user_id, $option_name, $newvalue );
 }
 
@@ -521,8 +510,6 @@
  *
  * @since 3.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int    $user_id     User ID
  * @param string $option_name User option name.
  * @param bool   $global      Optional. Whether option name is global or blog specific.
@@ -530,10 +517,10 @@
  * @return bool True on success, false on failure.
  */
 function delete_user_option( $user_id, $option_name, $global = false ) {
-	global $wpdb;
-
-	if ( !$global )
+	if ( ! $global ) {
+		$wpdb = WP::get( 'wpdb' );
 		$option_name = $wpdb->get_blog_prefix() . $option_name;
+	}
 	return delete_user_meta( $user_id, $option_name );
 }
 
@@ -563,8 +550,6 @@
  *
  * @since 3.0.0
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param int  $user_id User ID
  * @param bool $all     Whether to retrieve all blogs, or only blogs that are not
  *                      marked as deleted, archived, or spam.
@@ -572,8 +557,6 @@
  *               or belongs to no blogs.
  */
 function get_blogs_of_user( $user_id, $all = false ) {
-	global $wpdb;
-
 	$user_id = (int) $user_id;
 
 	// Logged out users can't have blogs
@@ -619,6 +602,7 @@
 	}
 
 	$blogs = array();
+	$wpdb = WP::get( 'wpdb' );
 
 	if ( isset( $keys[ $wpdb->base_prefix . 'capabilities' ] ) && defined( 'MULTISITE' ) ) {
 		$blog = get_blog_details( 1 );
@@ -691,8 +675,6 @@
  * @return bool
  */
 function is_user_member_of_blog( $user_id = 0, $blog_id = 0 ) {
-	global $wpdb;
-
 	$user_id = (int) $user_id;
 	$blog_id = (int) $blog_id;
 
@@ -730,6 +712,7 @@
 		return false;
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	// no underscore before capabilities in $base_capabilities_key
 	$base_capabilities_key = $wpdb->base_prefix . 'capabilities';
 	$site_capabilities_key = $wpdb->base_prefix . $blog_id . '_capabilities';
@@ -829,13 +812,11 @@
  * @since 3.0.0
  * @since 4.4.0 The number of users with no role is now included in the `none` element.
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param string $strategy 'time' or 'memory'
  * @return array Includes a grand total and an array of counts indexed by role strings.
  */
 function count_users($strategy = 'time') {
-	global $wpdb;
+	$wpdb = WP::get( 'wpdb' );
 
 	// Initialize
 	$id = get_current_blog_id();
@@ -1347,8 +1328,6 @@
  * @since 3.6.0 The `aim`, `jabber`, and `yim` fields were removed as default user contact
  *              methods for new installs. See wp_get_user_contact_methods().
  *
- * @global wpdb $wpdb WordPress database abstraction object.
- *
  * @param array|object|WP_User $userdata {
  *     An array, object, or WP_User object of user data arguments.
  *
@@ -1385,8 +1364,6 @@
  *                      be created.
  */
 function wp_insert_user( $userdata ) {
-	global $wpdb;
-
 	if ( $userdata instanceof stdClass ) {
 		$userdata = get_object_vars( $userdata );
 	} elseif ( $userdata instanceof WP_User ) {
@@ -1594,6 +1571,7 @@
 
 	$meta['show_admin_bar_front'] = empty( $userdata['show_admin_bar_front'] ) ? 'true' : $userdata['show_admin_bar_front'];
 
+	$wpdb = WP::get( 'wpdb' );
 	$user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $user_nicename, $user_login));
 
 	if ( $user_nicename_check ) {
@@ -2028,16 +2006,11 @@
  *
  * @since 4.4.0
  *
- * @global wpdb         $wpdb      WordPress database abstraction object.
- * @global PasswordHash $wp_hasher Portable PHP password hashing framework.
- *
  * @param WP_User $user User to retrieve password reset key for.
  *
  * @return string|WP_Error Password reset key on success. WP_Error on error.
  */
 function get_password_reset_key( $user ) {
-	global $wpdb, $wp_hasher;
-
 	/**
 	 * Fires before a new password is retrieved.
 	 *
@@ -2094,11 +2067,9 @@
 	do_action( 'retrieve_password_key', $user->user_login, $key );
 
 	// Now insert the key, hashed, into the DB.
-	if ( empty( $wp_hasher ) ) {
-		require_once ABSPATH . WPINC . '/class-phpass.php';
-		$wp_hasher = new PasswordHash( 8, true );
-	}
+	$wp_hasher = WP::get( 'wp_hasher', true );
 	$hashed = time() . ':' . $wp_hasher->HashPassword( $key );
+	$wpdb = WP::get( 'wpdb' );
 	$key_saved = $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
 	if ( false === $key_saved ) {
 		return new WP_Error( 'no_password_key_update', __( 'Could not save password reset key to database.' ) );
@@ -2117,16 +2088,11 @@
  *
  * @since 3.1.0
  *
- * @global wpdb         $wpdb      WordPress database object for queries.
- * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
- *
  * @param string $key       Hash to validate sending user's password.
  * @param string $login     The user login.
  * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys.
  */
 function check_password_reset_key($key, $login) {
-	global $wpdb, $wp_hasher;
-
 	$key = preg_replace('/[^a-z0-9]/i', '', $key);
 
 	if ( empty( $key ) || !is_string( $key ) )
@@ -2135,14 +2101,12 @@
 	if ( empty($login) || !is_string($login) )
 		return new WP_Error('invalid_key', __('Invalid key'));
 
+	$wpdb = WP::get( 'wpdb' );
 	$row = $wpdb->get_row( $wpdb->prepare( "SELECT ID, user_activation_key FROM $wpdb->users WHERE user_login = %s", $login ) );
 	if ( ! $row )
 		return new WP_Error('invalid_key', __('Invalid key'));
 
-	if ( empty( $wp_hasher ) ) {
-		require_once ABSPATH . WPINC . '/class-phpass.php';
-		$wp_hasher = new PasswordHash( 8, true );
-	}
+	$wp_hasher = WP::get( 'wp_hasher', true );
 
 	/**
 	 * Filters the expiration time of password reset keys.
@@ -2419,12 +2383,11 @@
  * @return array Array of user IDs.
  */
 function wp_get_users_with_no_role() {
-	global $wpdb;
-
 	if ( is_multisite() ) {
 		return array();
 	}
 
+	$wpdb = WP::get( 'wpdb' );
 	$prefix = $wpdb->get_blog_prefix();
 	$regex  = implode( '|', wp_roles()->get_names() );
 	$regex  = preg_replace( '/[^a-zA-Z_\|-]/', '', $regex );
Index: src/wp-settings.php
===================================================================
--- src/wp-settings.php	(revision 38271)
+++ src/wp-settings.php	(working copy)
@@ -21,6 +21,8 @@
 require( ABSPATH . WPINC . '/load.php' );
 require( ABSPATH . WPINC . '/default-constants.php' );
 require( ABSPATH . WPINC . '/plugin.php' );
+require( ABSPATH . WPINC . '/class-wp-registry.php' );
+require( ABSPATH . WPINC . '/class-wp.php' );
 
 /*
  * These can't be directly globalized in version.php. When updating,
@@ -92,12 +94,10 @@
 // Load early WordPress files.
 require( ABSPATH . WPINC . '/compat.php' );
 require( ABSPATH . WPINC . '/functions.php' );
-require( ABSPATH . WPINC . '/class-wp.php' );
 require( ABSPATH . WPINC . '/class-wp-error.php' );
 require( ABSPATH . WPINC . '/pomo/mo.php' );
 
 // Include the wpdb class and, if present, a db.php database drop-in.
-global $wpdb;
 require_wp_db();
 
 // Set the database table prefix and the format specifiers for database table columns.
