Page MenuHomePhabricator

Slow API list=recentchanges query (DBError: Lost connection to MySQL server during query)
Closed, ResolvedPublic

Description

Occurring three times (two retries), recentchanges in PHP raised DBQueryError. This was a few builds ago, yesterday, and hasnt reoccurred since.

requests.packages.urllib3.connectionpool: DEBUG: "GET /w/api.php?rcprop=user%7Ccomment%7Ctimestamp%7Ctitle%7Cids%7Csizes%7Credirect%7Cloginfo%7Cflags&maxlag=5&format=json&rclimit=5&list=recentchanges&rcnamespace=6%7C7&rcshow=&continue=&meta=userinfo&indexpageids=&action=query&uiprop=blockinfo%7Chasmsg HTTP/1.1" 200 117
pywiki: ERROR: Detected MediaWiki API exception DBQueryError; retrying
pywiki: VERBOSE: MediaWiki exception DBQueryError details:
          query=
{u'action': [u'query'],
 u'continue': [True],
 u'format': [u'json'],
 u'indexpageids': [True],
 'list': [u'recentchanges'],
 u'maxlag': ['5'],
 u'meta': [u'userinfo'],
 u'rclimit': [u'5'],
 u'rcnamespace': [6, 7],
 'rcprop': [u'user',
            u'comment',
            u'timestamp',
            u'title',
            u'ids',
            u'sizes',
            u'redirect',
            u'loginfo',
            u'flags'],
 u'rcshow': <pywikibot.data.api.OptionSet object at 0x5570910>,
 'rctoponly': [False],
 u'uiprop': [u'blockinfo', u'hasmsg']}
          response=
{u'servedby': u'mw1130', u'error': {u'info': u'[bfd910ab] Database query error', u'code': u'internal_api_error_DBQueryError'}}
pywiki: WARNING: Waiting 5 seconds before retrying.
requests.packages.urllib3.connectionpool: DEBUG: "GET /w/api.php?rcprop=user%7Ccomment%7Ctimestamp%7Ctitle%7Cids%7Csizes%7Credirect%7Cloginfo%7Cflags&maxlag=5&format=json&rclimit=5&list=recentchanges&rcnamespace=6%7C7&rcshow=&continue=&meta=userinfo&indexpageids=&action=query&uiprop=blockinfo%7Chasmsg HTTP/1.1" 200 118
pywiki: ERROR: Detected MediaWiki API exception DBQueryError; retrying
pywiki: VERBOSE: MediaWiki exception DBQueryError details:
          query=
{u'action': [u'query'],
 u'continue': [True],
 u'format': [u'json'],
 u'indexpageids': [True],
 'list': [u'recentchanges'],
 u'maxlag': ['5'],
 u'meta': [u'userinfo'],
 u'rclimit': [u'5'],
 u'rcnamespace': [6, 7],
 'rcprop': [u'user',
            u'comment',
            u'timestamp',
            u'title',
            u'ids',
            u'sizes',
            u'redirect',
            u'loginfo',
            u'flags'],
 u'rcshow': <pywikibot.data.api.OptionSet object at 0x5570910>,
 'rctoponly': [False],
 u'uiprop': [u'blockinfo', u'hasmsg']}
          response=
{u'servedby': u'mw1148', u'error': {u'info': u'[8ae26643] Database query error', u'code': u'internal_api_error_DBQueryError'}}
pywiki: WARNING: Waiting 10 seconds before retrying.
requests.packages.urllib3.connectionpool: DEBUG: "GET /w/api.php?rcprop=user%7Ccomment%7Ctimestamp%7Ctitle%7Cids%7Csizes%7Credirect%7Cloginfo%7Cflags&maxlag=5&format=json&rclimit=5&list=recentchanges&rcnamespace=6%7C7&rcshow=&continue=&meta=userinfo&indexpageids=&action=query&uiprop=blockinfo%7Chasmsg HTTP/1.1" 200 118
pywiki: ERROR: Detected MediaWiki API exception DBQueryError; retrying
pywiki: VERBOSE: MediaWiki exception DBQueryError details:
          query=
{u'action': [u'query'],
 u'continue': [True],
 u'format': [u'json'],
 u'indexpageids': [True],
 'list': [u'recentchanges'],
 u'maxlag': ['5'],
 u'meta': [u'userinfo'],
 u'rclimit': [u'5'],
 u'rcnamespace': [6, 7],
 'rcprop': [u'user',
            u'comment',
            u'timestamp',
            u'title',
            u'ids',
            u'sizes',
            u'redirect',
            u'loginfo',
            u'flags'],
 u'rcshow': <pywikibot.data.api.OptionSet object at 0x5570910>,
 'rctoponly': [False],
 u'uiprop': [u'blockinfo', u'hasmsg']}
          response=
{u'servedby': u'mw1235', u'error': {u'info': u'[16606b61] Database query error', u'code': u'internal_api_error_DBQueryError'}}

