写在最前头,本文是个人通过测试和生产环境总结下来的文章,并作了小部分处理,文中可能会存在某些描述不准确或错误的地方,欢迎各位大佬评论指出,互相学习!

Mysql8.0

以下说明在Mysql Version 8.0.21为主

二进制包安装

yum list installed| grep mariadb		#搜索mariadb安装包
yum remove mariadb*					   #删除已安装的包
yum install -y libaio gcc 				#安装依赖
useradd mysql						   #创建mysql的用户
mkdir /usr/local/mysql                   #创建mysql安装目录
mkdir /usr/local/mysql/mysqldb           #创建数据存放位置
chown -R mysql:mysql /usr/local/mysql    #修改目录下所属的组和用户
chmod 750 /usr/local/mysql/mysqldb       #修改权限

tar -zxvf mysql-8.0.21-el7-x86_64.tar.gz -C  /usr/local/mysql/		#解压源码包

vim /etc/my.cnf

[mysqld]
port=3306		#数据库端口号
basedir=/usr/local/mysql/mysql-8.0.21-el7-x86_64		#mysql安装目录
datadir=/usr/local/mysql/mysqldb		#mysql数据库的数据的存放目录
max_connections=10000		#允许最大连接数
max_connect_errors=10		#允许错误连接次数
character-set-server=utf8		#服务端默认的字符集
default-storage-engine=INNODB		#创建新表时使用的默认储存引擎
default_authentication_plugin=mysql_native_password		
[mysql]
default-character-set=utf8		#mysql客户端默认字符集
[client]
port=3306		#mysql客户端连接服务端时默认使用端口
default-character-set=utf8
cd bin/
./mysqld --initialize --console

#安装成功后会反馈一个初始密码
2020-08-14T02:58:35.297742Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2020-08-14T02:58:36.520850Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost:au5(kA?)y		#au5(kA?)y为数据库root用户的初始密码
cd support-files/
./mysql.server start			#运行mysql

进入mysql配置

mysql> use mysql;
mysql> update user set user.Host='localhost' where user.User='root';
mysql> flush privileges;

建立软连接

ln -s /usr/local/mysql/mysql-8.0.21-el7-x86_64/bin/mysqladmin /usr/bin/
ln -s /usr/local/mysql/mysql-8.0.21-el7-x86_64/bin/mys /usr/bin/

RPM安装

解压后安装顺序为:common、libs、libs-compat、client、server、test(可选装,测试数据库使用)、devel(可选装,嵌入式数据库函数)、embedded-compat(可选装,兼容式数据库函数)

tar -xvf mysql-8.0.17-1.el7.x86_64.rpm-bundle.tar			#解压
rpm -ivh mysql-community-common-8.0.21-1.el7.x86_64.rpm		 #安装common包

初始化

mysqld --initialize
chown mysql:mysql /var/lib/mysql -R
systemctl start mysql.service

数据库初始密码

cat /var/log/mysqld.log |grep password

进入数据库后更改root密码、授权等操作

编译安装

编译安装某些步骤区别不大,需要创建mysql运行的用户,授权安装目录,解压和预编译

*mysql5.5起,mysql安装的编译工具从configure向cmake过渡

#编译参数
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql 		#安装路径
-DWITH_SSL=yes
-DSYSCONFDIR=/etc/mysql 						  #指向mysql配置文件目录(/etc/mysql)
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock 				    
-DDEFAULT_CHARSET=utf8mb4 							  #指定字符编码			
-DDEFAULT_COLLATION=utf8mb4                #数据库校对规则
-DWITH_MYISAM_STORAGE_ENGING=1 
-DWITH_INNOBASE_STORAGE_ENGING=1 
-DMYSQL_DATADIR=/usr/local/mysql/data 				#mysql数据文件目录
-DWITH_BOOST=/tmp \
-DMYSQL_USER=mysql 								   #指定mysql用户
-DMYSQL_TCP_PORT=3306

安装问题

  1. 启动Mysql服务时报错 my_print_defaults:未找到命令
    解决方法:修改/etc/my.cnf的Mysql安装目录(basedir项),重新输入一遍没有错误的安装地址。
  2. 启动Mysql服务时报错 updating PID file错误
    解决方法:
