diff --git src/wp-includes/comment.php src/wp-includes/comment.php
index c8984f0..5d82b1f 100644
--- src/wp-includes/comment.php
+++ src/wp-includes/comment.php
@@ -511,39 +511,75 @@ class WP_Comment_Query {
 				$this->query_vars['orderby'] :
 				preg_split( '/[,\s]/', $this->query_vars['orderby'] );
 
-			$allowed_keys = array(
-				'comment_agent',
-				'comment_approved',
-				'comment_author',
-				'comment_author_email',
-				'comment_author_IP',
-				'comment_author_url',
-				'comment_content',
-				'comment_date',
-				'comment_date_gmt',
-				'comment_ID',
-				'comment_karma',
-				'comment_parent',
-				'comment_post_ID',
-				'comment_type',
-				'user_id',
-			);
-			if ( ! empty( $this->query_vars['meta_key'] ) ) {
-				$allowed_keys[] = $this->query_vars['meta_key'];
-				$allowed_keys[] = 'meta_value';
-				$allowed_keys[] = 'meta_value_num';
+			$orderby_array = array();
+			$found_orderby_comment_ID = false;
+			foreach ( $ordersby as $_key => $_value ) {
+				if ( ! $_value ) {
+					continue;
+				}
+
+				if ( is_int( $_key ) ) {
+					$_orderby = $_value;
+					$_order = $order;
+				} else {
+					$_orderby = $_key;
+					$_order = $_value;
+				}
+
+				if ( ! $found_orderby_comment_ID && 'comment_ID' === $_orderby ) {
+					$found_orderby_comment_ID = true;
+				}
+
+				$parsed = $this->parse_orderby( $_orderby );
+
+				if ( ! $parsed ) {
+					continue;
+				}
+
+				$orderby_array[] = $parsed . ' ' . $this->parse_order( $_order );
+			}
+
+			// If no valid clauses were found, order by comment_date_gmt.
+			if ( empty( $orderby_array ) ) {
+				$orderby_array[] = "$wpdb->comments.comment_date_gmt $order";
 			}
-			$ordersby = array_intersect( $ordersby, $allowed_keys );
-			foreach ( $ordersby as $key => $value ) {
-				if ( $value == $this->query_vars['meta_key'] || $value == 'meta_value' ) {
-					$ordersby[ $key ] = "$wpdb->commentmeta.meta_value";
-				} elseif ( $value == 'meta_value_num' ) {
-					$ordersby[ $key ] = "$wpdb->commentmeta.meta_value+0";
+
+			// To ensure determinate sorting, always include a comment_ID clause.
+			if ( ! $found_orderby_comment_ID ) {
+				$comment_ID_order = '';
+
+				// Inherit order from comment_date or comment_date_gmt, if available.
+				foreach ( $orderby_array as $orderby_clause ) {
+					if ( preg_match( '/comment_date(?:_gmt)*\ (ASC|DESC)/', $orderby_clause, $match ) ) {
+						$comment_ID_order = $match[1];
+						break;
+					}
+				}
+
+				// If no date-related order is available, use the date from the first available clause.
+				if ( ! $comment_ID_order ) {
+					foreach ( $orderby_array as $orderby_clause ) {
+						if ( false !== strpos( 'ASC', $orderby_clause ) ) {
+							$comment_ID_order = 'ASC';
+						} else {
+							$comment_ID_order = 'DESC';
+						}
+
+						break;
+					}
 				}
+
+				// Default to DESC.
+				if ( ! $comment_ID_order ) {
+					$comment_ID_order = 'DESC';
+				}
+
+				$orderby_array[] = "$wpdb->comments.comment_ID $comment_ID_order";
 			}
-			$orderby = empty( $ordersby ) ? 'comment_date_gmt' : implode(', ', $ordersby);
+
+			$orderby = implode( ', ', $orderby_array );
 		} else {
-			$orderby = 'comment_date_gmt';
+			$orderby = "$wpdb->comments.comment_date_gmt $order";
 		}
 
 		$number = absint( $this->query_vars['number'] );
@@ -724,7 +760,7 @@ class WP_Comment_Query {
 
 		$where = implode( ' AND ', $where );
 
-		$pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits', 'groupby' );
+		$pieces = array( 'fields', 'join', 'where', 'orderby', 'limits', 'groupby' );
 		/**
 		 * Filter the comment query clauses.
 		 *
@@ -739,7 +775,6 @@ class WP_Comment_Query {
 		$join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : '';
 		$where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : '';
 		$orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : '';
-		$order = isset( $clauses[ 'order' ] ) ? $clauses[ 'order' ] : '';
 		$limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
 		$groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
 
@@ -752,7 +787,7 @@ class WP_Comment_Query {
 		}
 
 		if ( $orderby ) {
-			$orderby = "ORDER BY $orderby $order";
+			$orderby = "ORDER BY $orderby";
 		}
 
 		$this->request = "SELECT $fields FROM $wpdb->comments $join $where $groupby $orderby $limits";
@@ -804,6 +839,77 @@ class WP_Comment_Query {
 
 		return ' AND (' . implode(' OR ', $searches) . ')';
 	}
+
+	/**
+	 * Parse and sanitize 'orderby' keys passed to the comment query.
+	 *
+	 * @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|bool Value to used in the ORDER clause. False otherwise.
+	 */
+	protected function parse_orderby( $orderby ) {
+		global $wpdb;
+
+		$allowed_keys = array(
+			'comment_agent',
+			'comment_approved',
+			'comment_author',
+			'comment_author_email',
+			'comment_author_IP',
+			'comment_author_url',
+			'comment_content',
+			'comment_date',
+			'comment_date_gmt',
+			'comment_ID',
+			'comment_karma',
+			'comment_parent',
+			'comment_post_ID',
+			'comment_type',
+			'user_id',
+		);
+
+		if ( ! empty( $this->query_vars['meta_key'] ) ) {
+			$allowed_keys[] = $this->query_vars['meta_key'];
+			$allowed_keys[] = 'meta_value';
+			$allowed_keys[] = 'meta_value_num';
+		}
+
+		$parsed = false;
+		if ( $orderby == $this->query_vars['meta_key'] || $orderby == 'meta_value' ) {
+			$parsed = "$wpdb->commentmeta.meta_value";
+		} else if ( $orderby == 'meta_value_num' ) {
+			$parsed = "$wpdb->commentmeta.meta_value+0";
+		} else if ( in_array( $orderby, $allowed_keys ) ) {
+			$parsed = "$wpdb->comments.$orderby";
+		}
+
+		return $parsed;
+	}
+
+	/**
+	 * Parse an 'order' query variable and cast it to ASC or DESC as necessary.
+	 *
+	 * @since 4.2.0
+	 * @access protected
+	 *
+	 * @param string $order The 'order' query variable.
+	 * @return string The sanitized 'order' query variable.
+	 */
+	protected function parse_order( $order ) {
+		if ( ! is_string( $order ) || empty( $order ) ) {
+			return 'DESC';
+		}
+
+		if ( 'ASC' === strtoupper( $order ) ) {
+			return 'ASC';
+		} else {
+			return 'DESC';
+		}
+	}
 }
 
 /**
diff --git tests/phpunit/tests/comment/query.php tests/phpunit/tests/comment/query.php
index 3f56ee2..69c36e2 100644
--- tests/phpunit/tests/comment/query.php
+++ tests/phpunit/tests/comment/query.php
@@ -581,7 +581,9 @@ class Tests_Comment_Query extends WP_UnitTestCase {
 	 */
 	function test_orderby_meta() {
 		$comment_id = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id ) );
+		sleep( 1 );
 		$comment_id2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id ) );