https://travis-ci.org/wikimedia/pywikibot-core/jobs/65289168#L1518

Event Timeline

jayvdb raised the priority of this task from to Needs Triage.
jayvdb updated the task description. (Show Details)
jayvdb subscribed.
Restricted Application added subscribers: Aklapper, Unknown Object (MLST). · View Herald TranscriptJun 5 2015, 10:28 AM
Anomie subscribed.

The three logged exceptions all look like this:

2015-06-03 19:36:26 mw1148 wikidatawiki exception INFO: [8ae26643] /w/api.php?rcprop=user%7Ccomment%7Ctimestamp%7Ctitle%7Cids%7Csizes%7Credirect%7Cloginfo%7Cflags&maxlag=5&format=json&rclimit=5&list=recentchanges&rcnamespace=6%7C7&rcshow=&continue=&meta=userinfo&indexpageids=&action=query&uiprop=blockinfo%7Chasmsg   DBQueryError from line 1276 of /srv/mediawiki/php-1.26wmf8/includes/db/Database.php: A database error has occurred. Did you forget to run maintenance/update.php after upgrading?  See: https://www.mediawiki.org/wiki/Manual:Upgrading#Run_the_update_script
Query: SELECT  rc_id,rc_timestamp,rc_namespace,rc_title,rc_cur_id,rc_type,rc_deleted,rc_this_oldid,rc_last_oldid,rc_comment,rc_user,rc_user_text,rc_minor,rc_type,rc_bot,rc_old_len,rc_new_len,rc_logid,rc_log_type,rc_log_action,rc_params,page_is_redirect  FROM `recentchanges` FORCE INDEX (rc_timestamp) LEFT JOIN `page` ON ((rc_namespace=page_namespace) AND (rc_title=page_title))  WHERE rc_namespace IN ('6','7')  AND rc_type IN ('0','1','3')   ORDER BY rc_timestamp DESC,rc_id DESC LIMIT 6  
Function: ApiQueryRecentChanges::run
Error: 2013 Lost connection to MySQL server during query (10.64.16.144)

#0 /srv/mediawiki/php-1.26wmf8/includes/db/Database.php(1214): DatabaseBase->reportQueryError()
#1 /srv/mediawiki/php-1.26wmf8/includes/db/Database.php(1756): DatabaseBase->query()
#2 /srv/mediawiki/php-1.26wmf8/includes/api/ApiQueryBase.php(376): DatabaseBase->select()
#3 /srv/mediawiki/php-1.26wmf8/includes/api/ApiQueryRecentChanges.php(367): ApiQueryBase->select()
#4 /srv/mediawiki/php-1.26wmf8/includes/api/ApiQueryRecentChanges.php(131): ApiQueryRecentChanges->run()
#5 /srv/mediawiki/php-1.26wmf8/includes/api/ApiQuery.php(286): ApiQueryRecentChanges->execute()
#6 /srv/mediawiki/php-1.26wmf8/includes/api/ApiMain.php(1131): ApiQuery->execute()
#7 /srv/mediawiki/php-1.26wmf8/includes/api/ApiMain.php(469): ApiMain->executeAction()
#8 /srv/mediawiki/php-1.26wmf8/includes/api/ApiMain.php(442): ApiMain->executeActionWithErrorHandling()
#9 /srv/mediawiki/php-1.26wmf8/api.php(88): ApiMain->execute()
#10 /srv/mediawiki/w/api.php(3): include()
#11 {main} {"private":false}

