data consistency RDS MySQLMySQL for RDS and DBaaS, in general, are very controlled environments by the vendors, meaning that there are missing things like a SUPER grant for the root user (and any user in general). This has some implications on operations, one of them being the impossibility of running pt-table-checksum to verify data consistency between a primary and its replicas.

However, there’s a workaround that might overcome this situation and involves three things:

  • The pt-table-checksum itself
  • A way to collect executed queries
  • And the last one, which can be controversial, is to remove the read-only from the replica and use a maintenance window to stop traffic to the database while pt-table-checksum runs.

The problem with RDS is that you cannot change binlog_format to STATEMENT, which is one of the requirements for pt-table-checksum to run.

The workaround consists of capturing the executed queries and replay it them in the replica. There are several ways to collect the queries: one can be using the Performance Schema in a similar way as explained in this blog post. Another one is just using the slow log with long_query_time = 0. By default on RDS the log output is set to TABLE so with a simple query against mysql.slow_log you can get the queries. Another option that we prefer to avoid is to use pt-query-digest processlist feature since it might lose capturing some queries.

Queries look like this:

The next step is to send those queries to the replicas as soon as possible so we can somehow guarantee that the point in time for comparison is the same for tables on both primary and secondary. And that’s the reason why one needs to change the read-only value in the replicas to 0. A change that can be rollbacked immediately after the pt-table-checksum process ends.

The Proof of Concept

I have created an RDS primary/secondary environment and have added a table with inconsistency on purpose.

Primary values:

And replica values:

Can you spot the difference :)? It’s the last row. While on the Primary the string_field says “pepe” in the replica it says “papa”.

So are we ready to run pt-table-checksum? Not quite. The tool will complain about not being able to change the binlog_format and it will end the execution. Unfortunately, currently, there’s no way to avoid that other than modifying the code. The change is to add a return to the following conditional:

With the return:

In pt-table-checksum version 3.2.1, that is in the line 10181:
https://github.com/percona/percona-toolkit/blob/release-3.2.1/bin/pt-table-checksum#L10181

Now we are ready! Let’s see if we can find out that difference using the tools. To send the queries to the replicas, execute the queries previously captured.

And finally, the actual pt-table-checksum command:

The output won’t report any difference and is expected to happen like that, so don’t panic. So, how do we check the reality? By querying the checksums table in the replica:

See the difference? It is the chunk number 3, the “this_crc” and “master_crc” are different. It’s hard to spot, right? Let’s try with some filters to the query:

There you go, data inconsistency detected.

Working with MySQL 8.0? There’s an even easier way to check data consistency!

Fine print

Some things to consider:

  • Replicas should be up to date – If there’s a lag between primary and secondary you would get false negatives.
  • The read-only itself: it’s kind of ironic that to check data consistency you have to disable the one thing that guarantees data consistency. However, it is temporary, and it is highly important to revert to read-only=on once the process is done.
  • Traffic to the database must be stopped in order to guarantee 100% that the data that we are checking is in the same point-in-time, meaning: no changes happened in between.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
greenlion

Can pt-q-d read from P_S.threads? SHOW PROCESSLIST holds a mutex…