{"id":3512,"date":"2025-11-04T11:45:00","date_gmt":"2025-11-04T11:45:00","guid":{"rendered":"https:\/\/kedar.nitty-witty.com\/blog\/?p=3512"},"modified":"2025-11-04T11:43:07","modified_gmt":"2025-11-04T11:43:07","slug":"how-to-checksum-on-aws-rds-for-mysql-replication-8-0-8-4","status":"publish","type":"post","link":"https:\/\/kedar.nitty-witty.com\/blog\/how-to-checksum-on-aws-rds-for-mysql-replication-8-0-8-4","title":{"rendered":"How to checksum on AWS RDS for MySQL Replication 8.0 > 8.4"},"content":{"rendered":"\n<p>During a MySQL upgrade process the <strong>RDS replication between MySQL 8.0 and 8.4<\/strong> was configured. I wanted to ensure the data was consistent for any random reason. This post is a quick work-log of how I tested and validated consistency using <strong>Percona Toolkit<\/strong>&#8216;s pt-table-checksum. And yes it is possible to perform checksum on AWS RDS.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"environment-setup\">Environment Setup<\/h2>\n\n\n\n<p>mysql80.kedarnittywitty.rds.amazonaws.com &#8211; MySQL 8.0<br>mysql84.kedarnittywitty.rds.amazonaws.com &#8211; MySQL 8.4<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img data-dominant-color=\"212121\" data-has-transparency=\"true\" style=\"--dominant-color: #212121;\" decoding=\"async\" width=\"912\" height=\"133\" src=\"https:\/\/kedar.nitty-witty.com\/blog\/wp-content\/uploads\/2025\/09\/image.avif\" alt=\"\" class=\"wp-image-3513 has-transparency\" srcset=\"https:\/\/kedar.nitty-witty.com\/blog\/wp-content\/uploads\/2025\/09\/image.avif 912w, https:\/\/kedar.nitty-witty.com\/blog\/wp-content\/uploads\/2025\/09\/image-300x44.avif 300w, https:\/\/kedar.nitty-witty.com\/blog\/wp-content\/uploads\/2025\/09\/image-768x112.avif 768w, https:\/\/kedar.nitty-witty.com\/blog\/wp-content\/uploads\/2025\/09\/image-390x57.avif 390w, https:\/\/kedar.nitty-witty.com\/blog\/wp-content\/uploads\/2025\/09\/image-820x120.avif 820w\" sizes=\"(max-width: 912px) 100vw, 912px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-1-configure-replication\">Replication configuration<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\"># mysql -hmysql80.kedarnittywitty.rds.amazonaws.com<br>...<br>Server version: 8.0.42 Source distribution<br>...<br>mysql&gt; CREATE USER IF NOT EXISTS 'repl_user'@'%' IDENTIFIED BY 'password';<br>Query OK, 0 rows affected (0.22 sec)<br><br>mysql&gt; GRANT REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO 'repl_user'@'%';<br>Query OK, 0 rows affected (0.22 sec)<br><br><br>mysql&gt; show binary logs;<br>+----------------------------+-----------+-----------+<br>| Log_name                   | File_size | Encrypted |<br>+----------------------------+-----------+-----------+<br>| mysql-bin-changelog.000001 |      1520 | No        |<br>| mysql-bin-changelog.000002 |       600 | No        |<br>| mysql-bin-changelog.000003 |       694 | No        |<br>+----------------------------+-----------+-----------+<code><br><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Setup Replica Using RDS Procedures<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\"><br>mysql&gt; CALL mysql.rds_set_external_source ('mysql80.kedarnittywitty1.rds.amazonaws.com', 3306, 'repl_user', 'password', 'mysql-bin-changelog.000003', '4', 0);<br>Query OK, 0 rows affected (0.25 sec)<br><br>mysql&gt; CALL mysql.rds_start_replication;<br>+-----------------------------------------------------------+<br>| Message                                                   |<br>+-----------------------------------------------------------+<br>| Replication started. Replication is now running normally. |<br>+-----------------------------------------------------------+<br>1 row in set (3.25 sec)<br><br>Query OK, 0 rows affected (3.25 sec)<br><br>mysql&gt; SHOW REPLICA STATUS\\G<br>*************************** 1. row ***************************<br>             Replica_IO_State: Waiting for master to send event<br>                  Source_Host: mysql80.kedarnittywitty.rds.amazonaws.com<br>                  Source_User: repl_user<br>                  Source_Port: 3306<br>                Connect_Retry: 60<br>              Source_Log_File: mysql-bin-changelog.000004<br>          Read_Source_Log_Pos: 544<br>               Relay_Log_File: relaylog.000004<br>                Relay_Log_Pos: 781<br>        Relay_Source_Log_File: mysql-bin-changelog.000004<br>           Replica_IO_Running: Yes<br>          Replica_SQL_Running: Yes<br>              Replicate_Do_DB:<br>          Replicate_Ignore_DB:<br>           Replicate_Do_Table:<br>       Replicate_Ignore_Table: innodb_memcache.cache_policies,innodb_memcache.config_options,mysql.plugin,mysql.rds_configuration,mysql.rds_history,mysql.rds_monitor,mysql.rds_replication_status,mysql.rds_sysinfo,mysql.rds_upgrade_prechecks<br>      Replicate_Wild_Do_Table:<br>  Replicate_Wild_Ignore_Table:<br>                   Last_Errno: 0<br>                   Last_Error:<br>                 Skip_Counter: 0<br>          Exec_Source_Log_Pos: 544<br>              Relay_Log_Space: 1042<br>              Until_Condition: None<br>               Until_Log_File:<br>                Until_Log_Pos: 0<br>           Source_SSL_Allowed: No<br>           Source_SSL_CA_File:<br>           Source_SSL_CA_Path:<br>              Source_SSL_Cert:<br>            Source_SSL_Cipher:<br>               Source_SSL_Key:<br>        Seconds_Behind_Source: 0<br>Source_SSL_Verify_Server_Cert: No<br>                Last_IO_Errno: 0<br>                Last_IO_Error:<br>               Last_SQL_Errno: 0<br>               Last_SQL_Error:<br>  Replicate_Ignore_Server_Ids:<br>             Source_Server_Id: 1813606236<br>                  Source_UUID: 53d56fdd-823f-11f0-a05d-0271b16d16ab<br>             Source_Info_File: mysql.slave_source_info<br>                    SQL_Delay: 0<br>          SQL_Remaining_Delay: NULL<br>    Replica_SQL_Running_State: Slave has read all relay log; waiting for more updates<br>           Source_Retry_Count: 86400<br>                  Source_Bind:<br>      Last_IO_Error_Timestamp:<br>     Last_SQL_Error_Timestamp:<br>               Source_SSL_Crl:<br>           Source_SSL_Crlpath:<br>           Retrieved_Gtid_Set:<br>            Executed_Gtid_Set:<br>                Auto_Position: 0<br>         Replicate_Rewrite_DB:<br>                 Channel_Name:<br>           Source_TLS_Version:<br>       Source_public_key_path:<br>        Get_Source_public_key: 0<br>            Network_Namespace:<br>1 row in set (0.21 sec)<code><br><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-2-prepare-test-data\">Create Test Database and Table<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">mysql -hmysql80.kedarnittywitty.rds.amazonaws.com<br><br>mysql&gt; create database checksum_rds;<br>Query OK, 1 row affected (0.22 sec)<br><br>mysql&gt; use checksum_rds;<br>Database changed<br>mysql&gt; create table pttablechecksum (<br>    -&gt; id int not null auto_increment primary key,<br>    -&gt; val varchar(10) ) engine=innodb;<br>Query OK, 0 rows affected (0.24 sec)<br><br>mysql&gt; insert into pttablechecksum values (null,'a'), (null,'a'), (null,'a'), (null,'a'), (null,'a'), (null,'a'), (null,'a'), (null,'a'), (null,'a');<br>Query OK, 1 row affected (0.21 sec)<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-3-create-data-inconsistency\">Create Data Inconsistency<\/h2>\n\n\n\n<p><strong>Simulate drift<\/strong> by manually modifying replica data:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">mysql -hmysql84.kedarnittywitty.rds.amazonaws.com<br><br>mysql&gt; use checksum_rds;<br>Reading table information for completion of table and column names<br>You can turn off this feature to get a quicker startup with -A<br><br>mysql&gt; show tables;<br>+------------------------+<br>| Tables_in_checksum_rds |<br>+------------------------+<br>| pttablechecksum        |<br>+------------------------+<br>1 row in set (0.31 sec)<br><br>mysql&gt; select count(*) from pttablechecksum;<br>+----------+<br>| count(*) |<br>+----------+<br>|        9 |<br>+----------+<br>1 row in set (0.22 sec)<br><br>mysql&gt; delete from pttablechecksum where id=8;<br>Query OK, 1 row affected (0.27 sec)<code><br><\/code><\/pre>\n\n\n\n<p><strong>Verify Divergence:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">root@nitty-witty:~# mysql  -hmysql80.kedarnittywitty.rds.amazonaws.com -e \"select * from checksum_rds.pttablechecksum\"<br>+----+------+<br>| id | val  |<br>+----+------+<br>|  1 | a    |<br>|  2 | a    |<br>|  3 | a    |<br>|  4 | a    |<br>|  5 | a    |<br>|  6 | a    |<br>|  7 | a    |<br>|  8 | a    |<br>|  9 | a    |<br>| 10 | a    |<br>+----+------+<br>root@nitty-witty:~# mysql  -hmysql84.kedarnittywitty.rds.amazonaws.com -e \"select * from checksum_rds.pttablechecksum\"<br>+----+------+<br>| id | val  |<br>+----+------+<br>|  1 | a    |<br>|  2 | a    |<br>|  3 | a    |<br>|  4 | a    |<br>|  5 | a    |<br>|  6 | a    |<br>|  7 | a    |<br>|  9 | a    |<br>+----+------+<code><br><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Setup Percona Toolkit for checksum<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\"># Download Toolkit for MySQL 8.4 from https:\/\/www.percona.com\/percona-toolkit &amp; install<br><br>root@nitty-witty:~# dpkg -i percona-toolkit_3.7.0-2.noble_amd64.deb<br><br># Create required database and table<br><br>mysql&gt; create database percona;<br>Query OK, 1 row affected (0.22 sec)<br><br>drop table if exists dsns;<br>CREATE TABLE `dsns` (<br>`id` int(11) NOT NULL AUTO_INCREMENT,<br>`parent_id` int(11) DEFAULT NULL,<br>`dsn` varchar(255) NOT NULL,<br>PRIMARY KEY (`id`)<br>);<br><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-4-run-pt-table-checksum\">Execute Checksum Validation<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\"># Running checksum\n\nroot@nitty-witty:~# pt-table-checksum --host=mysql80.kedarnittywitty.rds.amazonaws.com --user=admin --password=password --databases=checksum_rds  --no-check-binlog-format --no-check-replication-filters --chunk-size=3 --recursion-method=processlist\nChecking if all tables can be checksummed ...\nStarting checksum ...\n            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE\n08-26T10:25:07      0      2       10          1       6       0   0.498 checksum_rds.pttablechecksum<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-5-analyze-checksum-results\">Analyze Checksum Results<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">root@nitty-witty:~# mysql -hmysql84.kedarnittywitty.rds.amazonaws.com<br>Welcome to the MySQL monitor.  Commands end with ; or \\g.<br>Your MySQL connection id is 818<br>Server version: 8.4.5 Source distribution<br><br>Copyright (c) 2009-2025 Percona LLC and\/or its affiliates<br>Copyright (c) 2000, 2025, Oracle and\/or its affiliates.<br><br>Oracle is a registered trademark of Oracle Corporation and\/or its<br>affiliates. Other names may be trademarks of their respective<br>owners.<br><br>Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.<br><br>mysql&gt; select * from percona.checksums;<br>+--------------+-----------------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+<br>| db           | tbl             | chunk | chunk_time | chunk_index | lower_boundary | upper_boundary | this_crc | this_cnt | source_crc | source_cnt | ts                  |<br>+--------------+-----------------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+<br>| checksum_rds | pttablechecksum |     1 |   0.005242 | PRIMARY     | 1              | 3              | 4e1a991  |        3 | 4e1a991    |          3 | 2025-08-26 10:25:06 |<br>| checksum_rds | pttablechecksum |     2 |   0.004853 | PRIMARY     | 4              | 6              | b6c17581 |        3 | b6c17581   |          3 | 2025-08-26 10:25:06 |<br>| checksum_rds | pttablechecksum |     3 |    0.00527 | PRIMARY     | 7              | 9              | bf30be61 |        2 | 8ba15c31   |          3 | 2025-08-26 10:25:07 |<br>| checksum_rds | pttablechecksum |     4 |   0.007311 | PRIMARY     | 10             | 10             | 0        |        0 | bc272b27   |          1 | 2025-08-26 10:25:07 |<br>| checksum_rds | pttablechecksum |     5 |   0.004934 | PRIMARY     | NULL           | 1              | 0        |        0 | 0          |          0 | 2025-08-26 10:25:07 |<br>| checksum_rds | pttablechecksum |     6 |   0.005274 | PRIMARY     | 10             | NULL           | 0        |        0 | 0          |          0 | 2025-08-26 10:25:07 |<br>+--------------+-----------------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+<br>6 rows in set (0.00 sec)<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Find All Inconsistent Tables<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">SELECT db, tbl, SUM(this_cnt) AS total_rows, COUNT(*) AS chunks<br>FROM percona.checksums<br>WHERE (source_cnt &lt;&gt; this_cnt <br>       OR source_crc &lt;&gt; this_crc <br>       OR ISNULL(source_crc) &lt;&gt; ISNULL(this_crc))<br>GROUP BY db, tbl;<br><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-6-generate-repair-statements\">Use pt-table-sync to fix data discrepancy<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">root@nitty-witty:~# pt-table-sync --verbose --print --replicate=percona.checksums --sync-to-source --tables checksum_rds.pttablechecksum h=mysql84.kedarnittywitty.rds.amazonaws.com,u=admin,p=password &gt; checksum_rds.pttablechecksum.sql\nroot@nitty-witty:~# less checksum_rds.pttablechecksum.sql\nroot@nitty-witty:~#\nroot@nitty-witty:~# cat checksum_rds.pttablechecksum.sql\n# Syncing via replication h=mysql84.kedarnittywitty.rds.amazonaws.com,p=...,u=admin\n# DELETE REPLACE INSERT UPDATE ALGORITHM START    END      EXIT DATABASE.TABLE\nREPLACE INTO `checksum_rds`.`pttablechecksum`(`id`, `val`) VALUES ('8', 'a') \/*percona-toolkit src_db:checksum_rds src_tbl:pttablechecksum src_dsn:P=3306,h=mysql80.kedarnittywitty.rds.amazonaws.com,p=...,u=admin dst_db:checksum_rds dst_tbl:pttablechecksum dst_dsn:h=mysql84.kedarnittywitty.rds.amazonaws.com,p=...,u=admin lock:1 transaction:1 changing_src:percona.checksums replicate:percona.checksums bidirectional:0 pid:72602 user:root host:nitty-witty*\/;\n#      0       1      0      0 Chunk     12:15:52 12:15:52 2    checksum_rds.pttablechecksum\nREPLACE INTO `checksum_rds`.`pttablechecksum`(`id`, `val`) VALUES ('10', 'a') \/*percona-toolkit src_db:checksum_rds src_tbl:pttablechecksum src_dsn:P=3306,h=mysql80.kedarnittywitty.rds.amazonaws.com,p=...,u=admin dst_db:checksum_rds dst_tbl:pttablechecksum dst_dsn:h=mysql84.kedarnittywitty.rds.amazonaws.com,p=...,u=admin lock:1 transaction:1 changing_src:percona.checksums replicate:percona.checksums bidirectional:0 pid:72602 user:root host:nitty-witty*\/;\n#      0       1      0      0 Chunk     12:15:52 12:15:52 2    checksum_rds.pttablechecksum<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>TL;DR &#8211; For checksum in RDS, SESSION_VARIABLES_ADMIN is your friend.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"key-considerations-for-rds\">Checksum for RDS<\/h2>\n\n\n\n<p>The pt-table-checksum is one of the important tool from Percona Toolkit and it works perfectly OK on RDS. Note that here we used &#8220;admin&#8221; user for running the checksum. For Non-admin users, you will need <code><strong>SESSION_VARIABLES_ADMIN<\/strong><\/code> privilege:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">GRANT SESSION_VARIABLES_ADMIN ON *.* TO 'checksum_user'@'%'<code><br><\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"During a MySQL upgrade process the RDS replication between MySQL 8.0 and 8.4 was configured. I wanted to ensure the data was consistent for any random reason. This post is&hellip;\n","protected":false},"author":1,"featured_media":3537,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[868,869,8,870],"tags":[1152,1154,758,1090,1151,1153],"class_list":{"0":"post-3512","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-aws-rds","8":"category-mariadb","9":"category-mysql","10":"category-mysql-tools","11":"tag-checksum","12":"tag-data-validation","13":"tag-mysql-8-0","14":"tag-mysql-8-4","15":"tag-mysql-rds","16":"tag-mysql-rds-8-4"},"aioseo_notices":[],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/posts\/3512","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/comments?post=3512"}],"version-history":[{"count":2,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/posts\/3512\/revisions"}],"predecessor-version":[{"id":3538,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/posts\/3512\/revisions\/3538"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/media\/3537"}],"wp:attachment":[{"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/media?parent=3512"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/categories?post=3512"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/tags?post=3512"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}