The "Lost connection to MySQL server during query" usually indicates that the query was taking too long to run and was killed. For this particular query it looks like it was having to scan the whole recentchanges table (around 6.7 million rows, looks like) to find out that there aren't any rows for namespaces 6 or 7.

Chances are we should just kill the "FORCE INDEX" in that query and let the database guess when a filesort would make sense, but I'd want to hear from our DBAs before just doing it. The queries here will always be ordering by rc_timestamp,rc_id, and for WHERE:

  • will usually have an IN on rc_type (possibly rc_source in the future, see discussion on Gerrit 213472),
  • could have an IN on rc_namespace, as shown here
  • could have a range on rc_timestamp (<= X, >= X, or both),
  • could have "rc_timestamp < X OR (rc_timestamp = X AND rc_id <= Y)" (or >; in either case it matches the direction of the order by),
  • could have testing of various rc_minor/rc_bot/rc_patrolled/rc_user being = or != 0,
  • could have rc_user_text = X or != X
  • could have rc_this_oldid = page_latest
  • could have a join with change_tag with an IN on ct_tag
  • could have a test for "(rc_deleted & X) != X"

Yes, for this particular case (machine, table and parameters), not using a FORCE INDEX will be better:

With FORCE:

mysql> EXPLAIN SELECT  rc_id,rc_timestamp,rc_namespace,rc_title,rc_cur_id,rc_type,rc_deleted,rc_this_oldid,rc_last_oldid,rc_comment,rc_user,rc_user_text,rc_minor,rc_type,rc_bot,rc_old_len,rc_new_len,rc_logid,rc_log_type,rc_log_action,rc_params,page_is_redirect  FROM `recentchanges` FORCE INDEX (rc_timestamp) LEFT JOIN `page` ON ((rc_namespace=page_namespace) AND (rc_title=page_title))  WHERE rc_namespace IN ('6','7')  AND rc_type IN ('0','1','3')   ORDER BY rc_timestamp DESC,rc_id DESC LIMIT 6\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: recentchanges
         type: index
possible_keys: NULL
          key: rc_timestamp
      key_len: 16
          ref: NULL
         rows: 6
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: page
         type: eq_ref
possible_keys: name_title
          key: name_title
      key_len: 261
          ref: wikidatawiki.recentchanges.rc_namespace,wikidatawiki.recentchanges.rc_title
         rows: 1
        Extra: 
2 rows in set (0.02 sec)

Execution time:
Empty set (20.50 sec)

PAGER set to stdout
+----------------------------+---------+
| Variable_name              | Value   |
+----------------------------+---------+
| Handler_commit             | 1       |
| Handler_delete             | 0       |
| Handler_discover           | 0       |
| Handler_external_lock      | 0       |
| Handler_icp_attempts       | 0       |
| Handler_icp_match          | 0       |
| Handler_mrr_init           | 0       |
| Handler_mrr_key_refills    | 0       |
| Handler_mrr_rowid_refills  | 0       |
| Handler_prepare            | 0       |
| Handler_read_first         | 0       |
| Handler_read_key           | 0       |
| Handler_read_last          | 1       |
| Handler_read_next          | 0       |
| Handler_read_prev          | 6847234 |
| Handler_read_rnd           | 0       |
| Handler_read_rnd_deleted   | 0       |
| Handler_read_rnd_next      | 0       |
| Handler_rollback           | 0       |
| Handler_savepoint          | 0       |
| Handler_savepoint_rollback | 0       |
| Handler_tmp_update         | 0       |
| Handler_tmp_write          | 0       |
| Handler_update             | 0       |
| Handler_write              | 0       |
+----------------------------+---------+
25 rows in set (0.00 sec)

