一、安装
源码编译MySQL,若需要MySQLtar包可私信我
#创建数据目录
mkdir /data/mysql -p
#安装相关依赖
yum install libtirpc-devel-0.2.4-0.16.el7.x86_64.rpm
yum install cmake gcc-c++ openssl-devel ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rpcgen.x86_64 -y
#解压MySQL包,并进入其目录
tar zxf mysql-boost-5.7.44.tar.gz
cd mysql-5.7.44/
#进行源码安装
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/data/mysql -DMYSQL_UNIX_ADDR=/data/mysql/mysql.sock -DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_EXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8mb4 -DDEFAULT_COLLATION=utf8mb4_unicode_ci -DWITH_BOOST=/root/mysql-5.7.44/boost/boost_1_59_0/
#有几个核就j几
make -j2
#安装
make install
#拷贝启动文件
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/
#修改配置文件
vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
#设置环境变量
vim ~/.bash_profile
PATH=$PATH:$HOME/bin:/usr/local/mysql/bin
source ~/.bash_profile
#建立mysql用户
useradd -s /sbin/nologin -M mysql
#将mysql数据目录归属于mysql用户
chown mysql.mysql -R /data/mysql/
#清空数据目录,注意非实验环境需先备份其中内容
rm -rf /data/mysql/*
#MySQL初始化,注意初始化之后会产生一个临时密码,在第一次登陆后需改密码
mysqld --user mysql --initialize
#登录MySQL,并修改root密码,第一次登录不修改密码使用不了
mysql -uroot -p'j;t/EZJ*g1y7'
alter user root@localhost identified by 'Mysql@123';
#设置MySQL开机自启动
yum install chkconfig -y
chkconfig mysqld on ###不设定启动级别,默认2345
chkconfig --list
在三台主机上安装MySQL,具体如下
主机 | 主机名 | 角色 |
192.168.220.10 | node1 | 主 |
192.168.220.20 | node2 | 从 |
192.168.220.30 | node3 | 从 |
二、主从复制
1、干净数据库主从复制
步骤如下
1)分别在主库从库设定不同的server-id以区分不同的数据库
注:设定server-id后从机设定了read_only=1也可以写入,在设定server-id之后不让从机写入需设定super_read_only=on2)设定数据库开始二进制日志
3)在主库上创建主从复制的用户,并给予权限
4)配置从库
#主库node1--配置server-id和开启二进制日志(注,修改完配置文件需要重启数据库)
vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=1 #server-id
log-bin=mysql-bin #二进制日志
#主库--创建用户并授权(登录数据库自己解决)
create user repl@'%' identified by 'Mysql@123'; #创建用户
grant replication slave on *.* to repl@'%'; #授权
#配置完成之后可查看master状态
mysql> show master status ;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 595 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#从库node2--配置server-id和开启二进制日志(注,修改完配置文件需要重启数据库)
vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=2 #server-id
log-bin=mysql-bin #二进制日志
#从库node2--配置主从
change master to master_host='192.168.220.10',master_user='repl',master_password='Mysql@123',master_log_file='mysql-bin.000001',master_log_pos=595;
start slave;
#可以查看slave状态
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.220.10
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 595
Relay_Log_File: node2-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes #看到IO线程Yes
Slave_SQL_Running: Yes #看到SQL线程Yes则说明主从配置成功
2、有数据的数据库主从复制
步骤如下
1)分别在主库从库设定不同的server-id以区分不同的数据库
注:设定server-id后从机设定了read_only=1也可以写入,在设定server-id之后不让从机写入需设定super_read_only=on2)设定数据库开始二进制日志
3)在主库上创建主从复制的用户,并给予权限
4)导出主库数据,传到从库做还原
注:在企业搭建主从复制拉平数据时,需要先将主库锁起来
5)配置从库
#主库node1--配置server-id和开启二进制日志(注,修改完配置文件需要重启数据库)
vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=1 #server-id
log-bin=mysql-bin #二进制日志
#主库--创建用户并授权(登录数据库自己解决)
create user repl@'%' identified by 'Mysql@123'; #创建用户
grant replication slave on *.* to repl@'%'; #授权
#配置完成之后可查看master状态
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 1481 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#主库和从库之间拉平数据,主库要先锁表
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
#验证表是否锁住
mysql> insert into db1.tb1 values('3','力迅');
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
#导出主库数据(注:企业中不能将数据库密码显示输入)
mysqldump -uroot -p'Mysql@123' -B db1 > mysql.sql
#将sql传至新的node节点
scp /root/mysql.sql root@node3:/root
#从库node3--配置server-id和开启二进制日志(注,修改完配置文件需要重启数据库)
vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=3 #server-id
log-bin=mysql-bin #二进制日志
#从库导入主库数据(注:需要先登录数据库)
mysql> source /root/mysql.sql
#从库node3--配置主从
change master to master_host='192.168.220.10',master_user='repl',master_password='Mysql@123',master_log_file='mysql-bin.000001',master_log_pos=595;
start slave;
#可以查看slave状态
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.220.10
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 1481
Relay_Log_File: node3-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes #看到两个线程双Yes则配置成功
#主从搭建好之后把主库解表
mysql> unlock tables;
3、SQL_delay(延迟复制,给主库上一个保险)
延迟复制时用来控制sql 线程的,和 i/o 线程无关这个延迟复制不是i/o 线程过段时间来复制, i/o 是正常工作的是日志已经保存在slave 端了,那个 sql 要等多久进行回放步骤如下
1)先停止从库SQL线程
2)设置master_delay
3)重新启动SQL线程
#将node3配置为延迟复制从库
#停止SQL线程
STOP SLAVE SQL_THREAD;
#修改master_delay时间
CHANGE MASTER TO MASTER_DELAY=60;
#开启SQL线程
START SLAVE SQL_THREAD;
#在show slave status;内容里看到以下内容就配置成功
SQL_Delay: 60
4、慢查询日志
- 慢查询,顾名思义,执行很慢的查询
当执行 SQL 超过 long_query_time 参数设定的时间阈值(默认 10s )时,就被认为是慢查询,这个 SQL语句就是需要优化的 慢查询被记录在慢查询日志里 慢查询日志默认是不开启的 如果需要优化 SQL 语句,就可以开启这个功能,它可以让你很容易地知道哪些语句是需要优化的。
#慢查询日志默认不开启
mysql> show variables like "slow%";
+---------------------+----------------------------+
| Variable_name | Value |
+---------------------+----------------------------+
| slow_launch_time | 2 |
| slow_query_log | OFF |
| slow_query_log_file | /data/mysql/node1-slow.log |
+---------------------+----------------------------+
3 rows in set (0.00 sec)
#慢查询默认查询时间为10s
mysql> show variables like "long%";
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)
#开启慢查询日志,两种方法,一种通过命令行,一种通过修改配置参数,以下是命令行
set global slow_query_log=on
#验证慢查询日志是否开启
mysql> show variables like "slow%";
+---------------------+----------------------------+
| Variable_name | Value |
+---------------------+----------------------------+
| slow_launch_time | 2 |
| slow_query_log | ON |
| slow_query_log_file | /data/mysql/node1-slow.log |
+---------------------+----------------------------+
3 rows in set (0.00 sec)
#慢查询日志记录在slow_query_log_file所对应的位置/data/mysql/node1-slow.log里
5、并行复制
默认情况下slave 中使用的是 sql 单线程回放 ,在master 中时多用户读写,如果使用 sql 单线程回放那么会造成组从延迟严重,开启MySQL 的多线程回放可以解决上述问题
#查看默认情况下slave的线程情况
mysql> show processlist;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| 2 | root | localhost | db1 | Query | 0 | starting | show processlist |
| 5 | system user | | NULL | Connect | 4022 | Waiting for master to send event | NULL |
| 7 | system user | | NULL | Connect | 2911 | Slave has read all relay log; waiting for more updates | NULL |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
3 rows in set (0.00 sec)
#将node2设定为多线程回放
slave-parallel-type=LOGICAL_CLOCK #基于组提交
slave-parallel-workers=16 #开启的线程数量
master_info_repository=TABLE #将master信息记录在表中,默认记录/data/mysql/master_info
relay_log_info_repository=TABLE #将回放日志信息记录在表中,默认记录在/data/mysql目录下
relay_log_recovery=ON #日志回放恢复功能开启
#查看修改过后slave的线程情况
mysql> show processlist;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| 1 | system user | | NULL | Connect | 5 | Waiting for master to send event | NULL |
| 2 | system user | | NULL | Connect | 5 | Slave has read all relay log; waiting for more updates | NULL |
| 3 | system user | | NULL | Connect | 5 | Waiting for an event from Coordinator | NULL |
| 4 | system user | | NULL | Connect | 5 | Waiting for an event from Coordinator | NULL |
| 5 | system user | | NULL | Connect | 5 | Waiting for an event from Coordinator | NULL |
| 7 | system user | | NULL | Connect | 5 | Waiting for an event from Coordinator | NULL |
| 8 | system user | | NULL | Connect | 5 | Waiting for an event from Coordinator | NULL |
| 9 | system user | | NULL | Connect | 5 | Waiting for an event from Coordinator | NULL |
| 10 | system user | | NULL | Connect | 5 | Waiting for an event from Coordinator | NULL |
| 11 | system user | | NULL | Connect | 5 | Waiting for an event from Coordinator | NULL |
| 12 | root | localhost | NULL | Query | 0 | starting | show processlist |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
11 rows in set (0.00 sec)
6、gtid模式
思维引导:为什么需要gtid模式?
在master 端的写入时多用户读写,在slave端的复制时单线程日志回放,所以slave端与master端一定会延迟, 这种延迟在 slave 端的延迟可能会不一致,当 master 挂掉后 slave 接管,一般会挑选一个和master延迟日志最接近的充当新的master,其余的slave主机重新指向新的master主机, 这时候按照之前的配置我们需要知道新的 master 上的 pos 的 id ,但是我们无法确定新的 master 和 slave 之 间差多少,于是我们就需要一个全局的日志,gtid
配置过程
- 在所有节点上开启gtid模式
- 停止所有的slave
- 重新配置从库change master to
- 启动所有slave节点
#在所有节点上开启gtid
[root@node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
log-bin=mysql-bin
server-id=1
gtid-mode=on #以下两行内容,开始gtid
enforce-gtid-consistency=on
#从库操作皆以node2为例
mysql> stop slave;
mysql> change master to master_host='192.168.220.10',master_user='repl',master_password='Mysql@123',master_auto_position=1;
mysql> start slave;
#检验
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.220.10
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 154
Relay_Log_File: node2-relay-bin.000002
Relay_Log_Pos: 367
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: 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:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 154
Relay_Log_Space: 574
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: 1
Master_UUID: 7ead7e03-687d-11ef-8256-000c298c629a
Master_Info_File: /data/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave 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: 1 #出现这个则表示gtid模式成功开启
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
7、异步主从架构
实际上主从同步的原理就是基于 binlog 进行数据同步的。在主从复制过程中,会基于3 个线程来操作, 一个主库线程,两个从库线程。
三个线程
二进制日志转储线程( Binlog dump thread )是一个主库线程。当从库线程连接的时候, 主库可以将二进制日志发送给从库,当主库读取事件(Event )的时候,会在 Binlog 上加锁,读取完成之后,再将锁释放掉。 从库 I/O 线程会连接到主库,向主库发送请求更新 Binlog 。这时从库的