通常,一般业务我们使用云服务器提供的数据库,无论是MySQL数据库还是其他数据库,云服务厂商都提供了主备功能,我们不需要自己配置处理。而如果需要我们自己搭建数据库,那么考虑到数据的高可用性、故障恢复和扩展性,必须做数据备份配置。
# 单个数据库
mysqldump -h hostname -u username -p dbname > backup.sql
# 多个数据库
mysqldump -h hostname -u username -p --databases dbname1 dbname2 > backup.sql
mysqlbackup --host=hostname --user=username --password=password --backup-dir=/path/to/backupdir backup
MySQL 提供的多种数据备份机制各有优缺点和适应场景,复制(主从复制 / 多主复制)适合我们的应用场景,多主复制比主从复制会更为复杂一些,需要考虑数据冲突等问题。在实际使用过程中,主主复制存在很多数据冲突的问题需要解决,所以这里我们选择使用主从备份机制。
MySQL 主从复制是一种基于日志的复制机制,用于将主服务器(Master)上的数据实时复制到一个或多个从服务器(Slave)。主从复制的原理如下:
通过主从复制,可以实现数据的实时复制和分布式读取,提高数据库的可用性和读取性能。此外,主从复制还可以用于备份数据,当主服务器发生故障时,可以快速切换到从服务器,减少服务停机时间。
需要注意的是,主从复制是异步的,从服务器的数据可能稍有延迟。而且主从复制只复制数据修改操作,不复制表结构的变更。如果需要同步表结构的变更,可以使用主从复制搭配其他工具,如 GTID(Global Transaction Identifier)或者基于触发器的解决方案。
MySQL主主复制是一种数据同步和高可用性解决方案,它能够保持多个MySQL服务器之间的数据一致性。主主复制的原理如下:
首先准备至少2台Linux服务器,一台作为MySQL主服务器,一台或者多台作为MySQL从服务器。我们这里准备两台服务器分别为:
mkdir -p /opt/container/mysql/data /opt/container/mysql/config /opt/container/mysql/slave/mysql-files
chmod -R 777 /opt/container/mysql/data /opt/container/mysql/config /opt/container/mysql/slave/mysql-files
/opt/container/mysql/data 用于存放MySQL数据文件
/opt/container/mysql/config 用于存放MySQL配置文件
/opt/container/mysql/slave/mysql-files 用于存放MySQL数据导入/导出的数据文件存放目录
version: '3'
services:
mysql:
environment:
## root账号的密码
MYSQL_ROOT_PASSWORD: root密码
TZ: Asia/Shanghai
## 新建mysql账号
MYSQL_USER: 'mysql_user'
MYSQL_PASSWORD: mysql_user密码
MYSQL_DATABASE: 'mysql_db'
image: "docker.io/mysql:latest"
container_name: mysql
restart: always
## 映射挂载
volumes:
## 数据目录,要确保先创建好
- "/opt/container/mysql/data:/var/lib/mysql"
- "/opt/container/mysql/config/my.cnf:/etc/mysql/my.cnf"
- "/opt/container/mysql/slave/mysql-files:/var/lib/mysql-files"
- "/etc/localtime:/etc/localtime"
- "/usr/share/zoneinfo/Asia/Shanghai:/etc/timezone"
## 初始化的脚本,初始化我们存放的init.sql文件
- "./mysql:/docker-entrypoint-initdb.d/"
ports:
- "3306:3306"
command:
--max_connections=1000
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--default-authentication-plugin=mysql_native_password
在/opt/container/mysql/config目录下新增my.cnf文件, 配置文件内容:
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Custom config should go here
!includedir /etc/mysql/conf.d/
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
server-id=150
log-bin=/var/lib/mysql/mysql-bin
expire_logs_days=60
binlog-format=mixed
max_allowed_packet=256M
relay-log=mysql-relay
log-slave-updates
auto_increment_increment=2 #表示自增长字段每次递增的量
auto_increment_offset=1 #表示自增长字段从那个数开始
在/opt/container/mysql/config目录下新增my.cnf文件, 配置文件内容:
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Custom config should go here
!includedir /etc/mysql/conf.d/
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
server-id=200
# 设置只读模式
# read_only = 1
log-bin=/var/lib/mysql/mysql-bin
expire_logs_days=60
binlog-format=mixed
max_allowed_packet=256M
relay-log=mysql-relay
log-slave-updates
auto_increment_increment=2 #表示自增长字段每次递增的量
auto_increment_offset=1 #表示自增长字段从那个数开始
将docker-compose-mysql.yml上传至/opt/software目录,这个目录可以自己选择,然后到目录下执行安装启动命令
docker-compose -f docker-compose-mysql.yml up -d
[root@localhost software]# docker-compose -f docker-compose-mysql.yml up -d
[+] Running 13/13
⠿ mysql Pulled 40.4s
⠿ 72a69066d2fe Pull complete 14.2s
⠿ 93619dbc5b36 Pull complete 14.2s
⠿ 99da31dd6142 Pull complete 14.6s
⠿ 626033c43d70 Pull complete 14.7s
⠿ 37d5d7efb64e Pull complete 14.7s
⠿ ac563158d721 Pull complete 16.2s
⠿ d2ba16033dad Pull complete 16.2s
⠿ 688ba7d5c01a Pull complete 16.2s
⠿ 00e060b6d11d Pull complete 24.5s
⠿ 1c04857f594f Pull complete 24.5s
⠿ 4d7cfa90e6ea Pull complete 24.6s
⠿ e0431212d27d Pull complete 24.6s
WARN[0040] Found orphan containers ([nginx]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
[+] Running 1/1
⠿ Container mysql Started 0.3s
通过docker ps命令可以看到mysql已经安装并启动成功
[root@localhost software]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bf4e482dbc71 mysql:latest "docker-entrypoint.s…" 21 minutes ago Up 21 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
[root@localhost software]# docker exec -it bf4e482dbc71 bash
root@bf4e482dbc71:/# mysql -uroot -p密码
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 156 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
[root@localhost software]# docker exec -it b168db7981c0 bash
root@bf4e482dbc71:/# mysql -uroot -p密码
CHANGE MASTER TO master_host = '192.168.0.210',
master_port = 3306,
master_user = 'root',
master_password = '密码',
master_log_file = 'mysql-bin.000003',
master_log_pos = 156;
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.0.210
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 156
Relay_Log_File: mysql-relay.000002
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_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: 156
Relay_Log_Space: 529
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: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 150
Master_UUID: ce0ecbd8-667b-11ee-98e5-0242ac120003
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.00 sec)
mysql> create database my_test;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| dbwl |
| information_schema |
| my_test |
| mysql |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
mysql> use my_test;
Database changed
mysql> create table t_test(id int UNSIGNED NOT NULL AUTO_INCREMENT, name varchar(32) NOT NULL, PRIMARY KEY (id));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into t_test(name) values('Test');
Query OK, 1 row affected (0.02 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| dbwl |
| information_schema |
| my_test |
| mysql |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
mysql> use my_test;
Database changed
mysql> show tables;
+-------------------+
| Tables_in_my_test |
+-------------------+
| t_test |
+-------------------+
1 row in set (0.00 sec)
mysql> select * from t_test;
+----+------+
| id | name |
+----+------+
| 1 | Test |
+----+------+
1 row in set (0.00 sec)
MySQL 主主复制的配置和主从复制基本一样,只是需要将原本在从服务器执行的配置命令在主服务器上再执行一遍。
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 2581 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
CHANGE MASTER TO master_host = '192.168.0.195',
master_port = 3306,
master_user = 'root',
master_password = '密码',
master_log_file = 'mysql-bin.000003',
master_log_pos = 2581;
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.0.195
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 2581
Relay_Log_File: mysql-relay.000002
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_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: 2581
Relay_Log_Space: 529
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: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 200
Master_UUID: c1d65f95-667e-11ee-bc7f-0242ac120003
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.00 sec)
mysql> create database my_test_slave;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| dbwl |
| information_schema |
| my_test |
| my_test_slave |
| mysql |
| performance_schema |
| sys |
+--------------------+
7 rows in set (0.00 sec)
mysql> use my_test_slave;
Database changed
mysql> create table t_test(id int UNSIGNED NOT NULL AUTO_INCREMENT, name varchar(32) NOT NULL, PRIMARY KEY (id));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into t_test(name) values('Test');
Query OK, 1 row affected (0.02 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| dbwl |
| information_schema |
| my_test |
| my_test_slave |
| mysql |
| performance_schema |
| sys |
+--------------------+
7 rows in set (0.00 sec)
mysql> use my_test_slave;
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> show tables;
+-------------------------+
| Tables_in_my_test_slave |
+-------------------------+
| t_test |
+-------------------------+
1 row in set (0.00 sec)
mysql> select * from t_test;
+----+------+
| id | name |
+----+------+
| 1 | Test |
+----+------+
1 row in set (0.00 sec)
mysql> insert into t_test(name) values('TestMaster');
Query OK, 1 row affected (0.02 sec)
mysql> select * from t_test;
+----+------------+
| id | name |
+----+------------+
| 1 | Test |
| 3 | TestMaster |
+----+------------+
2 rows in set (0.00 sec)
很多业务场景中,大多数人使用主主复制+keepalived来实现MySQL服务器的高可用,但是存在很大的问题是处理数据冲突问题,可以通过my.cnf中配置,id自增来解决:
auto_increment_increment=2 #表示自增长字段每次递增的量
auto_increment_offset=1 #表示自增长字段从那个数开始
在实际业务处理中会更加复杂,所以在数据库到底是使用主从复制还是主主复制,需要根据自己的业务场景选择。