mysql> SHOW PROFILE FOR QUERY 2;
+----------------------+-----------+
| Status               | Duration  |
+----------------------+-----------+
| starting             |  0.000133 |
| checking permissions |  0.000009 |
| checking permissions |  0.000007 |
| Opening tables       |  0.000023 |
| After opening tables |  0.000010 |
| System lock          |  0.000008 |
| Table lock           |  0.000066 |
| After table lock     |  0.000009 |
| init                 |  0.000050 |
| optimizing           |  0.000021 |
| statistics           |  0.000034 |
| preparing            |  0.000034 |
| executing            |  0.000007 |
| Sorting result       |  0.000010 |
| Sending data         | 22.417293 |
| end                  |  0.000028 |
| query end            |  0.000013 |
| closing tables       |  0.000029 |
| freeing items        |  0.000017 |
| updating status      |  0.000033 |
| logging slow query   |  0.000014 |
| cleaning up          |  0.000012 |
+----------------------+-----------+
22 rows in set (0.00 sec)

Without force:

mysql> EXPLAIN SELECT  rc_id,rc_timestamp,rc_namespace,rc_title,rc_cur_id,rc_type,rc_deleted,rc_this_oldid,rc_last_oldid,rc_comment,rc_user,rc_user_text,rc_minor,rc_type,rc_bot,rc_old_len,rc_new_len,rc_logid,rc_log_type,rc_log_action,rc_params,page_is_redirect  FROM `recentchanges` LEFT JOIN `page` ON ((rc_namespace=page_namespace) AND (rc_title=page_title))  WHERE rc_namespace IN ('6','7')  AND rc_type IN ('0','1','3')   ORDER BY rc_timestamp DESC,rc_id DESC LIMIT 6\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: recentchanges
         type: range
possible_keys: rc_namespace_title,rc_ns_usertext,tmp_3
          key: rc_namespace_title
      key_len: 4
          ref: NULL
         rows: 2
        Extra: Using index condition; Using where; Using filesort
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: page
         type: eq_ref
possible_keys: name_title
          key: name_title
      key_len: 261
          ref: wikidatawiki.recentchanges.rc_namespace,wikidatawiki.recentchanges.rc_title
         rows: 1
        Extra: 
2 rows in set (0.15 sec)

Execution time:
Empty set (0.00 sec)

PAGER set to stdout
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Handler_commit             | 1     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_external_lock      | 0     |
| Handler_icp_attempts       | 0     |
| Handler_icp_match          | 0     |
| Handler_mrr_init           | 0     |
| Handler_mrr_key_refills    | 0     |
| Handler_mrr_rowid_refills  | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 0     |
| Handler_read_key           | 2     |
| Handler_read_last          | 0     |
| Handler_read_next          | 0     |
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_deleted   | 0     |
| Handler_read_rnd_next      | 0     |
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_tmp_update         | 0     |
| Handler_tmp_write          | 0     |
| Handler_update             | 0     |
| Handler_write              | 0     |
+----------------------------+-------+
25 rows in set (0.00 sec)

mysql> SHOW PROFILE FOR QUERY 6;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000127 |
| checking permissions | 0.000010 |
| checking permissions | 0.000008 |
| Opening tables       | 0.000037 |
| After opening tables | 0.000011 |
| System lock          | 0.000009 |
| Table lock           | 0.000009 |
| After table lock     | 0.000010 |
| init                 | 0.000059 |
| optimizing           | 0.000025 |
| statistics           | 0.000126 |
| preparing            | 0.000043 |
| executing            | 0.000009 |
| Sorting result       | 0.000046 |
| Sending data         | 0.000040 |
| end                  | 0.000010 |
| query end            | 0.000012 |
| closing tables       | 0.000013 |
| freeing items        | 0.000012 |
| updating status      | 0.000033 |
| cleaning up          | 0.000009 |
+----------------------+----------+
21 rows in set (0.00 sec)

However, are you sure it wouldn't affect the same query with other parameters (edge cases)?