+		sleep( 1 );
 		$comment_id3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id ) );
 
 		add_comment_meta( $comment_id, 'key', 'value1', true );
@@ -612,14 +614,10 @@ class Tests_Comment_Query extends WP_UnitTestCase {
 		$this->assertEquals( $comment_id2, $comments[1]->comment_ID );
 
 		$comments = get_comments( array( 'meta_value' => 'value3', 'orderby' => array( 'key' ) ) );
-		$this->assertEquals( 2, count( $comments ) );
-		$this->assertEquals( $comment_id, $comments[0]->comment_ID );
-		$this->assertEquals( $comment_id3, $comments[1]->comment_ID );
+		$this->assertEquals( array( $comment_id3, $comment_id ), wp_list_pluck( $comments, 'comment_ID' ) );
 
 		$comments = get_comments( array( 'meta_value' => 'value3', 'orderby' => array( 'meta_value' ) ) );
-		$this->assertEquals( 2, count( $comments ) );
-		$this->assertEquals( $comment_id, $comments[0]->comment_ID );
-		$this->assertEquals( $comment_id3, $comments[1]->comment_ID );
+		$this->assertEquals( array( $comment_id3, $comment_id ), wp_list_pluck( $comments, 'comment_ID' ) );
 
 		// value1 is present on two different keys for $comment_id yet we should get only one instance
 		// of that comment in the results
@@ -985,64 +983,78 @@ class Tests_Comment_Query extends WP_UnitTestCase {
 	}
 
 	public function test_orderby_default() {
+		global $wpdb;
+
 		$q = new WP_Comment_Query();
 		$q->query( array() );
 
-		$this->assertContains( 'ORDER BY comment_date_gmt', $q->request );
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_date_gmt", $q->request );
 	}
 
 	public function test_orderby_single() {
+		global $wpdb;
+
 		$q = new WP_Comment_Query();
 		$q->query( array(
 			'orderby' => 'comment_agent',
 		) );
 
-		$this->assertContains( 'ORDER BY comment_agent', $q->request );
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent", $q->request );
 	}
 
 	public function test_orderby_single_invalid() {
+		global $wpdb;
+
 		$q = new WP_Comment_Query();
 		$q->query( array(
 			'orderby' => 'foo',
 		) );
 
-		$this->assertContains( 'ORDER BY comment_date_gmt', $q->request );
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_date_gmt", $q->request );
 	}
 
 	public function test_orderby_comma_separated() {
+		global $wpdb;
+
 		$q = new WP_Comment_Query();
 		$q->query( array(
 			'orderby' => 'comment_agent, comment_approved',
 		) );
 
-		$this->assertContains( 'ORDER BY comment_agent, comment_approved', $q->request );
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_approved DESC", $q->request );
 	}
 
-	public function test_orderby_array() {
+	public function test_orderby_flat_array() {
+		global $wpdb;
+
 		$q = new WP_Comment_Query();
 		$q->query( array(
 			'orderby' => array( 'comment_agent', 'comment_approved' ),
 		) );
 
-		$this->assertContains( 'ORDER BY comment_agent, comment_approved', $q->request );
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_approved DESC", $q->request );
 	}
 
 	public function test_orderby_array_contains_invalid_item() {
+		global $wpdb;
+
 		$q = new WP_Comment_Query();
 		$q->query( array(
 			'orderby' => array( 'comment_agent', 'foo', 'comment_approved' ),
 		) );
 
-		$this->assertContains( 'ORDER BY comment_agent, comment_approved', $q->request );
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_approved DESC", $q->request );
 	}
 
 	public function test_orderby_array_contains_all_invalid_items() {
+		global $wpdb;
+
 		$q = new WP_Comment_Query();
 		$q->query( array(
 			'orderby' => array( 'foo', 'bar', 'baz' ),
 		) );
 
-		$this->assertContains( 'ORDER BY comment_date_gmt', $q->request );
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_date_gmt", $q->request );
 	}
 
 	/**
@@ -1081,6 +1093,158 @@ class Tests_Comment_Query extends WP_UnitTestCase {
 		$this->assertNotContains( 'ORDER BY', $q->request );
 	}
 
+	/**
+	 * @ticket 30478
+	 */
+	public function test_orderby_array() {
+		global $wpdb;
+
+		$q = new WP_Comment_Query();
+		$found = $q->query( array(
+			'fields' => 'ids',
+			'orderby' => array(
+				'comment_agent' => 'DESC',
+				'comment_date_gmt' => 'ASC',
+				'comment_ID' => 'DESC',
+			),
+		) );
+
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_date_gmt ASC, $wpdb->comments.comment_ID DESC", $q->request );
+	}
+
+	/**
+	 * @ticket 30478
+	 */
+	public function test_orderby_array_should_discard_invalid_columns() {
+		global $wpdb;
+
+		$q = new WP_Comment_Query();
+		$found = $q->query( array(
+			'fields' => 'ids',
+			'orderby' => array(
+				'comment_agent' => 'DESC',
+				'foo' => 'ASC',
+				'comment_ID' => 'DESC',
+			),
+		) );
+
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_ID DESC", $q->request );
+	}
+
+	/**
+	 * @ticket 30478
+	 */
+	public function test_orderby_array_should_convert_invalid_order_to_DESC() {
+		global $wpdb;
+
+		$q = new WP_Comment_Query();
+		$found = $q->query( array(
+			'fields' => 'ids',
+			'orderby' => array(
+				'comment_agent' => 'DESC',
+				'comment_date_gmt' => 'foo',
+				'comment_ID' => 'DESC',
+			),
+		) );
+
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_date_gmt DESC, $wpdb->comments.comment_ID DESC", $q->request );
+	}
+
+	/**
+	 * @ticket 30478
+	 */
+	public function test_orderby_array_should_sort_by_comment_ID_as_fallback_and_should_inherit_order_from_comment_date_gmt() {
+		global $wpdb;
+
+		$q = new WP_Comment_Query();
+		$found = $q->query( array(
+			'fields' => 'ids',
+			'orderby' => array(
+				'comment_agent' => 'DESC',
+				'comment_date_gmt' => 'ASC',
+			),
+		) );
+
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_date_gmt ASC, $wpdb->comments.comment_ID ASC", $q->request );
+	}
+
+	/**
+	 * @ticket 30478
+	 */
+	public function test_orderby_array_should_sort_by_comment_ID_as_fallback_and_should_inherit_order_from_comment_date() {
+		global $wpdb;
+
+		$q = new WP_Comment_Query();
+		$found = $q->query( array(
+			'fields' => 'ids',
+			'orderby' => array(
+				'comment_agent' => 'DESC',
+				'comment_date' => 'ASC',
+			),
+		) );
+
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_date ASC, $wpdb->comments.comment_ID ASC", $q->request );
+	}
+
+	/**
+	 * @ticket 30478
+	 */
+	public function test_orderby_array_should_sort_by_comment_ID_DESC_as_fallback_when_not_sorted_by_date() {
+		global $wpdb;
+
+		$q = new WP_Comment_Query();
+		$found = $q->query( array(
+			'fields' => 'ids',
+			'orderby' => array(
+				'comment_agent' => 'ASC',
+			),
+		) );
+
+		$this->assertContains( "ORDER BY $wpdb->comments.comment_agent ASC, $wpdb->comments.comment_ID DESC", $q->request );
+	}
+
+	/**
+	 * @ticket 30478
+	 */
+	public function test_orderby_date_modified_gmt_should_order_by_comment_ID_in_case_of_tie_ASC() {
+		$now = current_time( 'mysql', 1 );
+		$comments = $this->factory->comment->create_many( 5, array(
+			'comment_post_ID' => $this->post_id,
+			'comment_date_gmt' => $now,
+		) );
+
+		$q = new WP_Comment_Query();
+		$found = $q->query( array(
+			'orderby' => 'comment_date_gmt',
+			'order' => 'ASC',
+		) );
+
+		// $comments is ASC by default.
+		$this->assertEquals( $comments, wp_list_pluck( $found, 'comment_ID' ) );
+	}
+
+	/**
+	 * @ticket 30478
+	 */
+	public function test_orderby_date_modified_gmt_should_order_by_comment_ID_in_case_of_tie_DESC() {
+		$now = current_time( 'mysql', 1 );
+		$comments = $this->factory->comment->create_many( 5, array(
+			'comment_post_ID' => $this->post_id,
+			'comment_date_gmt' => $now,
+		) );
+
+		$q = new WP_Comment_Query();
+		$found = $q->query( array(
+			'orderby' => 'comment_date_gmt',
+			'order' => 'DESC',
+		) );
+
+		// $comments is ASC by default.
+		rsort( $comments );
+
+		$this->assertEquals( $comments, wp_list_pluck( $found, 'comment_ID' ) );
+	}
+
 	public function test_count() {
 		$c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7 ) );
 		$c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7 ) );