chmod -R 700 /usr/local/mysql/mysql-8.0.16-el7-x86_64		#对应mysql安装目录
chmod -R 707 /usr/local/mysql/mysqldb		#对应mysql数据文件的安装目录
  1. 无法直接使用mysql命令
    解决方法:在mysql的bin目录下的mysql创建一个软链接到/usr/bin
ln -s /usr/local/mysql/mysql-8.0.21-el7-x86_64/bin/mysql /usr/bin/

AB主从复制

主库

主从复制需要开启二进制日志,slave通过I/O线程读取二进制日志,并把读取到的写到中继日志中,通过重放中继日志同步到从数据库

修改my.cnf

vim /etc/my.cnf
log-bin=mysql-bin		#开启二进制日志
server-id=1			    #服务器 ID 要唯一
CREATE USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'test,123';		#创建一个给从服务器连接的账号,mysql_native_password是身份验证插件,Mysql8.0要先创建账号,再进行授权。
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%';		#REPLICATION复制权限,若不设成这个I/O会无法连接

重启mysql

show master status;


+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000011 |     6097 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+

#把二进制日志的文件、位置写到从库上

从库

修改my.cnf

vim /etc/my.cnf
[mysqld]
server-id=2

在从节点上设置主节点的参数

mysql>CHANGE MASTER TO
MASTER_HOST='192.168.204.200',
MASTER_USER='slave',
MASTER_PASSWORD='slave123',
MASTER_LOG_FILE='binlog.000011',	#对应主库日志文件
MASTER_LOG_POS=6097;			#对应主库的Position

开始主从同步

mysql>start slave;
mysql>show slave status\G		#查看主从同步的状态

查看状态项时,以下两项为yes时,才会开始同步

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

主从同步成功后,此后对数据库进行增删库表数据都会同步

常见错误

  1. SQL线程项为Yes,IO项为Connecting,可以多重启几次从库看看状态,如果得不到解决,查看mysql的错误日志,可以由几方面去逐步排查:网络原因、防火墙、账户密码、mysql配置、连接服务器语法、mysql权限。
  • 网络问题:能相互ping,排除网络问题
  • 防火墙:查看双方的通信端口是否有开放,实验环境中可以尝试关闭防火墙查看问题是否可以解决排除防火墙原因
  • 账户密码:从库的HOST、User、Password要确认没有错误
  • mysql配置:查看主库的my.cnf是否开启二进制日志,server-id是否唯一
  • 连接服务器语法:从库设置的master_log_file、master_log_pos要与主库一致
  1. mysql权限问题:账号的host属性是否有从库,查看用于主从复制的账户授予的权限是否为REPLICATION
    尝试在从库上使用主从同步的账号连接主库,若连接成功,重启主从同步。
  2. 账户消权提示 root用户需要 SYSTEM_USER privilege(s) 权限
    原因:mysql8新增 system_user账户类型,需要授权给root
grant system_user on *.* to 'root';

错误日志

/usr/local/mysql/mysqldb/mysql_server1.err


GTID主从复制

工作流程

  1. master更新数据,会在事务前产生GTID,一同记录到binlog
  2. slave的 I/O线程将变更的binlog,写入到relaylog;
  3. sql线程从relaylog获取GTID,然后对比slave端的binlog是否有记录;
  4. 若有记录,说明该GTID的事务已经执行,slave会忽略;
  5. 若没有记录,slave会从relaylog执行该GTID的事务,并记录到binlog。

主从中添加三个配置,slave的binlog也必须开启

server-id = 6
gtid_mode = ON
enforce_gtid_consistency = ON
log-slave-updates = ON				#mysql-5.7后非必需,会增大I/O

主库创建用户,添加复制的权限

mysql> show global variables like '%uuid%';			#uuid是每个mysql实例的唯一id
mysql> show global variables like '%gtid%';			#确认GTID功能打开,主从的GTID要保持一致
mysql> show variables like 'log_bin';				#bin-log日志

跳过复制错误

gtid_next、gtid_purged

mysql> stop slave;
mysql> set session gtid_next='4e659069-3cd8-11e5-9a49-001c4270714e:1';		#通过查找slave状态获取报错,停止slave,直接跳过此GTID
mysql> begin; 
mysql> commit;
mysql> SET SESSION GTID_NEXT = AUTOMATIC;   							  #把gtid_next设置回来
mysql> start slave;  												 	#开启复制

批量跳过