Maybe it is needed in 5.5 but not in 10/5.6. Maybe it is needed when page sampling is wrong. FORCE index is a (sometimes necessary) evil, due usually to the lack of documentation of why it was set there.

My point of view would be to prove it statistically- set one of our machines with a proposed change and use pt-query-digest (example output) or performance_schema to prove it is better overall and with no regression in a controlled environment, over a long period of time.

We are trying to improve the process on our side to better help you with this, too.

hashar triaged this task as Medium priority.Jun 8 2015, 8:29 AM
hashar subscribed.

Thanks, @hoo for the merge.

To advance on this:

Can someone with a full understanding of the code provide a smallish, but very representative list of different queries that could be generated from that piece of code (different namespaces, different wikis, different sizes, different parameters)? That way we can validate the patch on all the servers, and if a 100% upgrade to a version MySQL >5.5 will be a blocker.

Krinkle renamed this task from recentchanges internal_api_error_DBQueryError to Slow API list=recentchanges query (DBError: Lost connection to MySQL server during query).Jun 24 2015, 8:34 PM
Krinkle set Security to None.

This has failed on 18 of the last 25 builds I've seen in the last 6 days, after becoming slowly more frequently in the week prior. Here they are in inverse order:

https://travis-ci.org/jayvdb/pywikibot-core/jobs/71872055#L1253 - not ok
https://travis-ci.org/jayvdb/pywikibot-core/jobs/71869416#L1255 - not ok

https://travis-ci.org/wikimedia/pywikibot-core/jobs/71649611#L1253 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71648662#L1249 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71647928#L1249 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71637810#L1249 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71636530#L1249 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71626597#L1249 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71537433#L1249 - not ok

https://travis-ci.org/wikimedia/pywikibot-core/builds/71651589 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/71650083 - ok

https://travis-ci.org/wikimedia/pywikibot-core/jobs/71781512#L1253 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71780736#L1253 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71753694#L1253 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71654242#L1253 - not ok

https://travis-ci.org/wikimedia/pywikibot-core/builds/71443564 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/71366667 - ok

https://travis-ci.org/wikimedia/pywikibot-core/jobs/71360256#L1304 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71291166#L1304 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71288396#L1304 - not ok
https://travis-ci.org/wikimedia/pywikibot-core/jobs/71239103#L1304 - not ok

https://travis-ci.org/wikimedia/pywikibot-core/builds/71229217 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/71060535 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/71055039 - ok

https://travis-ci.org/wikimedia/pywikibot-core/jobs/71050946#L2444 - not ok


Earlier:

https://travis-ci.org/wikimedia/pywikibot-core/builds/71018727 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/71016382 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/71009193 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70927259 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70927169 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70926431 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70911329 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70905004 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70875982 - ok

https://travis-ci.org/wikimedia/pywikibot-core/jobs/70826732#L1999 - not ok

https://travis-ci.org/wikimedia/pywikibot-core/builds/70802539 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70729439 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70719399 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70636952 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70593073 - ok
https://travis-ci.org/wikimedia/pywikibot-core/builds/70539255 - ok

https://travis-ci.org/wikimedia/pywikibot-core/jobs/70510077#L1982 - not ok

Change 226057 had a related patch set uploaded (by John Vandenberg):
Disable on part of testRecentChanges on wikidata

https://gerrit.wikimedia.org/r/226057

This has probably has aggravated due to all slaves being upgraded recently to newer versions (@Springle?), but I am still blocked by T101502#1396381.

Change 226057 merged by jenkins-bot:
Disable a part of testRecentChanges on wikidata

https://gerrit.wikimedia.org/r/226057

Due to https://gerrit.wikimedia.org/r/226057, the pywikibot test framework wont be tracking this problem on wikidata. It will still see the problem if it occurs on other wikis. I expect that it could happen on any of the (many) other Wikimedia wikis which have a policy of only using files hosted on Wikimedia Commons. e.g. Czech WP Special:ListFiles lists only one file.

