Foreword
MySQL master-master synchronization actually promotes slave database
to master database
on the basis of master-slave synchronization, so that they can read and write databases with each other, and slave database becomes master Database; the process of master-slave mutual authorization connection, reading the binlog log of the other party and updating it to the local database, as long as the data of the other party changes, it will change accordingly.
1. Advantages and disadvantages of master-master synchronization
In fact, each technology has its advantages and disadvantages. We need to choose the technical service that is more suitable for our own use among the functions.
Advantages of master-master synchronization
- Improve data availability: MySQL master-master synchronization can synchronize data between multiple MySQL servers. When one server fails, other servers can continue to provide services, thereby improving data availability.
- Enhanced data security: MySQL master-master synchronization can realize data backup and replication. When data loss or damage occurs on one of the servers, other servers can provide backup data, thereby enhancing data security. .
- Support read-write separation: MySQL master-master synchronization can realize read-write separation, that is, distribute read requests and write requests to different MySQL servers, thereby improving the read-write performance of the database.
Disadvantages of master-master synchronization
- Data synchronization delay: MySQL master-master synchronization has the problem of data synchronization delay, that is, data inconsistency may occur during the data synchronization process. When a MySQL server modifies data, other servers need a certain amount of time to complete data synchronization, so data synchronization delays may occur.
- Need to coordinate multiple MySQL servers: MySQL master-master synchronization needs to coordinate data synchronization between multiple MySQL servers, so more management and maintenance work is required, including configuration, monitoring, and troubleshooting.
- Degraded database performance: MySQL master-master synchronization may reduce the performance of the database, especially in the process of data synchronization, which may occupy too many system resources, thereby affecting the performance of the database.
To sum up, MySQL master-master synchronization has the advantages of improving data availability, enhancing data security, and supporting read-write separation, but there are also disadvantages such as data synchronization delays, the need to coordinate multiple MySQL servers, and database performance degradation. Therefore, when selecting a database synchronization method, it is necessary to comprehensively consider the actual situation.
1. Deploy MySQL database
It is still necessary to install the MySQL8.0 database on both servers at the same time, here is a quick demonstration.
1.1 Preliminary preparation
In order for the whole experimental procedure to be relatively smooth, the firewall and selinux need to be closed in advance.
iptables -F systemctl stop firewalld.service setenforce 0
Here the second server is no longer a slave, but both are master databases.
system | IP | database version |
---|---|---|
CentOS7.9 | 192.168.116.166(master1) | mysql8.0 |
CentOS7.9 | 192.168.116.128(master2) | mysql8.0 |
1.2 Installing the database
Both servers need to install the database, which is a prerequisite and must be installed.
For detailed steps, please refer to “Installing and Deploying MySQL8.0”
# backup source [root@localhost yum.repos.d]# mv CentOS-Base.repo CentOS-Base.repo.bak #Download network sources [root@localhost yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo #Empty existing files and packages [root@localhost yum.repos.d]# rpm -qa | grep mysql [root@localhost yum.repos.d]# rpm -qa | grep mariadb mariadb-libs-5.5.68-1.el7.x86_64 [root@localhost yum.repos.d]# rpm -e mariadb-libs --nodeps [root@localhost yum.repos.d]# find / -name mysql /etc/selinux/targeted/active/modules/100/mysql /usr/lib64/mysql [root@localhost yum.repos.d]# rm -rf /etc/selinux/targeted/active/modules/100/mysql /usr/lib64/mysql #Download and install MySQL8.0 [root@localhost yum.repos.d]# rpm -ivh https://repo.mysql.com/mysql80-community-release-el7.rpm [root@localhost yum.repos.d]# yum install mysql-community-server -y [root@localhost yum.repos.d]# systemctl restart mysqld #Find the initialization password to prepare for the next step to log in and change the password [root@localhost yum.repos.d]# grep -iwa "Password" /var/log/mysqld.log 2023-03-07T06:56:53.564861Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: h-Ijft/b/9W* #Change database password [root@localhost yum.repos.d]# mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.32 Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> alter user 'root'@'localhost' identified by 'Admin#123'; Query OK, 0 rows affected (0.00 sec) mysql> exit
Once installed, you can start configuring master-master synchronization.
1.3 Ideas
Set the first server as master1 and the second server as master2
The master master1 and the master master2 first perform master-slave synchronization to make them master-slave with each other, and then reverse the second time, let the master be the slave, and let the slave be the master.
On this basis, it is definitely necessary to modify the configuration file, so we will modify master1 first.
2. Configure master1
To increase recognition, modify the host name of the first server in advance
[root@localhost ~]# hostname master1 [root@localhost ~]# bash [root@master1 ~]#
2.1 Modify configuration file
[root@master1 ~]# vim /etc/my.cnf [root@master1 ~]# sed 4, + 5p -n /etc/my.cnf [mysqld] server-id=11 log-bin=mysql-bin auto_increment_increment=2 auto_increment_offset=1 replicate-do-db=demo_db
- server-id=11 #The unique ID of the database
- log-bin=mysql-bin #Store log file location
- auto_increment_increment=2 #Control the step size of the primary key auto-increment, set a few for several servers
- auto_increment_offset=1 #Set the auto-increment start value. This is the first one, then it is 1, and the next one is 2.
- replicate-do-db=demo_db #Select the database to be synchronized.
After modifying the configuration file, remember to restart the service, because modifying the configuration file is equivalent to reassigning variables; without restarting the service, the inode value of the file will not be synchronized to the kernel, so restarting the service is to let the kernel know the new inode value a process.
[root@master1 ~]# systemctl restart mysqld
2.2 Create user master1
Create a master1 user in the database
[root@master1 ~]# mysql -uroot -p'Admin#123' mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.32 MySQL Community Server - GPL Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create user 'master1'@'%' identified with mysql_native_password by '#Master1'; Query OK, 0 rows affected (0.01 sec) mysql> grant replication slave on *.* to 'master1'@'%'; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) mysql> show grants for 'master1'@'%'; + ------------------------------------------------- + | Grants for master1@% | + ------------------------------------------------- + | GRANT REPLICATION SLAVE ON *.* TO `master1`@`%` | + ------------------------------------------------- + 1 row in set (0.00 sec)
create user 'master1'@'%' identified with mysql_native_password by '#Master1';
- The meaning of this statement is to create a user named master1. The name of the user can be defined by oneself; @’%’ means that the database can be logged in remotely, and the statement identified with mysql_native_password by is a fixed way of writing in MySQL8. set password.
grant replication slave on *.* to 'master'@'%';
- This statement means to authorize the user to authorize the database permissions, *.basically grants all permissions, the first means all databases, and the second means database tables.
flush privileges;
- This statement means to refresh the database, so that the previously set content can be synchronized to the database.
show grants for 'master1'@'%';
- Check whether the previously set permissions have been written into the database, and the displayed content indicates that the write has been successful.
Next, continue to check the status of master1
mysql> show master status; + ------------------ + ---------- + -------------- + ---- -------------- + ------------------- + | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | + ------------------ + ---------- + -------------- + ---- -------------- + ------------------- + | mysql-bin.000002 | 157 | | | | + ------------------ + ---------- + -------------- + ---- -------------- + ------------------- + 1 row in set (0.00 sec)
- File is the storage file of the log-bin we just set up, which is used to record the log file of mysql operation.
- Position represents the offset
- Binlog_Do_DB The database that needs to be synchronized
- Binlog_Ignore_DB does not synchronize the database
The value of this offset will change every time the database is operated, so after checking the status, it is best not to continue to operate any content on the master1 database.
Then start to modify the second database.
3. Configure slave1 from the database
This configuration operates on a second server
modify hostname
[root@localhost ~]# hostname master2 [root@localhost ~]# bash [root@master2~]#
3.1 Modify configuration file
Modify the configuration file /etc/my.cnf
, this is the second server, so both id
and auto_increment_offset
need to be adjusted to 2.
[root@master2 ~]# vim /etc/my.cnf [root@master2 ~]# sed 4, + 5p -n /etc/my.cnf [mysqld] server-id=12 log-bin=mysql-bin auto_increment_increment=2 auto_increment_offset=2 replicate-do-db=demo_db
Still the same, modify the configuration file must restart the service
[root@master2 ~]# systemctl restart mysqld
3.2 Bind the main master1 database
mysql> change master to master_host='192.168.116.166', -> master_user='master1', -> master_password='#Master1', -> master_log_file='mysql-bin.000002', -> master_log_pos=157; Query OK, 0 rows affected, 8 warnings (0.00 sec) mysql> start slave; Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> show slave status \G *************************** 1. row ********************* ***** Slave_IO_State: Waiting for source to send event Master_Host: 192.168.116.166 Master_User: master1 Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 157 Relay_Log_File: master2-relay-bin.000002 Relay_Log_Pos: 326 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: demo_db Replicate_Ignore_DB: Replicate_Do_Table: ?… 1 row in set, 1 warning (0.00 sec)
In fact, there are only a few sentences in the above statement that need to be executed. Let’s take a look together.
The template of this piece of information can be copied directly, and the IP, user name, password, log file, and offset of your own definition need to be modified after the equal sign.
change master to master_host='192.168.116.166', #fill in your own IP master_user='master1', #Fill in the user name you created on the first server master_password='#Master1', #Fill in the user password created on the first server master_log_file='mysql-bin.000002', #Fill in the log information of the master on the first server master_log_pos=157; #Fill in the offset of the master on the first server
Use this statement to view the status of the slave database;
show slave status \G
Seeing that these two values are yes means that the synchronization has been successful.
4. Configure master2 database
Next, continue to configure the current master2 server
4.1 Create user master2
Create a user named master2
mysql> create user 'master2'@'%' identified with mysql_native_password by '#Master2'; Query OK, 0 rows affected (0.01 sec) mysql> grant replication slave on *.* to 'master2'@'%'; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec)
View the status of master2
mysql> show master status; + ------------------ + ---------- + -------------- + ---- -------------- + ------------------- + | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | + ------------------ + ---------- + -------------- + ---- -------------- + ------------------- + | mysql-bin.000004 | 157 | | | | + ------------------ + ---------- + -------------- + ---- -------------- + ------------------- + 1 row in set (0.00 sec)
At this point, you don’t need to continue to operate, or you can directly exit the mysql management system.
Go back to the first server and continue to synchronize the second database user
5. Configure slave2 database
In fact, slave2 is also master1, and it is still bound in the same way.
5.1 Bind and synchronize the main master2 database
mysql> change master to master_host='192.168.116.128', master_user='master2', -> master_password='#Master2', master_log_file='mysql-bin.000004', -> master_log_pos=157; Query OK, 0 rows affected, 8 warnings (0.00 sec) mysql> start slave; Query OK, 0 rows affected, 1 warning (0.02 sec) mysql> show slave status \G *************************** 1. row ********************* ***** Slave_IO_State: Connecting to source Master_Host: 192.168.116.128 Master_User: master2 Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 157 Relay_Log_File: master1-relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Connecting Slave_SQL_Running: Yes Replicate_Do_DB: demo_db Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 157 Relay_Log_Space: 157 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 2003 Last_IO_Error: error connecting to master '[email protected]:3306' - retry-time: 60 retries: 1 message: Can't connect to MySQL server on '192.168.116.128:3306' (113) Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: ?… 1 row in set, 1 warning (0.00 sec)
As you can see, when viewing the slave status, there is a value that is not yes.
Slave_IO_Running: Connecting Slave_SQL_Running: Yes
You can see the cause of the error here. Of course, there are many reasons that affect the value of IO is Connecting. Let’s check them one by one.
5.2 Solutions
It is not terrible to encounter errors. You can think about the steps you have performed before, and go back to check whether the previous step is executed correctly. If it is correct, check whether it is a selinux, firewall, network and other problems.
Reason for configuration failure:
- The network is not available – you can try to ping the domain name of the website
- Firewall, selinux is not closed – re-execute the closed operation
- The user password is entered incorrectly – reconfigure it again, confirm it clearly and then enter it
- IP error – confirm whether it is the IP of the local server
- Offset and log file errors – restart the service and reconfigure it again
Both servers need to be checked
[root@master1 ~]# hostname -I 192.168.116.166 192.168.122.1 [root@master1 ~]# systemctl status firewalld ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled) Active: inactive (dead) since Friday 2023-02-10 10:52:45 CST; 1 months 12 days ago Docs: man: firewalld(1) Main PID: 804 (code=exited, status=0/SUCCESS) Feb 10 10:51:06 localhost.localdomain systemd[1]: Starting firewalld - dynamic f.... Feb 10 10:51:10 localhost.localdomain systemd[1]: Started firewalld - dynamic fi.... Feb 10 10:51:11 localhost.localdomain firewalld[804]: WARNING: AllowZoneDrifting... Feb 10 10:52:44 localhost.localdomain systemd[1]: Stopping firewalld - dynamic f.... Feb 10 10:52:45 localhost.localdomain systemd[1]: Stopped firewalld - dynamic fi.... Hint: Some lines were ellipsized, use -l to show in full. [root@master1 ~]# ping -c 1 www.baidu.com PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data. 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=53 time=37.8 ms --- www.a.shifen.com ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 37.807/37.807/37.807/0.000 ms [root@master1 ~]# getenforce Permissive [root@master1 ~]# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
The first server test is OK
Next test the second server
[root@master2 ~]# hostname -I 192.168.116.128 192.168.122.1 [root@master2 ~]# systemctl status firewalld ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2023-03-25 15:28:38 CST; 2s ago Docs: man: firewalld(1) Main PID: 70425 (firewalld) Tasks: 2 CGroup: /system.slice/firewalld.service └─70425 /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...). Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...). Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...). Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...e. Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...e. Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...). Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...). Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...). Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...). Mar 25 15:28:39 master2 firewalld[70425]: WARNING: COMMAND_FAILED: '/usr/sbin/ipt...). Hint: Some lines were ellipsized, use -l to show in full.
It was found that the firewall of the second server was not closed, which was most likely affected by these problems, and then the firewall was turned off.
[root@master2 ~]# systemctl stop firewalld.service
After closing, continue to bind the server on the first server.
It is easier to deal with the problem of the firewall. First, close the slave, reset it, and then open it.
stop slave; reset slave; start slave;
mysql> stop slave; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> reset slave; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> start slave; Query OK, 0 rows affected, 1 warning (0.04 sec) mysql> show slave status \G *************************** 1. row ********************* ***** Slave_IO_State: Waiting for source to send event Master_Host: 192.168.116.128 Master_User: master2 Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 157 Relay_Log_File: master1-relay-bin.000006 Relay_Log_Pos: 373 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: demo_db Replicate_Ignore_DB: ?… 1 row in set, 1 warning (0.00 sec)
Check that both values are yes, indicating that the synchronization has been successful.
6. Test results
The above is the whole content of the master-master synchronization. It is time to verify whether it has been completely successful.
We create the database that we chose to synchronize on the first master1, then create a table for this database, and then insert a few rows of information into the table.
6.1 The first database test
[root@master1 ~]# mysql -uroot -pAdmin#123 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 32 Server version: 8.0.32 MySQL Community Server - GPL Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create database demo_db; Query OK, 1 row affected (0.01 sec) mysql> use demo_db Database changed mysql> create table demo_tb(id int not null,name varchar(20) default 'username'); Query OK, 0 rows affected (0.02 sec) mysql> insert into demo_tb values(1,'zhangsan'), (2,'lisi'), (3,'kunkun'); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0
6.2 Second database test
[root@master2 ~]# mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 16 Server version: 8.0.32 MySQL Community Server - GPL Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show databases; + --------------------+ | Database | + --------------------+ | demo_db | | information_schema | |mysql| | performance_schema | | sys | + --------------------+ 5 rows in set (0.00 sec) mysql> select * from demo_db.demo_tb; + ---- + ---------- + | id | name | + ---- + ---------- + | 1 | zhangsan | | 2 | lisi | | 3 | kunkun | + ---- + ---------- + 3 rows in set (0.01 sec) mysql> use demo_db Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> insert into demo_tb values(4,'liao'), -> (5,'chengpi'), -> (6,'mahua'); Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0
On the first database, see if the content inserted by the second one can also be successfully written.
mysql> select * from demo_tb; + ---- + ---------- + | id | name | + ---- + ---------- + | 1 | zhangsan | | 2 | lisi | | 3 | kunkun | | 4 | liao | | 5 | chengpi | | 6 | mahua | + ---- + ---------- + 6 rows in set (0.00 sec)
Check the input content of the second database, and it can also be synchronized to the first database, indicating that it has been successful.
Summary
The above is the whole content of this article. If you have read yesterday’s “MySQL Database Realizes Master-Slave Synchronization”, you will find that the master-slave synchronization is only on the master-slave synchronization and then operate the master-slave synchronization in reverse. If you think the above content is okay, you can like it and support it!