#查看主库执行到何处,比如:2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-33
mysql> stop slave;
mysql> reset master;
mysql> set global gtid_purged='2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-33';
mysql> start slave;

Log部分

主库binlog,执行过事务记录的日志

从库relaylog:从库接收到主库的binlog日志,

从库binlog:指SQL线程复现relay log后记录的日志(log-slave-update开启),以及从库执行过的事务记录的binlog日志

master.info:存储用户,密码,IP,port,记录上次请求过的binlog位置

relay-log.info:记录了上次SQL线程执行过的relaylog的位置点

GTID

主库的bin-log的pos和从库的relay-log的pos会一致,SQL语句也会相同

#语法:

SHOW RELAYLOG EVENTS
    [IN 'log_name']
    [FROM pos]
    [LIMIT [offset,] row_count]				#[offset],偏移量,默认为0;[row_count]查询条数
    [channel_option]
channel_option:
    FOR CHANNEL channel
    
#例子:
#指定查询 mysql-bin.000021 这个文件,从pos点:8224开始查起,偏移2行,查询10条
  
mysql> show binlog events in 'mysql-bin.000021' from 8224 limit 2,10\G;
mysql> show binary logs;
mysql> show binlog events in 'mysql-bin.000012' FROM pos num ;
mysql> show variables like '%bin%';					           #查看binlog相关参数
mysql> show variables like '%relay%';
mysql> show relaylog events;
mysql> show relaylog events in 'mysql3-relay-bin.000012';		#查看指定relaylog
mysql> select * from mysql.slave_relay_log_info \G			    #查看 relay_log_info

Master_Log_File,Read_Master_Log_Pos 记录了IO thread读到的当前master binlog文件和位置, 对应master的binlog文件和位置。
Relay_Log_File,Relay_Log_Pos 记录了SQL thread执行到relay log的那个文件和位置,对应的是slave上的relay log文件和位置。

简单来讲就是从库先通过io线程读取主库的二进制文件(Master_Log_File)和位置(Read_Master_Log_Pos)然后缓存到本地(从库服务器)的中继文件(Relay_Log_File)中并记录已经读取到的位置(Relay_Log_Pos),再通过从库的sql线程去读取中继文件(Relay_Log_File),这个sql线程执行会记录已经执行到了哪个文件(Relay_Master_Log_File)和哪个位置(Exec_Master_Log_Pos)。

状态解析

IO thread 	把所有从master读到的binlog记录到本地的binlog中,所以relay log的最后一个event的end log_pos就是Read_Master_Log_Pos
SQL thread	按照transaction来执行,所以Exec_Master_Log_Pos对应relay log中最后一个事务event的end_log_pos,这个位置对应的是master的binlog的位置
Relay_Log_Pos 记录的是SQL thread执行的event在relay log中结束位置,头部会出现偏移量,是relay log的偏移量。

那么,从别的服务器取的从库信息来看,我们重新搭建新的从库只需要的是其中的Relay_Master_Log_File & Exec_Master_Log_Pos。

模拟测试

编写脚本大量向数据库写入数据,并对从库进行锁表操作,观察主从两库的log有什么区别