As the failing query uses rcnamespace=6|7, it might be an unusual edge case. However if the same query with only rcnamespace=6 also fails badly, regularly, and the FORCE INDEX suggests it might, then this bug is also affecting more typical usage of the API.

However, the problem may also be unique to Wikidata, as it has a very large RC feed which is likely to be an aggravating factor in the performance of the query.

Can the ops team identify how frequently this exception is happening? Has it started occurring more frequently in the last week? On very active wikis with very few files?

I am wrong about frequency, a search on logstash shows the following statistics:

  • 37 mediawiki-related DB errors containing ApiQueryRecentChanges::run, in the last 7 days
  • 30 on wikidatawiki and 7 on enwiki

In comparison, other errors -with a similar patern, where they seem to be killed due to running for a long time- are more worrying (but still low in numbers):

  • 500 mediawiki-related DB errors contaning ApiQueryRevisions::run in the last 7 days
  • Happening only at dewiki

If the error happens every time it is still something to solve, but it may not be so urgent (there are other more frequent API-related errors).

Can someone with a full understanding of the code provide a smallish, but very representative list of different queries that could be generated from that piece of code (different namespaces, different wikis, different sizes, different parameters)?

There aren't really a smallish but very representative set of queries. As stated in T101502#1341361, there are several different pieces that could wind up in the WHERE portion ANDed together, which the client effectively selects independently. And the queries could be on any wiki, of course. I have no idea which combinations might be most prevalent.

Here's a bit lower-level of a layout of the possibilities:

SELECT  rc_id,rc_timestamp,rc_namespace,rc_title,rc_cur_id,rc_type,rc_deleted,rc_this_oldid,rc_last_oldid,rc_comment,rc_user,rc_user_text,rc_minor,rc_type,rc_bot,rc_old_len,rc_new_len,rc_logid,rc_log_type,rc_log_action,rc_params,page_is_redirect  FROM `recentchanges` FORCE INDEX (rc_timestamp) LEFT JOIN `page` ON ((rc_namespace=page_namespace) AND (rc_title=page_title)) 

 -- rc_type will usually be like this. I don't think it'll ever be omitted, but could include all known types.
 WHERE rc_type IN ('0','1','3')
 -- rc_namespace could have anywhere from one namespace to all of them, or this might be omitted entirely.
 -- The bit after the AND might be omitted, although that should be relatively rare when rc_namespace isn't also omitted.
 WHERE rc_namespace IN ('0','1') AND (rc_type != 3 OR (rc_deleted & 1) != 1)
 -- This sort of thing comes from continuation, and i'd guess would be fairly common.
 WHERE rc_timestamp < '20150101000000' OR (rc_timestamp = '20150101000000' AND rc_id <= 123456)
 -- Ranges on rc_timestamp are possible.
 WHERE rc_timestamp <= '20150101000000'
 WHERE rc_timestamp >= '20140101000000'
 WHERE rc_timestamp <= '20150101000000' AND rc_timestamp >= '20140101000000'
 -- Any of these might be included (in any combination), each as = 0 or != 0.
 WHERE rc_minor = 0
 WHERE rc_bot = 0
 WHERE rc_patrolled = 0
 WHERE rc_user = 0
 -- Can test for a user, by name. The rc_deleted bit might be omitted, but that'd be uncommon.
 WHERE rc_user_text = 'Example' AND (rc_deleted & 4) != 4
 WHERE rc_user_text != 'Example' AND (rc_deleted & 4) != 4
 -- Might include this.
 WHERE rc_this_oldid = page_latest
 -- Might even include this.
 INNER JOIN change_tag ON (rc_id=ct_rc_id)
 WHERE ct_tag IN ('...')

 -- LIMIT could be anything from 2 to 5001. Ordering could be ASC.
 ORDER BY rc_timestamp DESC,rc_id DESC LIMIT 6

@Anomie This is better than nothing :-) , with this at least I can do some informal testing, thank you for taking the time!

Krinkle subscribed.

[This task] seems focused around the index forcing which was removed with rMW2f1cfcf306bb: API: Remove index forcing in ApiQueryRecentChanges.

Closing in favour of T149077.