This blog is about how to perform replication for one MySQL primary and one
MySQL replica instance, 8.0 Reference
Replication is asynchronous by default, it could also be synchronous and
semisynchronous.
synchronous replication is a characteristic of NDB Cluster.
semisynchronous replication is supported in addition to the built-in
asynchronous replication.
With semisynchronous replication, a commit performed on the source blocks
before returning to the session that performed the transaction until at least
one replica acknowledges that it has received and logged the events for the
transaction.
Replicas do not need to be connected permanently(replication can be paused) to
receive updates from a source.
Depending on the configuration, you can replicate all databases, selected
databases, or even selected tables within a database.
Goal
Here we focus on binary log file position based replication with MySQL
version 8.0.42, Reference
and MySQL Shell.
Vagrant
The playground
is managed by Vagrant, please launch it before move on to the next section.
Briefly, you will have a primary MySQL with bin log enabled and GTID disabled, a
replica MySQL the same MySQL version with bin log off and unique server ID set.
Initial Data Seed
On primary, let’s create an animals DB and tables:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
CREATE DATABASE IF NOTEXISTS animals;
CREATE TABLE animals.animals ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), species VARCHAR(50), age INT );
-- for replication user to connect to the primary (master) and read the binary -- log. GRANT REPLICATION SLAVE ON*.*TO'repl'@'%'; -- for allows a user to run SHOW MASTER STATUS, SHOW SLAVE STATUS, root user -- on replica don't need this. GRANT REPLICATION CLIENT ON*.*TO'repl'@'%';
-- https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-utilities-dump-instance-schema.html -- The required set of privileges, you can exclude the unwanted ones. GRANT RELOAD, SELECT, EVENT, SHOWVIEW, TRIGGERON*.*TO'repl'@'%';
-- Check the repl user privileges. SHOW GRANTS FOR'repl'@'%';
# The dump log file for debugging. # --log-file=./dump_mysqlsh.log
# Doing a instance dump, you can choose schema or table dump if needed. # Please note that the system DBs will be skipped. # -- util dump-instance /etc/mysqlsh-dump
# When true is set, the utility sets a global read lock using the FLUSH TABLES # WITH READ LOCK statement (if the user ID used to run the utility has the RELOAD # privilege) # Default it is true. # --consistent=true
# I don't need to dump the events and triggers, so disable them here # --events=false # --triggers=false
Please note that the --consistent=true uses FTWRL, this lock is held just long
enough for all the dump threads to establish their own transactions. Once all
threads have started their consistent snapshot transactions, the global read
lock is released immediately. From that point on, each thread operates within
its own REPEATABLE READ transaction, leveraging InnoDB's MVCC to read a consistent
view of the data as it existed when the global read lock was first acquired. This
allows concurrent writes to the database to continue without interruption
during the majority of the dump process.
WARNING: Using a password on the command line interface can be insecure. NOTE: Backup lock is not available to the account 'repl'@'%' and DDL changes will not be blocked. The dump may fail with an error if schema changes are made while dumping.
Acquiring global read lock Global read lock acquired
Initializing - done 1 out of 5 schemas will be dumped and within them 1 table, 0 views. 2 out of 5 users will be dumped.
Gathering information - done All transactions have been started Global read lock has been released Writing global DDL files Writing users DDL Running data dump using 2 threads.
NOTE: Progress information uses estimated values and may not be accurate. Writing schema metadata - done Writing DDL - done Writing table metadata - done
Starting data dump 100% (2 rows / ~2 rows), 0.00 rows/s, 0.00 B/s uncompressed, 0.00 B/s compressed Dump duration: 00:00:00s Total duration: 00:00:00s Schemas dumped: 1 Tables dumped: 1 Uncompressed data size: 27 bytes Compressed data size: 36 bytes Compression ratio: 0.8 Rows written: 2 Bytes written: 36 bytes Average uncompressed throughput: 27.00 B/s Average compressed throughput: 36.00 B/s
# I am using Unix socket instead of TCP/IP to connect local MySQL. Since I don't # configure auth_socket plugin, so password is needed. # --socket=/var/lib/mysql/mysql.sock
# Ignore the major version cap. # --ignoreVersion=true
WARNING: Using a password on the command line interface can be insecure. Loading DDL and Data from '/etc/mysqlsh-dump' using 2 threads.
Opening dump... Target is MySQL 8.0.42. Dump was produced from MySQL 8.0.42
Scanning metadata - done Checking for pre-existing objects... Executing common preamble SQL Executing DDL - done Executing view DDL - done Starting data load Executing common postamble SQL 100% (27 bytes / 27 bytes), 0.00 B/s, 1 / 1 tables done Recreating indexes - done 1 chunks (2 rows, 27 bytes) for 1 tables in 1 schemas were loaded in 0 sec (avg throughput 27.00 B/s) 0 warnings were reported during the load.
If the load is good, you should find the animals.animals table presents:
1 2 3 4 5 6 7 8 9
mysql>SELECT*FROM animals.animals;
+----+-------+---------+------+ | id | name | species | age | +----+-------+---------+------+ |1| Bella | Dog |3| |2| Milo | Cat |2| +----+-------+---------+------+ 2rowsinset (0.00 sec)
Obtain binlog coordinates
Since we use consistent=true in mysqsh dump, we can find binlog file and
position from the @.json file in /etc/mysqlsh-dump folder:
We need to kick off the replication within the expiration of the bin log in the
primary after the data dump and load:
1 2
mysql>show replica status\G Emptyset (0.01 sec)
Run replication setup in replica:
1 2 3 4 5 6 7 8 9 10
-- You can set SSL if it is enabled, the fill options please see -- https://dev.mysql.com/doc/refman/8.0/en/change-master-to.html CHANGE REPLICATION SOURCE TO SOURCE_HOST ='172.20.21.30', SOURCE_PORT =3306, SOURCE_USER ='repl', SOURCE_HEARTBEAT_PERIOD =5, SOURCE_PASSWORD ='ReplP2025!!', SOURCE_LOG_FILE ='binlog.000002', SOURCE_LOG_POS =2201;
Check replication status, the Replica_IO_Running, Replica_SQL_Running are
No since we haven’t started it yet:
Check the replication status again, the Replica_IO_Running, Replica_SQL_Running
should be YES if no issue and Replica_SQL_Running_State contains the current
state:
Show all currently running threads, includes the replication:
1 2 3 4 5 6 7 8 9 10 11
mysql>show processlist\G
***************************2.row*************************** Id: 46 User: repl Host: 172.20.21.31:52140 db: NULL Command: Binlog Dump Time: 7738 State: Source has sent all binlog to replica; waiting for more updates Info: NULL
Verification
Now, let’s insert new row on animals.animals table on primary:
1 2
INSERT INTO animals.animals (name, species, age) VALUES ('Maria', 'Fish', 23);