diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php
index ec50703b33..ae6d15b311 100644
--- a/src/wp-includes/media.php
+++ b/src/wp-includes/media.php
@@ -2793,46 +2793,46 @@ function next_image_link( $size = 'thumbnail', $text = false ) {
  *
  * @since 2.5.0
  *
+ * @uses _previous_image_post_where_filter_once()
+ * @uses _next_image_post_where_filter_once()
+ *
  * @param bool         $prev Optional. Whether to display the next (false) or previous (true) link. Default true.
  * @param string|array $size Optional. Image size. Accepts any valid image size, or an array of width and height
  *                           values in pixels (in that order). Default 'thumbnail'.
  * @param bool         $text Optional. Link text. Default false.
  */
 function adjacent_image_link( $prev = true, $size = 'thumbnail', $text = false ) {
-	$post        = get_post();
-	$attachments = array_values(
+	$adjacent = $prev ? 'previous' : 'next';
+	$order    = $prev ? 'DESC' : 'ASC';
+	$post     = get_post();
+
+	add_filter( 'posts_where', "_{$adjacent}_image_posts_where_filter_once" );
+
+	$attachment = array_values(
 		get_children(
 			array(
-				'post_parent'    => $post->post_parent,
-				'post_status'    => 'inherit',
-				'post_type'      => 'attachment',
-				'post_mime_type' => 'image',
-				'order'          => 'ASC',
-				'orderby'        => 'menu_order ID',
+				'post_parent'      => $post->post_parent,
+				'post_status'      => 'inherit',
+				'post_type'        => 'attachment',
+				'post_mime_type'   => 'image',
+				'orderby'          => array(
+					'menu_order' => $order,
+					'ID'         => $order,
+				),
+				'posts_per_page'   => 1,
+				'suppress_filters' => false,
 			)
 		)
 	);
 
-	foreach ( $attachments as $k => $attachment ) {
-		if ( $attachment->ID == $post->ID ) {
-			break;
-		}
-	}
-
 	$output        = '';
 	$attachment_id = 0;
 
-	if ( $attachments ) {
-		$k = $prev ? $k - 1 : $k + 1;
-
-		if ( isset( $attachments[ $k ] ) ) {
-			$attachment_id = $attachments[ $k ]->ID;
-			$output        = wp_get_attachment_link( $attachment_id, $size, true, false, $text );
-		}
+	if ( ! empty( $attachment ) ) {
+		$attachment_id = $attachment[0]->ID;
+		$output        = wp_get_attachment_link( $attachment_id, $size, true, false, $text );
 	}
 
-	$adjacent = $prev ? 'previous' : 'next';
-
 	/**
 	 * Filters the adjacent image link.
 	 *
@@ -2849,6 +2849,28 @@ function adjacent_image_link( $prev = true, $size = 'thumbnail', $text = false )
 	echo apply_filters( "{$adjacent}_image_link", $output, $attachment_id, $size, $text );
 }
 
+/**
+ * Append to WHERE clause for selecting only the previous image.
+ *
+ * @param string $where The WHERE clause of the query.
+ */
+function _previous_image_posts_where_filter_once( $where ) {
+	remove_filter( 'posts_where', __FUNCTION__ );
+	$post = get_post();
+	return "$where AND (menu_order < $post->menu_order OR (menu_order = $post->menu_order AND ID < $post->ID))";
+}
+
+/**
+ * Append to WHERE clause for selecting only the next image.
+ *
+ * @param string $where The WHERE clause of the query.
+ */
+function _next_image_posts_where_filter_once( $where ) {
+	remove_filter( 'posts_where', __FUNCTION__ );
+	$post = get_post();
+	return "$where AND (menu_order > $post->menu_order OR (menu_order = $post->menu_order AND ID > $post->ID))";
+}
+
 /**
  * Retrieves taxonomies attached to given the attachment.
  *
