MySQL主从
一. 主从介绍
- MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主从后,在A上写数据,另外一台B也会跟着写数据,两者数据实时同步的
1. 作用
- 实时灾备,用于故障切换
- 读写分离,提供查询服务
- 备份,避免影响业务
2. 主从形式,Master-Slave
- 一主一从 ,写操作比较少,读操作比较多,(例京东)
- 主主复制,数据同步,使用共享存储
- 一主多从 — 扩展系统读取的性能,因为读是在从库读取的
- 多主一从 — 5.7开始支持,在写操作比较多,读操作比较少,(例12306购票)
- 联级复制
3. 主从复制原理
- 主从复制步骤:
- 主库将所有的写操作记录到binlog日志中并生成一个log dump线程,将binlog日志传给从库的I/O线程
- 从库生成两个线程,一个I/O(硬盘)线程,一个SQL线程
- I/O线程去请求主库的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中
- SQL线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,达到最终数据一致的目的
4. 主从复制配置
4.1 主从复制配置步骤:
- 确保从数据库与主数据库里的数据一样
- 在主数据库里创建一个同步账号授权给从数据库使用
- 配置主数据库(修改配置文件)
- 配置从数据库(修改配置文件)
4.2 需求:
- 搭建两台
MySQL 服务器,一台作为主服务器,一台作为从服务器,主服务器进行写操作,从服务器进行读操作
4.3 环境
数据库角色 | IP | 应用与系统版本 | 有无数据 |
---|
主数据库 | 192.168.232.134 | Red Hat Enterprise Linux release 8.5 (Ootpa) mysql-5.7 | 有数据 | 从数据库 | 192.168.232.128 | Red Hat Enterprise Linux release 8.5 (Ootpa) mysql-5.7 | 无数据 |
5. 先创建主数据
134
mysql> create database school;
Query OK, 1 row affected (0.01 sec)
mysql> use school;
Database changed
mysql> create table tb_student_info(id int not null primary key auto_increment,name varchar(30),age tinyint,sex varchar(6),height
int,course_id int);
Query OK, 0 rows affected (0.13 sec)
mysql> insert into tb_student_info(name,age,sex,height,course_id) values('danny',25,'M',160,1),('green',23,'M',158,2),('henry',23,'F',185,1),('jane',23,'M',162,3),('jim',22,'F',175,2),('john',21,'F',172,4),('lily',22,'M',165,4),('susan',23,'M',170,5),('thomas',22,'F',178,5),('tom',23,'F',165,5);
Query OK, 10 rows affected (0.13 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql> select * from tb_student_info;
+----+--------+------+------+--------+-----------+
| id | name | age | sex | height | course_id |
+----+--------+------+------+--------+-----------+
| 1 | danny | 25 | M | 160 | 1 |
| 2 | green | 23 | M | 158 | 2 |
| 3 | henry | 23 | F | 185 | 1 |
| 4 | jane | 23 | M | 162 | 3 |
| 5 | jim | 22 | F | 175 | 2 |
| 6 | john | 21 | F | 172 | 4 |
| 7 | lily | 22 | M | 165 | 4 |
| 8 | susan | 23 | M | 170 | 5 |
| 9 | thomas | 22 | F | 178 | 5 |
| 10 | tom | 23 | F | 165 | 5 |
+----+--------+------+------+--------+-----------+
10 rows in set (0.00 sec)
mysql>
mysql> create table tb_coursse(id int not null primary key auto_increment,course_name varchar(30));
Query OK, 0 rows affected (0.17 sec)
mysql> insert into tb_coursse(course_name) values('java'),('mysql'),('python'),('go'),('c++');
Query OK, 5 rows affected (0.10 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from tb_coursse;
+----+-------------+
| id | course_name |
+----+-------------+
| 1 | java |
| 2 | mysql |
| 3 | python |
| 4 | go |
| 5 | c++ |
+----+-------------+
5 rows in set (0.00 sec)
mysql>
6. mysql主从配置
- 确保从数据库与主数据库里的数据一样,先全备主数据库并还原到从数据库中
主库134
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| school |
| sys |
+--------------------+
5 rows in set (0.01 sec)
mysql>
从库128
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql>
- 全备主库,全备主库时需要另开一个终端,给数据库加上读锁,避免在备份期间有其他人在写入导致数据不一致
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
mysql>
此锁表的终端必须在备份完成以后才能退出
[root@134h ~]# mysqldump -uroot -prun123456 --all-databases > all-$(date '+%Y%m%d%H%M%S').mysql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@134h ~]# ls
all-20220702184959.mysql anaconda-ks.cfg pass
[root@134h ~]#
[root@134h ~]# ls
all-20220702184959.mysql anaconda-ks.cfg pass
[root@134h ~]# scp all-20220702184959.mysql root@192.168.232.128:/root/
The authenticity of host '192.168.232.128 (192.168.232.128)' can't be established.
ECDSA key fingerprint is SHA256:K5PZWAGixN2F0s4CX9AnYLG7WeRbA6adXzDLI4JRIpQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.232.128' (ECDSA) to the list of known hosts.
root@192.168.232.128's password:
all-20220702184959.mysql 100% 857KB 13.7MB/s 00:00
[root@134h ~]#
[root@128m ~]# ls
3306.pass 3308.pass anaconda-ks.cfg
3307.pass all-20220702184959.mysql
[root@128m ~]#
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
mysql> quit
Bye
[root@134h ~]#
- 在从库上恢复主库的备份并查看从库有哪些库,确保与主库一致
[root@128m ~]# ls
3306.pass 3308.pass anaconda-ks.cfg
3307.pass all-20220702184959.mysql
[root@128m ~]# mysql -uroot -prun123456 -S /tmp/mysql3306.sock < all-20220702184959.mysql
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@128m ~]#
查看
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| school |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql>
6.1 在主数据库里创建一个同步账号授权给从数据库使用
mysql> create user 'repl'@'192.168.232.128' identified by 'repl123';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> grant replication slave on *.* to 'repl'@'192.168.232.128';
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
6.2 配置主数据库
[root@134h ~]# vim /etc/my.cnf
[root@134h ~]# cat /etc/my.cnf
[mysqld]
basedir = /usr/local/mysql
datadir = /opt/data
socket = /tmp/mysql.sock
port = 3306
pid-file = /opt/data/mysql.pid
user = mysql
skip-name-resolve
sql-mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
server-id = 10 数据库服务器唯一标识符,主库的server-id值必须比从库的小
log-bin = mysql_bin //启用binlog日志
[root@134h ~]#
重启mysql服务
[root@134h ~]# systemctl restart mysqld
[root@134h ~]# systemctl status mysqld
● mysqld.service - mysql server daemon
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabl>
Active: active (running) since Sat 2022-07-02 22:07:46 CST; 4>
Process: 1315650 ExecStop=/usr/local/mysql/support-files/mysql>
Process: 1315981 ExecStart=/usr/local/mysql/support-files/mysq>
Main PID: 1315995 (mysqld_safe)
Tasks: 28 (limit: 23502)
Memory: 180.8M
CGroup: /system.slice/mysqld.service
├─1315995 /bin/sh /usr/local/mysql/bin/mysqld_safe -->
└─1316221 /usr/local/mysql/bin/mysqld --basedir=/usr/>
Jul 02 22:07:45 134h.example.com systemd[1]: mysqld.service: Suc>
Jul 02 22:07:45 134h.example.com systemd[1]: Stopped mysql serve>
Jul 02 22:07:45 134h.example.com systemd[1]: Starting mysql serv>
Jul 02 22:07:46 134h.example.com mysqld[1315981]: Starting MySQL>
Jul 02 22:07:46 134h.example.com systemd[1]: Started mysql serve>
[root@134h ~]#
进入
[root@134h ~]# mysql -uroot -prun123456
查看
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql_bin.000002 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql>
7. 配置从数据库
[root@128m ~]# vim /etc/my.cnf
[root@128m ~]# cat /etc/my.cnf
[mysqld_multi]
mysqld = /usr/local/mysql/bin/mysqld_safe
mysqladmin = /usr/local/mysql/bin/mysqladmin
[mysqld3306]
datadir = /opt/data/3306
port = 3306
socket = /tmp/mysql3306.sock
pid-file = /opt/data/3306/mysql_3306.pid
log-error = /var/log/3306.log
server-id = 20
relay-log = myrelay
[mysqld3307]
datadir = /opt/data/3307
port = 3307
socket = /tmp/mysql3307.sock
pid-file = /opt/data/3307/mysql_3307.pid
log-error = /var/log/3307.log
[mysqld3308]
datadir = /opt/data/3308
port = 3308
socket = /tmp/mysql3308.sock
pid-file = /opt/data/3308/mysql_3308.pid
log-error = /var/log/3308.log
[root@128m ~]#
重启从库
[root@128m ~]# systemctl restart sql3306
[root@128m ~]# systemctl status sql3306
* sql3306.service - 3306 server daemon
Loaded: loaded (/usr/lib/systemd/system/sql3306.service; enab>
Active: active (running) since Sat 2022-07-02 22:13:26 CST; 7>
Process: 860294 ExecStop=/usr/bin/ps -ef|grep 3306|grep -v gre>
Process: 860472 ExecStart=/usr/local/mysql/bin/mysqld_multi st>
Main PID: 860478 (mysqld_safe)
Tasks: 28 (limit: 23502)
Memory: 182.0M
CGroup: /system.slice/sql3306.service
|-860478 /bin/sh /usr/local/mysql/bin/mysqld_safe --d>
`-860642 /usr/local/mysql/bin/mysqld --basedir=/usr/l>
Jul 02 22:13:25 128m systemd[1]: Starting 3306 server daemon...
Jul 02 22:13:26 128m systemd[1]: Started 3306 server daemon.
[root@128m ~]#
7.1 配置并启动主从复制
mysql> change master to
-> master_host='192.168.232.134',
-> master_user='repl',
-> master_password='repl123',
-> master_log_file='mysql_bin.000002',
-> master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.13 sec)
mysql> start slave;
Query OK, 0 rows affected (0.10 sec)
mysql>
7.2 查看从服务器状态
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Connecting to master
Master_Host: 192.168.232.128
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql_bin.000002
Read_Master_Log_Pos: 154
Relay_Log_File: myrelay.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql_bin.000002
Slave_IO_Running: Connecting Yes//此处必须为Yes
Slave_SQL_Running: Yes//此处必须为Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
关闭防火墙
[root@128m ~]# systemctl disable --now firewalld
[root@128m ~]# systemctl stop firewalld
[root@128m ~]# systemctl status firewalld
* firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; di>
Active: inactive (dead)
Docs: man:firewalld(1)
再次查看
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.232.134
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql_bin.000002
Read_Master_Log_Pos: 154
Relay_Log_File: myrelay.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql_bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes//生效
8. 验证
主库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| school |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql>
从库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| school |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql>
8.1 在主库上使用,增删改
主库,删除
mysql> drop database school;
Query OK, 2 rows affected (0.25 sec)
mysql>
从库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql>
主库,创建
mysql> create database school;
Query OK, 1 row affected (0.00 sec)
mysql> use school;
Database changed
mysql> create table tb_student_info(id int not null primary key auto_increment,name varchar(30),age tinyint,sex varchar(6),height int,course_id int);
Query OK, 0 rows affected (0.13 sec)
mysql> insert into tb_student_info(name,age,sex,height,course_id) values('danny',25,'M',160,1),('green',23,'M',158,2),('henry',23,'F',185,1),('jane',23,'M',162,3),('jim',22,'F',175,2),('john',21,'F',172,4),('lily',22,'M',165,4),('susan',23,'M',170,5),('thomas',22,'F',178,5),('tom',23,'F',165,5);
Query OK, 10 rows affected (0.11 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql>
从库
mysql> use school;
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_school |
+------------------+
| tb_student_info |
+------------------+
1 row in set (0.00 sec)
mysql> select * from tb_student_info;
+----+--------+------+------+--------+-----------+
| id | name | age | sex | height | course_id |
+----+--------+------+------+--------+-----------+
| 1 | danny | 25 | M | 160 | 1 |
| 2 | green | 23 | M | 158 | 2 |
| 3 | henry | 23 | F | 185 | 1 |
| 4 | jane | 23 | M | 162 | 3 |
| 5 | jim | 22 | F | 175 | 2 |
| 6 | john | 21 | F | 172 | 4 |
| 7 | lily | 22 | M | 165 | 4 |
| 8 | susan | 23 | M | 170 | 5 |
| 9 | thomas | 22 | F | 178 | 5 |
| 10 | tom | 23 | F | 165 | 5 |
+----+--------+------+------+--------+-----------+
10 rows in set (0.00 sec)
mysql>
主库,修改
mysql> update tb_student_info set height = 177 where name = 'green';
Query OK, 1 row affected (0.15 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update tb_student_info set age = 26 where name = 'lily';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
从库
mysql> select * from tb_student_info;
+----+--------+------+------+--------+-----------+
| id | name | age | sex | height | course_id |
+----+--------+------+------+--------+-----------+
| 1 | danny | 25 | M | 160 | 1 |
| 2 | green | 23 | M | 177 | 2 |
| 3 | henry | 23 | F | 185 | 1 |
| 4 | jane | 23 | M | 162 | 3 |
| 5 | jim | 22 | F | 175 | 2 |
| 6 | john | 21 | F | 172 | 4 |
| 7 | lily | 26 | M | 165 | 4 |
| 8 | susan | 23 | M | 170 | 5 |
| 9 | thomas | 22 | F | 178 | 5 |
| 10 | tom | 23 | F | 165 | 5 |
+----+--------+------+------+--------+-----------+
10 rows in set (0.00 sec)
主库,删除
mysql> delete from tb_student_info where name = 'john';
Query OK, 1 row affected (0.00 sec)
mysql> delete from tb_student_info where name = 'thomas';
Query OK, 1 row affected (0.00 sec)
mysql>
从库
mysql> select * from tb_student_info;
+----+-------+------+------+--------+-----------+
| id | name | age | sex | height | course_id |
+----+-------+------+------+--------+-----------+
| 1 | danny | 25 | M | 160 | 1 |
| 2 | green | 23 | M | 177 | 2 |
| 3 | henry | 23 | F | 185 | 1 |
| 4 | jane | 23 | M | 162 | 3 |
| 5 | jim | 22 | F | 175 | 2 |
| 7 | lily | 26 | M | 165 | 4 |
| 8 | susan | 23 | M | 170 | 5 |
| 10 | tom | 23 | F | 165 | 5 |
+----+-------+------+------+--------+-----------+
8 rows in set (0.00 sec)
|