#添加新表
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(200) DEFAULT NULL,
  `createtime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

数据写入脚本

#!/bin/bash
i=1
while [ $i -le 100000000 ]
do
    mysql -uroot -ptest,123 test3 -e "insert into student (name,createTime) values ('student$i',NOW());"
    i=$(($i+1))
	echo $i
done

锁表

mysql>	lock tables test read;				#锁住test2表
mysql>	unlock tables;					    #解锁

对从库进行锁表只读,从库会明显落后主库,此时查看log,relay_log_pos并非对应relaylog的最后一个事务,Exec_Master_Log_Pos才是,并且查看relaylog可知,开始位置pos与主库binlog的pos不一致,但是结束位置的pos值都相同,此时是发生偏移。


Mysql高可用

keepalive+双主

双主

两个库互为主库开启binlog以及相应的用户,开启主从同步

安装keepalived,配置如下

! Configuration File for keepalived

global_defs {
   notification_email {			#故障发生时给谁发邮件通知	
   root@localhost
   root@192.168.204.201	 
 }
   notification_email_from keepalived@localhost		#通知邮件的发出地址
   smtp_server 127.0.0.1
   smtp_connect_timeout 30		#超时时间
   router_id node1			 #运行keepalived的机器标识号,主从机必须不同	
   script_user root
   enable_script_security 
}

vrrp_instance VI_1 {
    state MASTER		#MASTER/BACKUP
    interface ens33		#本地物理网卡,用来发VRRP包
    virtual_router_id 51	#虚拟路由,主从机必须一致,取值0-255,同一网段不许重复
    priority 100		#优先级,越大越优
    advert_int 1		#VRRP包发送间隔
    authentication {	#认证区域,保持master和backup一致
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        192.168.204.215 dev ens33	#漂移地址
    }
}

virtual_server 192.168.204.215 3306 {	#LVS配置
    delay_loop 6		#服务轮询时间
    lb_algo rr			#LVS调度算法
    lb_kind DR			#LVS集群算法
    persistence_timeout 50	
    protocol TCP

    real_server 192.168.204.200 3306 {	#真实服务器的IP和端口
        weight 100
	notify_down /root/mysql.sh
        TCP_CHECK {
        connect_timeout 10
        retry 3
        delay_before_retry 3
        connect_port 3306
        }	
    }
}

在两端建立关闭keepalived脚本,当mysql停掉后自动关闭keepalived,因为keepalived仅仅在对方机器宕机或者keeplived停掉的时候才会接管业务,mysql服务停止但是keepalived服务可能还在工作,此时会导致用户访问的vip无法到对应的业务,所以需要编写脚本当mysql服务中断时,keepalived也中断。

vim /root/mysql.sh
pkill keepalived

测试

Master1

ip addr

 ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:26:25:74 brd ff:ff:ff:ff:ff:ff
    inet 192.168.204.200/24 brd 192.168.204.255 scope global noprefixroute ens33		#此时VIP在master端
       valid_lft forever preferred_lft forever
    inet 192.168.204.215/32 scope global ens33
       valid_lft forever preferred_lft forever

使用虚拟ip(192.168.204.215)能正常连接mysql

mysql的高可用 mysql8高可用_负载均衡

关闭Master的mysql服务

Master2

ip addr

2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:79:a5:eb brd ff:ff:ff:ff:ff:ff
    inet 192.168.204.201/24 brd 192.168.204.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.204.215/32 scope global ens33		#VIP自动漂移到Master2端
       valid_lft forever preferred_lft foreve

此时虚拟ip的数据库仍能连接,但是master1端已经无法连接

mysql的高可用 mysql8高可用_linux_02

报错

Keepalived_vrrp: WARNING - default user ‘keepalived_script’ for script execution does not exist - please create.

解决办法:在配置文件中添加运行健康检查脚本的用户或租

global_defs {
script_user root
enable_script_security
}

监控Mysql主从

基于zabbix去对mysql做监控,主要监控mysql总体状态,主从状态等

基于Status监控主从

保证zabbix用户有权限获取监控数据

#监控Mysql状态
#!/bin/bash
MYSQL_USER=root
MYSQL_PASSWORD=test,123
ARGS=1
MYSQL_COMMAND="show status "

#参数检测
if [ $# -ne "${ARGS}" ];then
    echo "please input the argument..."
fi

result=$(mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -e "${MYSQL_COMMAND}" 2>/dev/null| grep -w $1|awk -F " " '{print $2}')

echo $result
#监控主从状态
#!/bin/bash
MYSQL_USER=root
MYSQL_PASSWORD=test,123
ARGS=1
MYSQL_COMMAND="show slave status \G "

#参数检测
if [ $# -ne "${ARGS}" ];then
    echo "please input the argument..."
fi

result=$(mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -e "${MYSQL_COMMAND}" 2>/dev/null| grep -w $1|awk -F ": " '{print $2}')

echo $result
#zabbix配置文件
#UserParameter=mysql_copy_check,mysql -uroot -ptest,123  -e "show slave status\G" 2>/dev/null | grep -E 'Slave_IO_Running: Yes|Slave_SQL_Running: Yes' | grep -c Yes
UserParameter=mysql_copy_status[*],/home/test/mysql_copy_status.sh $1
#UserParameter=keepalived_master,/home/test/keepalived_master.sh
UserParameter=mysql_status[*],/home/test/mysql_status.sh $1
UserParameter=mysql.version,mysql -V
UserParameter=mysql_ping,mysqladmin -uroot -ptest,123  -S /tmp/mysql.sock ping 2>/dev/null |grep -c alive

问题:脚本获取数据时提示mysql: [Warning] Using a password on the command line interface can be insecure,影响脚本处理

解决方法:试过很多种方法,都无效,不如直接把报警扔到 /dev/null~

基于Pt-heartbeat监控主从

工作原理:pt-heartbeat会在指定库中创建一个heartbeat表,按照一定时间更新表的字段,监控操作开始后,会对比从库的heartbeat表中的timestamp值,计算出差值

#主库
pt-heartbeat -D test2 --update -h 192.168.227.205 -u pt_monitor -p 123456 --daemonize --create-table		#指定数据库,会在库中创建一个heartbeat表

#从库
pt-heartbeat -u pt_monitor -p 123456 -D test2 --table=heartbeat --master-server-id=5  --monitor -h 192.168.227.206
pt-heartbeat -u pt_monitor -p 123456 -D test2 --table=heartbeat --master-server-id=5  --monitor -h 192.168.227.206 --log=/home/heart.txt --daemonize					#在后台运行,并把日志输出到/home/heart.txt文件中
#返回结果
0.01s [  0.00s,  0.00s,  0.00s ]		#--monitor里输出的[]里的记录段,默认是1m,5m,15m
0.00s [  0.00s,  0.00s,  0.00s ]
0.00s [  0.00s,  0.00s,  0.00s ]

#参数
--daemonize   执行时,放入到后台执行
--user=-u,   连接数据库的帐号
--database=-D,    连接数据库的名称
--host=-h,     连接的数据库地址
--password=-p,     连接数据库的密码
--port=-P,     连接数据库的端口
--socket=-S,    连接数据库的套接字文件
--file 【--file=output.txt】   打印--monitor最新的记录到指定的文件,很好的防止满屏幕都是数据的烦恼。
--frames 【--frames=1m,2m,3m】  在--monitor里输出的[]里的记录段,默认是1m,5m,15m。可以指定1个,如:--frames=1s,多个用逗号隔开。可用单位有秒(s)、分钟(m)、小时(h)、天(d)。
--interval   检查、更新的间隔时间。默认是见是1s。最小的单位是0.01s,最大精度为小数点后两位,因此0.015将调整至0.02。
--log    开启daemonized模式的所有日志将会被打印到制定的文件中。
--monitor    持续监控从的延迟情况。通过--interval指定的间隔时间,打印出从的延迟信息,通过--file则可以把这些信息打印到指定的文件。
--master-server-id    指定主的server_id,若没有指定则该工具会连到主上查找其server_id。
--print-master-server-id    在--monitor和--check 模式下,指定该参数则打印出主的server_id。
--recurse    多级复制的检查深度。模式M-S-S...不是最后的一个从都需要开启log_slave_updates,这样才能检查到。
--recursion-method     指定复制检查的方式,默认为processlist,hosts。
--update    更新主上的心跳表。
--replace     使用--replace代替--update模式更新心跳表里的时间字段,这样的好处是不用管表里是否有行。
--stop    停止运行该工具(--daemonize),在/tmp/目录下创建一个“pt-heartbeat-sentinel” 文件。后面想重新开启则需要把该临时文件删除,才能开启(--daemonize)。
--table   指定心跳表名,默认heartbeat。

Zabbix添加item

pt-heartbeat -u pt_monitor -p 123456 -D test2 --table=heartbeat --master-server-id=5  --check -h 192.168.227.206			#直接使用check参数返回只返回一个值,并且按需修改更新间隔 Update interval

关于Mysql复制

异步复制

逻辑上:Mysql默认复制方式 ,主库在执行完提交的事务后立即返回结果给客户端,不关心从库是否接收并处理。

技术上:主库将事务Binlog写入到binlog文件中,此时主库通知以下Dump线程发送这些新的 binlog,然后主库继续处理提交操作,不保证这些Binlog传到每个从节点上。

全同步复制

逻辑上:主库执行完一个事务,所有从库都执行了该事务才返回给客户端

技术上:当主库提交事务后,所有从库点必须收到、APPLY并且提交这些事务,然后主库线程才能继续做后续操作,很显然缺点是主库完成一个事务的时间会被拉长,性能下降。

半同步复制

逻辑上:介于全同步和全异步复制之间的一种,主库只需要等待至少一个从库节点收到并且Flush binlog到relaylog文件即可,主库不需等待所有从库给主库反馈,只需一个反馈即可。

技术上: 等待至少一个从库收到并写到relaylog才返回客户端,有一定延迟,最少是一个tcp/ip往返时间,提高数据的安全性。

条件

Mysql5.5版本以上

变量have_dynamic_loading为YES (查看命令:show variables like “have_dynamic_loading”;)

主从复制已经存在 (即提前部署mysql主从复制环境,主从同步要配置基于整个数据库的,不要配置基于某个库的同步,即同步时不要过滤库)

#安装插件
msyql> install plugin rpl_semi_sync_master soname 'semisync_master.so'; 		#主库
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';			#从库
mysql> show plugins;														#查看安装插件
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;							   #主库开启半同步复制,推荐直接写在my.cnf中
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;							   #从库开启半同步复制,推荐直接写在my.cnf中

半同步状态

mysql> show global variables like '%rpl_semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |			#主库启用半同步
| rpl_semi_sync_master_timeout              | 10000      |			#半同步超时时间,从库超过这个时间无应答,改为异步复制,生产上可以调小一些,设置为1-2秒
| rpl_semi_sync_master_trace_level          | 32         |			
| rpl_semi_sync_master_wait_for_slave_count | 1          |			#多库环境下只等待一个从库应答
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |			#半同步模式,生产建议为AFTER_SYNC
| rpl_semi_sync_slave_enabled               | OFF        |			
| rpl_semi_sync_slave_trace_level           | 32         |
+-------------------------------------------+------------+

并行复制

Mysql复制原理通过三个线程完成,Master上的binlogdunmp线程以及slave上的I/O线程和SQL线程

# slave
 slave-parallel-type=LOGICAL_CLOCK		#m两个值,默认为DATABASE,基于库的并行复制方式;LOGICAL_CLOCK基于组提交的并行复制方式
 slave-parallel-workers=16			    #线程数				
 master_info_repository=TABLE
 relay_log_info_repository=TABLE
 relay_log_recovery=ON

多源复制

mysql5.7版本以上,有效解决数据库分库分表的数据统计问题

参考网站:https://cloud.tencent.com/developer/article/1382116


Mysql主从优化

二进制日志格式

statement:日志记录量较小,节约磁盘空间和网络IO,主从同步存在不一致风险
row:记录SQL对应的每一行操作,粒度比statement细,避免主从复制不一致问题,复制效率高于statement,
mixed:根据sql语句由系统决定使用row还是statement格式

复制所需的库

选择需要复制的库,或直接在从库中过滤相应的库;binlog-ignore-db、binlog-do-db可以指定mysql的binlog日志记录哪个db,但是这会增加master的负载,也无法做基于时间点的复制,比较好的替代方法在slave上配置过滤,用replicate_wild*系列语句。

sync_binlog=1			#1表示每写缓冲一次就同步到磁盘

多线程复制


双主主键冲突问题

避免主键冲突

写到my.cnf,避免主键ID重复

对于业务要求ID连续的无法使用

主1: 
auto_increment_increment=2 				
auto_increment_offset=1 				#这样主1的auto_increment字段的数值是:1,3,5...等奇数ID
主2: 
auto_increment_increment=2 
auto_increment_offset=2					#这样主2的auto_increment字段的数值是:2,4,6...等偶数ID

#auto-increment-increment 服务器的总数,auto-increment-offset不能重复,类似于ID;对于N台服务器,只要保证auto_increment_increment=N ,再设置auto_increment_offset的初始值。

主键冲突解决

对于已发生的主键冲突

mysql> show slave status\G				#查看出错的表名称,以及主键重复的数值
mysql> stop slave;
#停止同步以后,进入主库锁表,再手动同步从库

RBP模式可以解决很多因为主键冲突导致的主从无法同步情况

添加mysql到系统服务

vim /lib/systemd/system/mysql.service

[Unit]
Description=Mysql
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/mysql/mysqldb/mysql_server2.pid		#mysql的pid路径,在mysql的数据文件中可以找到,也可以启动mysql服务后ps进程中查看
ExecStart=/usr/local/mysql/mysql-8.0.21-el7-x86_64/support-files/mysql.server start		#启动mysql服务的路径
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=false

[Install]
WantedBy=multi-user.target

忘记root密码

进入安全模式–>把root用户密码置空–>退出安全模式–>重新修改