编辑
2025-08-10
undefined
00
请注意,本文编写于 122 天前,最后修改于 122 天前,其中某些信息可能已经过时。

目录

4、第三阶段数据库
1、Mysql
1、数据库服务基础管理
1.数据库服务安装启动
2.数据库服务密码管理
1、密码常用插件
2、设置密码
3、忘记密码修改方法
3.数据库服务用户管理
4.数据库服务权限管理
5.数据库服务连接管理
6.安装centos遇到错误
2、数据库服务语句应用
1.数据库服务配置管理
2.数据库多实例管理应用
3.数据库语句应用基础
4.数据库定义语言应用
5.数据库服务查询应用
3、数据库服务优化设置
1.数据库存储引擎应用
2.数据库索引功能应用
3.数据库服务事务机制(稳定性 数据安全性)
4、数据库事务隔离级别
日志信息查看方法
开启
关闭
开启后查看日志
修改日志存储路径(永久配置):
模拟故障,chmod修改权限
查看错误日志,发现是权限不够导致无法启动
chmod修改成755权限
查看是否开启
binlog配置信息
修改为statement测试
1.修改binlog_format
2.查看binlog日志信息记录
3.创建t2表
4.查看binlog.000011
修改为row测试
1.修改row
2.查看binlog日志信息记录
3.创建数据
4.查看binlog.000011,显示乱码
5.解码查看内容
总结:
查看日志:
记录oldboy库的事务操作:修改/etc/my.cnf
测试,分别在oldboy库跟world库创建t7表,通过mysqlbinlog binlog.000012查看日志发现只有oldboy的t7表,因为这是白名单
如果建表插入数据binlog没有记录,第一个通过show master status看是否有黑名单白名单的设置,第二个看一下sqllogbin是否开启
在数据库中查看binlog日志内容
1.设置为30M
2。查看当前binlog日志
3.扩充数据
4.发现binlog.000013到达13M后已经停了,并且自己切割了binlog.000014日志
修改时间
已自动切割了
创建目录
查看文件备份成功
如果51数据库有日志切割
那么备份目录下就会有实时的新log
如何利用binlog日志,实现数据修复:
这个命令也可以
查询测试
记录已经有了
Time: 2025-06-13T13:31:36.035120Z
User@Host: root[root] @ localhost [] Id: 11
Querytime: 1.888895 Locktime: 0.000004 Rowssent: 1000000 Rowsexamined: 1000000
全备数据:可以完全备份数据、表结构、函数、存储过程、触发器等,但是不包括用户权限
分库备份:
分表备份:school是数据库的名
拷贝整个目录
删除后无法登录
拷贝回来可以登录了
1.上传xbk软件程序包
2.解压mysql包
3.做软连接
4.设置环境变量
5.删除之前的数据目录并初始化
6.更换成现在的配置文件
7.登录可以看到8.28版本
8.解压xbk
9.做xtrabackup软连接
10.添加环境变量,可以补全就是成功
1.创建备份目录
2.创建测试数据
3.执行xtrabackup全量备份
--target-dir=/data/backup/full:备份目录
1.关闭数据库
2.删除数据模拟故障
3.恢复到内存中
4.恢复目录磁盘数据
5.授权
6.启动
7.查看数据
1.第一次备份:全备
2.第二次备份:增量
经过查看/data/backup/week02目录下多了pxb目录
3.第三备份:增量
经过查看/data/backup/week03比目录下/data/backup/week02目录多了pxb02目录
1.删除数据模拟故障
2.识别全备,增量目录中需要恢复的数据
3.将识别到的数据恢复到内存
4.内存恢复到磁盘
5.授权
6.查看数据
一句话概括: MySQL主从复制中,主库的binlog dump线程将二进制日志发送给从库,从库的I/O线程接收日志并写入中继日志,从库的SQL线
程读取中继日志并执行其中的SQL语句实现数据同步。
查看主库线程信息,可以看到建立了两个Binlog Dump线程
步骤一:创建主数据库
步骤二:创建从数据库,编写配置文件
步骤三:在主库上进行数据备份
步骤四:在主库上创建同步用户
步骤五:在从库上恢复数据信息
步骤六:在从库上开启主从同步功能
在从库激活主从:
从库线程状态查看是否生效
这样也可以看到CHANGE MASTER TO的配置
创建删除数据库看是否一致
在主库查看
在从库查看
实现步骤:
步骤一:创建主数据库
步骤二:创建从数据库
清除状态
测试:
因为开启GTID主从同步功能,所以每完成一个事务都有一个ExecutedGtidSet编号
查看从节点跟主库是一样
主库新增加一个数据库,从库无变化,因为还没设置要推什么,设置下面参数
已经可以看到最新的节点,最新的数据库
步骤一:创建好主数据库
步骤二:正常建立从库,可以保证正常同步
步骤三:调整从库为延时从库
测试
数据库修复:
结合relaylog确定回放点,恢复到drop table上面那一条
步骤一:在主库和从库安装半同步功能插件
步骤二:编写主库和从库配置文件信息
模拟故障状态
1.没有/etc/init.d/mysqld文件,
2.启动报错
没有/etc/my.cnf文件,编写/etc/my.cnf文件
步骤一:高可用系统环境准备
1.所有节点均执行以上操作,因为MHA程序加载数据库命令,会默认在/usr/bin下面进行加载(会影响数据补偿和监控功能)
2.配置各节点互信
步骤二:安装运行高可用服务程序
1、在所有主从节点安装-node程序包
2、在管理节点安装-manger程序包
3、管理节点编写配置文件信息
4、主库创建:选择mysqlnativepassword插件
5、创建配置文件,根据实际配置修改
6、检查MHA服务运行环境
如果验证不通过,底层之间互相的免密要没成功,重新做一遍
7、检查主从状态
8、开启MHA-manager,在管理管理节点执行
9、查看MHA状态
报错,显示检测没有活着的节点
步骤三:MHA服务功能配置
1、解压后的\mha\mha_script拖拽到/usr/local/bin目录下
1)先完成配置VIP地址漂移功能:
修改配置文件
重启MHA服务
核实此时的MHA的主库节点
手工在主库上添加VIP
2)再实现高可用故障切换报警功能
修改配置文件
3)最后高可用额外补偿功能配置
在备份服务器同步binlog
重启mha功能
连接vip测试
主库停止后,vip飘移到db02
会看到master成了52
这里也能看到
步骤一:根据主节点错误日志信息修复数据
恢复完后先成为从库,数据恢复一段时间后再变为主库
步骤二:将主库配置信息添加的MHA配置文件中
步骤三:重新设置额外补偿功能
步骤四:进行互信和主从同步检查
步骤五:重新运行启动MHA服务
监控脚本验证主节点存活方法
MHA怎么做监控:通过管理用户连接到主节点做一个查询语句,能返回主库还或者,不能返回就说明挂了,就会进行选主
如果成为新主,而数据量相差太大会进行数据补偿,数据补偿之后成为新主,防止数据差异量太大
步骤一:编写masteriponlinechangescript脚本文件
步骤二:需要停止MHA服务状态,防止出现多个vip
检查主从节点线程是否正常
禁用远程补偿功能
再次测试成功
步骤三:进行MHA服务手工在线切换:
查看db02的vip已经没了
db01已经有vip
db03已经看到主节点是10.0.0.51
数据库中间件,所有的请求通过中间件过度,实现分布式存储
步骤一:下载安装软件程序包
步骤二:进行proxysql配置
配置proxySQL内存表:
插入写组编号10,读组编号20
创建监控用户,并开启监控
利用监控用户对后端节点的运行情况进行监控数据同步,一旦后端节点出现数据同步异常,就不要再向故障节点发送相应业务请求;
创建完用户,从节点也要检查
查看监控信息
创建数据库应用用户信息,利用应用用户,可以使proxySQL进行数据库节点的操作管理;
在proxy_sql执行
验证是否可以实现读写分离:
步骤四:读写分离架构软件配置扩展
修改proxySQL监听SQL流量的端口号,监听多端口信息
使监听端口配置信息生效
重启服务
查看是否有多个端口
设定相应读写分离路由规则
确认有用户,主库创建用户
mysql_users添加用户
测试,先删除原有数据
insert into mysqlqueryrules(ruleid,active,username,destinationhostgroup,apply) values (1,1,'write',10,1),(2,1,'reader',20,1);
mysqlqueryrules 添加数据
读测试
写测试
部署redis服务的虚拟主机尽量将内存空间调大,建议调整为4G;
在Redis子目录src中存储了缓存服务应用的相关命令信息
编写基础配置文件信息:
缓存服务应用配置文件:
加载指定缓存服务配置文件,进行服务启动
Redis处于protected-mode默认开启的状态
1、修改配置文件
2、进行监听地址和密码信息设置后,需要重启redis服务程序
3、登录redis
密码设置后登录方式1
或者
在线查看缓存服务所有配置信息
在线修改密码信息,避免重启服务
1、RDB持久化存储手工实现方式:
2、RDB持久化存储核心配置参数:(自动持久化)
配置AOF
重启redis
登录新增key测试
产生aof文件
查看文件内容
实现缓存计数器功能(可以实时关注数据信息变化)
实现计数器递增功能(模拟每点一次关注,都执行一次以上命令)
查看已经存在的所有key名称信息:
返回键所存储数据的类型
进行缓存数据存储操作,hmset存放,stu01相当于表名
进行缓存数据读取操作
返回键所存储数据的类型
以秒/毫秒为单位设定生存时间,以及返回生存时间(EXPIRE/PEXPIRE TTL/PTTL)
创建生成数据列表信息
查看调取数据列表信息
读取第3个值,redis默认从0开始
设置xiaoQ01是key,后面是集合
设置oldboy01 是key,后面是集合
交集处理,显示相同的
差集,xiaoQ01有,oldboy01没有的
差集,oldboy01有,xiaoQ01没有的
更新数量
查看排名信息
进行主从复制实例配置:
运行启动多实例缓存服务:
登录6380创建测试数据
先登录6381测试,没有数据
在从库服务上开启主从同步:
登录6381端口从库查看
查看主从状态
Replication
Replication
在从数据库服务器上解除和主库的关联:
解除主从同步关系状态
步骤一:编写哨兵服务配置文件
步骤二:加载哨兵服务配置文件启动哨兵服务
可以看到主节点是6380
步骤三:验证高可用功能
模拟6380故障
登录6381发现6382成了主节点
集群架构环境规划准备:
集群架构环境节点配置:
集群架构节点启动运行:
查看服务
集群架构节点添加管理:
-- 至此集群构建过程完成
集群架构状态信息查看:
集群主节点状态情况
集群从节点状态情况
创建新的集群节点实例
编写新的节点配置文件
启动运行新的节点服务程序:
进行新的节点架构集群添加:把新的节点7006连接到7000所在的集群环境里
重新给新的集群节点分配槽位,用于存储key value
扩容从节点:新添加的从节点跟扩容的7006相关联,21d8aaf99d663a15652599d61d8466be9fac0179是7006的id
查看从节点信息
1、删除主节点
分片槽位第一次移动
显示已经没有槽位信息
删除7006节点,对应id为21d8aaf99d663a15652599d61d8466be9fac0179
2、删除从节点7007,对应id为6caefa494730fb1a1837036ab50316e633523314

4、第三阶段数据库

1、Mysql

1、数据库服务基础管理

1.数据库服务安装启动
bash
# 第一步:安装解压数数据库 -rw-r--r-- 1 root root 618056612 Feb 20 10:32 mysql-8.0.36-linux-glibc2.12-x86_64.tar.xz [root@db02 ~]#tar -xf mysql-8.0.36-linux-glibc2.12-x86_64.tar.xz 移动到/usr/local [root@db02 ~]#mv mysql-8.0.36-linux-glibc2.12-x86_64 /usr/local # 第二步:创建软连接 [root@db02 /usr/local]#cd /usr/local [root@db02 /usr/local]#ln -s mysql-8.0.36-linux-glibc2.12-x86_64/ mysql # 第三步:创建安装目录 [root@db02 /usr/local]#mkdir -p /data/3306/data 创建用户 [root@db02 /usr/local]#useradd mysql -M -s /sbin/nologin 授权 [root@db02 /usr/local]#chown -R mysql.mysql /data 设置path变量 [root@db01 /usr/local]#vim /etc/profile export PATH="$PATH:/usr/local/mysql/bin" [root@db02 /usr/local]#source /etc/profile # 第四步:进行数据库服务初始化(创建数据库服务运行启动时运行加载的数据) mysqld --initialize --datadir=/data/3306/data --basedir=/usr/local/mysql/ --user=mysql -- 安全初始化数据库服务(会产生临时密码) mysqld --initialize-insecure --datadir=/data/3306/data --basedir=/usr/local/mysql/ --user=mysql -- 不安全初始化数据库服务(不会产生临时密码 可以免密登录) [root@db03 /usr/local/mysql]#/usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir= /usr/local/mysql --datadir=/data/3306/data # 5.6初始化方式 # 第五步:编写生成数据库服务配置文件 ls /etc/my.cnf -- mysql数据库默认配置文件 cat > /etc/my.cnf <<eof [mysql] socket=/tmp/mysql.sock [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data socket=/tmp/mysql.sock eof # 查看 MySQL 配置 mysql --help | grep "socket" # 第六步:启动数据库服务程序 利用脚本文件启动数据库服务 ll /usr/local/mysql/support-files/mysql.server cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld /etc/init.d/mysqld start [root@db-01 ~ 10:28]# ps -ef|grep mysql root 1979 1 0 10:28 pts/0 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/data/3306/data --pid-file=/data/3306/data/db-01.pid mysql 2118 1979 13 10:28 pts/0 00:00:02 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/data/3306/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=db-01.err --pid-file=/data/3306/data/db-01.pid --socket=/tmp/mysql.sock root 2167 1709 0 10:29 pts/0 00:00:00 grep --color=auto mysql [root@db-01 ~ 10:29]# netstat -lntup|grep mysql tcp6 0 0 :::33060 :::* LISTEN 2118/mysqld tcp6 0 0 :::3306 :::* LISTEN 2118/mysqld [root@db-01 ~ 10:29]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.36 MySQL Community Server - GPL Copyright (c) 2000, 2024, 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>
2.数据库服务密码管理
1、密码常用插件
bash
# 可以设置密码插件为常用的mysql_native_password ,防止用户名密码正确而登录不上的情况 mysql> create user root@'%' identified with mysql_native_password by '123456'; mysql> alter user 'root'@'%' identified with mysql_native_password by '123456'; # 全局修改数据库服务配置文件信息 [root@xiaoQ-01 ~]# vim /etc/my.cnf [mysqld] # 在mysqld中区域进行修改 default_authentication_plugin=mysql_native_password
2、设置密码
bash
# 1)设置密码(没有密码) 方法一:在命令行设置为123456 mysqladmin -uroot password "123456" 方法二:在数据库中用SQL语句设置为654321 alter user root@'localhost' identified by '654321'; mysql> set password for 'root'@'localhost'=PASSWORD('123456'); # 5.6设置密码方式 mysql> flush privileges; # 刷新生效 # 2)修改密码 方法一:在命令行修改 mysqladmin -uroot -p654321 password "123" 方法二:在数据库中用SQL语句设置 alter user root@'localhost' identified by '321';
3、忘记密码修改方法
bash
# 步骤一:需要关闭数据库服务 [root@db02 ~]#/etc/init.d/mysqld stop # 步骤二:免密方式重新启动数据库 [root@db02 ~]#mysqld --skip-grant-tables & --skip-grant-tables --表示可以跳过/忽略授权表启动数据库(不加载mysql.user信息到内存中) # 步骤三:重新设置密码 [root@db02 ~]#mysql mysql> flush privileges; 可以将磁盘中用户表信息,加载到内存中 mysql> alter user root@'localhost' identified by '123456'; 设置密码语句 -- 内存(user)-- 磁盘(user) # 步骤四:恢复数据库服务正常运行 停止免密数据库服务进程 kill 进程号 [root@db02 ~]#/etc/init.d/mysqld start # 步骤五:密码登录 [root@db02 ~]#mysql -uroot -p123456
3.数据库服务用户管理
bash
# 1.创建用户: 方法一:创建本地用户(先登录数据库服务系统 --> 登录数据库) mysql> create user zjj@'localhost' identified by '123456'; Query OK, 0 rows affected (0.00 sec) 本地登录没问题 [root@db02 ~]#mysql -uzjj -p123456 远程登录不上 [root@db01 /usr/local]#mysql -uzjj -p123456 -h10.0.0.52 mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 1045 (28000): Access denied for user 'zjj'@'10.0.0.51' (using password: YES) 方法二:创建远程用户 mysql> create user zwx@'%' identified by 'Sdms2018'; 允许登录白名单定义方法: 01:% # 允许所有客户端远程连接服务端 02: 192.168.100.% # 允许指定网段主机连接服务端 192.168.100.1~192.168.100.254 172.16.% # 172.16.0.1~172.16.255.254 10.% 03: 192.168.100.10 允许指定主机连接服务端 远程登录测试,没问题 [root@db01 /usr/local]#mysql -uzwx -pSdms2018 -h10.0.0.52 # 2.查看用户 方式一:查看当前用户信息 mysql> select user(); +----------------+ | user() | +----------------+ | root@localhost | +----------------+ 1 row in set (0.00 sec) 方式二:查看所有用户信息 select user,host,authentication_string from mysql.user; # 3.删除用户: 方法一:删除用户信息 drop user xiaoC@'%'; 方法二:删除用户信息 delete from mysql.user where user='xiaoD' and host='%'; # 4. 修改root用户为远程用户 mysql> select user,host from mysql.user; | root | localhost | mysql> update mysql.user set host='%' where user='root'; Query OK, 1 row affected (0.03 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> flush privileges; mysql> select user,host from mysql.user; Query OK, 0 rows affected (0.01 sec) +------------------+-----------+ | user | host | +------------------+-----------+ | root | % |
4.数据库服务权限管理
bash
数据库服务常用权限: show privileges; -- # 查看所有数据库权限信息 | 序号 | 权限 | 授权资源 | 解释说明 | ---- | ------ | ---------------- | --------------------------------------- | 01 | Select | Tables | 可以对表进行操作,查询表中数据信息 | 02 | Insert | Tables | 可以对表进行操作,插入表中数据信息 | 03 | Update | Tables | 可以对表进行操作,修改表中数据信息 | 04 | Delete | Tables | 可以对表进行操作,删除表中数据信息 | 05 | Alter | Tables | 可以对表进行操作,修改表中结构信息(元数据-属性) | 06 | Index | Tables | 可以对表进行操作,删除或创建表中的索引信息 | 07 | Create | Databases,Tables | 可以对表和库进行操作,用于创建数据库和表信息 | 08 | Drop | Databases,Tables | 可以对表和库进行操作,用于删除数据库和表信息 # 设置用户权限:grant (授权) grant 权限信息 on 库名(*).表名(*) to 用户名@'白名单信息'; mysql> grant create on work.* to zj@'localhost'; 练习一:授权xiaoA本地登录用户,具有创建xiaoA数据库权限,并且具有在xiaoA数据库中创建t1表的权限 grant create on xiaoA.t1 to xiaoA@'localhost'; GRANT CREATE ON *.* TO `xiaoA`@`localhost` 练习二:授权xiaoB本地登录用户,可以在xiaoA数据库中的t1表中,添加新的数据 grant insert on xiaoA.t1 to xiaoB@'localhost'; 补充知识:关注-了解 01 数据库三种特殊权限 USAGE -- No privileges - allow connect only 只能登录数据库(用户创建后的默认权限) all -- 可以针对数据库管理员设置'所有'权限 GRANT OPTION -- 可以给别人进行授权的权限(玉玺) 02 用户授权表知识 mysql.user -- 全局权限信息 mysql.db -- 针对库的权限信息 mysql.tables_priv -- 针对表的权限信息 create user test01@'localhost'; grant select,insert,update on *.* to test01@'localhost'; create user test02@'localhost'; grant select,insert on xiaoA.* to test02@'localhost'; create user test03@'localhost'; grant insert on xiaoA.t1 to test03@'localhost'; # 查看用户权限: mysql> show grants for zj@'localhost'; +----------------------------------------------+ | Grants for zj@localhost | +----------------------------------------------+ | GRANT USAGE ON *.* TO `zj`@`localhost` | | GRANT CREATE ON `work`.* TO `zj`@`localhost` | +----------------------------------------------+ 2 rows in set (0.04 sec) # 回收用户权限:revoke mysql> show grants for test01@'localhost'; +----------------------------------------------+ | Grants for zj@localhost | +----------------------------------------------+ | GRANT USAGE ON *.* TO `zj`@`localhost` | | GRANT CREATE ON `work`.* TO `zj`@`localhost` | +----------------------------------------------+ 1 row in set (0.00 sec) mysql> revoke create on work.* from zj@'localhost'; Query OK, 0 rows affected (0.02 sec) # 授权权限 grant all on *.* to root@'%' with Grant option;
5.数据库服务连接管理
bash
连接方式: 1)本地连接(利用socket文件 套接字文件建立连接) socket文件--门 客户端加载门 == 服务端创建门 [root@oldboy ~]#mysql -uroot -S /tmp/mysql_xiaoQ.sock -- -S指定socket的信息可以省略,因为在数据库服务配置文件的客户端已经配置过了 socket:套接字文件,在登录的时候添加参数-S /tmp/mysql.sock指定套接字文件,是MySQL客户端与服务器进程进行本地通信的关键接口,它的 作用至关重要: 1.当 MySQL 客户端和服务器在同一台机器上时,它们通过这个socket文件直接通信(不经过网络协议栈)比 TCP/IP 连接快 30-50% (省去了网络协议封装/解封装过程) 2.当 MySQL 配置为 skip_networking(禁用网络端口)时,这是唯一的连接方式 3.当服务器运行多个MySQL实例时(如 3306, 3307端口),每个实例有独立 socket 文件 2)远程连接(利用TCP/IP协议) mysql -uroot -p123456 -h目标地址 -P目标端口 连接方法: 方式一:利用数据库命令连接登录数据库服务 (基础) mysql -uroot -p -S /tmp/mysql_xiaoQ.sock -- 本地登录 mysql -uroot -p123456 -h目标地址 -P目标端口 -- 远程登录 PS:没有图形界面,操作语句信息没有补全功能 方式二:利用数据库远程工具连接数据库服务 方式三:利用数据库管理平台连接数据库服务 (了解) phpmyadmin -- 管理平台可以连接管理数据 Ninedata -- 可以连接物理数据库服务 可以对于数据库云产品(RDS) SQL语句执行智能优化 -AI按钮 方式四:利用程序代码和数据库服务建立连接 1)编写连接数据库程序代码 testmysql.php testinfo.php (<php? phpinfo() php>) 2)需要应用数据库连接器
6.安装centos遇到错误
bash
因为yum源的问题导致软件安装不上 #1.查看操作系统版本 [root@mysql yum.repos.d]# cat /etc/os-release NAME="CentOS Linux" VERSION="8" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="8" PLATFORM_ID="platform:el8" PRETTY_NAME="CentOS Linux 8" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:8" HOME_URL="https://centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-8" CENTOS_MANTISBT_PROJECT_VERSION="8" # 2.备份现有源配置 mv /etc/yum.repos.d /etc/yum.repos.d.bak mkdir /etc/yum.repos.d # 3.创建新的存档源配置文件 sudo tee /etc/yum.repos.d/CentOS-Vault.repo << 'EOF' [base] name=CentOS-8.5.2111 - Base baseurl=https://vault.centos.org/8.5.2111/BaseOS/$basearch/os/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial [extras] name=CentOS-8.5.2111 - Extras baseurl=https://vault.centos.org/8.5.2111/extras/$basearch/os/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial [AppStream] name=CentOS-8.5.2111 - AppStream baseurl=https://vault.centos.org/8.5.2111/AppStream/$basearch/os/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial EOF # 4.清除缓存并重建 yum clean all yum makecache sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo sudo yum clean all # 清除旧缓存 sudo yum makecache # 生成新缓存 wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo

2、数据库服务语句应用

1.数据库服务配置管理
序号配置信息解释说明
[mysqld]服务端配置标签
01user=mysql表示数据库服务管理用户信息
02basedir=/usr/local/mysql表示数据库服务程序安装路径
03datadir=/data/3306/data表示数据库服务数据存储路径
04server_id=6表述数据库服务标识节点编号(主从复制的唯一编号)
05port=3306表示数据库服务启动端口设定
06socket=/tmp/mysql.sock表示数据库服务本地连接文件(套接字文件)
07default_authentication_plugin=mysql_native_password表示数据库服务加密插件设定,用于向下兼容
[mysql]客户端配置标签(本地连接数据库生效)
01socket=/tmp/mysql.sock表示数据库服务本地连接文件(套接字文件)
bash
1)如何加载数据库配置文件 方式一:默认加载数据库配置文件 /etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf 方式二:自定义加载数据库配置文件 mysqld --defaults-file=/data/3306/my3306.conf & 2)如何编写数据库配置文件 标签信息:[] 客户端标签:[mysql][mysqladmin][mysqldump] 局部标签 [client] 全局标签 解释说明:可以在执行客户端命令时,加载客户端标签下的配置内容,从而减少命令执行过程中的参数应用 服务端标签:[mysqld][mysqld_safe] 局部标签 [server] 全局标签 解释说明:可以实现数据库服务运行后的某些功能 配置项信息: 客户端所有合理配置项:mysql --help 查看 服务端所有合理配置项:mysqld --help --verbose 查看 PS:配置项信息查询链接:https://dev.mysql.com/doc/refman/8.4/en/dynindex-sysvar.html
2.数据库多实例管理应用
bash
步骤一:进行多实例创建规划 | 实例信息编号 | 实例服务端口 | 实例存储路径 | 实例配置文件 | 套接字文件 | | ------------ | -------------- | --------------- | ---------------------- | ------------------- | | mysql-01 | 端口信息:3307 | /data/3307/data | /data/3307/data/my.cnf | /tmp/mysql3307.sock | | mysql-02 | 端口信息:3308 | /data/3308/data | /data/3308/data/my.cnf | /tmp/mysql3308.sock | | mysql-03 | 端口信息:3309 | /data/3309/data | /data/3309/data/my.cnf | /tmp/mysql3309.sock | 步骤二:创建多实例数据目录 mkdir -p /data/33{07..09}/data chown -R mysql.mysql /data 步骤三:创建多实例配置文件 cat >>/data/3307/my.cnf<<EOF [mysqld] user=mysql port=3307 basedir=/usr/local/mysql datadir=/data/3307/data socket=/tmp/mysql3307.sock EOF cat >>/data/3308/my.cnf<<EOF [mysqld] user=mysql port=3308 basedir=/usr/local/mysql datadir=/data/3308/data socket=/tmp/mysql3308.sock EOF cat >>/data/3309/my.cnf<<EOF [mysqld] user=mysql port=3309 basedir=/usr/local/mysql datadir=/data/3309/data socket=/tmp/mysql3309.sock EOF 步骤四:多实例数据库服务初始化 mv /etc/my.cnf /tmp/ mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/3307/data mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/3308/data mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/3309/data 步骤五:启动数据库多实例 mysqld --defaults-file=/data/3307/my.cnf & mysqld --defaults-file=/data/3308/my.cnf & mysqld --defaults-file=/data/3309/my.cnf & # 关闭服务的方式 [root@db02 /etc/yum.repos.d]#pkill -f "mysqld.*/data/3307/my.cnf" 步骤六:分别登录访问不同实例控制台 本地访问: mysql -uroot -S /tmp/mysql3307.sock mysql -uroot -S /tmp/mysql3308.sock mysql -uroot -S /tmp/mysql3309.sock 远程访问: mysql -uroot -p123456 -h10.0.0.52 -P3307 mysql -uroot -p123456 -h10.0.0.52 -P3308 mysql -uroot -p123456 -h10.0.0.52 -P3309 # 如果设置了客户端提示符,怎么登陆显示 1.设置客户端的提示符 [root@db02 ~]#cat /data/3307/my.cnf . [mysqld] user=mysql port=3307 basedir=/usr/local/mysql datadir=/data/3307/data socket=/tmp/mysql3307.sock [mysql] prompt="mysql-3307>" 2.使用--defaults-extra-file 参数指定你的配置文件 [root@db02 ~]#mysql --defaults-extra-file=/data/3307/my.cnf -uroot -S /tmp/mysql3307.sock -p123456
3.数据库语句应用基础
bash
1)数据库语句应用分类 DDL语句(数据定义语言) 作用:可以操作数据库和数据表(增删改--create alter drop) DCL语句(数据控制语言) 作用:可以管理数据库权限信息和安全相关设置(grant revoke commit rollback) DML语句(数据操纵语言) 作用:可以管理数据表中的数据内容(增改删-cud insert update delete) DQL语句(数据查询语言) 作用:可以获取数据库的数据库信息 配置信息 监控信息(select show) 简历编写: 1)熟练掌握数据库服务DDL/DCL/DML/DQL各种SQL语句应用 2)数据库字符编码设置(字符集) 查看字符编码: show variables like "%character%"; show create database 数据库名称; -- 查看指定数据库字符编码 show create table 数据表名称; -- 查看指定数据表字符编码 设置调整字符编码: 全局调整: vim /etc/my.cnf [mysqld] character-set-server=utf8mb3 [mysql] default-character-set=utf8mb3 局部调整: alter database xiaoA CHARACTER SET utf8mb4 alter table t1 CHARSET=utf8mb3 3) 数据库数据类型设置 设置数据类型: - 保证数据表中录入数据的合理性 - 可以有效控制数据占用的磁盘空间 查询数据效率慢 如何应用数据类型: 数值类型:整数 小数 字符类型:可变长类型 定长类型 时间类型:日期类型 时间类型 日期时间类型 枚举类型:保证输入信息必须符合指定要求 4)数据库数据约束属性设置 约束设置: PK约束(主键约束):指定的列存储的数据信息 不能为空也不能重复 UK约束(唯一约束):指定的列存储的数据信息 不能出现重复信息 NN约束(非空约束):指定的列存储的数据信息 不能出现空值信息 FK约束(外键约束):多张表进行数据修改 添加 删除时,需要有逻辑顺序(了解) 属性设置: default 默认填充信息 auto_increment 自增数值属性设置(针对主键列) unsigned 可以保证数值列必须是正数 comment 可以给表或列做注释说明
4.数据库定义语言应用
bash
1)数据库DDL语句应用 创建库:create 简单方式:create database 库名; 完整方式:CREATE DATABASE `xiaoA` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ENCRYPTION='N' 修改库:alter 修改字符集: alter database 库名 CHARACTER SET 字符集(utf8 gbk) utf8mb3-utf8 utf8mb4-增加了对emoji 修改校对规则/排序规则:alter database 库名 CHARACTER SET 字符集 COLLATE utf8mb4_0900_ai_ci (对大小写识别方式/影响字符信息排序) 删除库:drop (慎用) drop database 库名; --- 物理删除 2)数据表DDL语句应用 创建表:create CREATE TABLE student ( `id` int NOT NULL COMMENT '学号信息', `name` varchar(3) COMMENT '学生名', `age` tinyint unsigned NOT NULL COMMENT '学生年龄', `gender` enum('M','F','N') NOT NULL DEFAULT 'N' COMMENT '学生性别', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生表' 修改表:alter 表名称修改: alter table stu2 rename stu3; rename table students to student; 表字符集修改: alter table student CHARSET=utf8mb3; 表的结构信息: - 字段信息:添加 删除 添加: alter table student add column telno char(11) not null unique key comment '手机号'; alter table student add column qqnum char(11) not null unique key comment 'QQ号' after gender; alter table student add column wechatnum char(11) not null unique key comment 'QQ号' first; 删除: alter table student drop column wechatnum; 查看表的结构信息 mysql> desc student; +--------+-------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------------+------+-----+---------+-------+ | id | int | NO | PRI | NULL | | | name | varchar(3) | YES | | NULL | | | age | tinyint | NO | | NULL | | | gender | enum('M','F','N') | NO | | N | | | telno | char(11) | NO | UNI | NULL | | +--------+-------------------+------+-----+---------+-------+ 5 rows in set (0.01 sec) - 数据类型:修改 alter table student modify name char(10) comment '学生名'; - 约束修改: alter table student modify name char(10) not null comment '学生名'; - 属性修改: ALTER TABLE student CHANGE COLUMN id INT NOT NULL AUTO_INCREMENT COMMENT '学号信息' ; 表的索引修改:添加 删除 ??? 删除表:drop/delete/truncate drop table student; -- 物理删除 delete from student; truncate table student;

delete和truncate的区别:

特性DELETETRUNCATE
命令类型DML(数据操作语言)DDL(数据定义语言)
可回滚性✅ 支持事务回滚❌ 立即生效不可回滚(多数DB)
删除方式逐行删除直接释放数据页
执行速度慢(记录日志)极快(最小化日志)
WHERE条件✅ 支持条件删除❌ 只能全表删除
自增ID重置❌ 不重置自增计数器✅ 重置自增计数器到初始值
触发器激活✅ 激活DELETE触发器❌ 不激活任何触发器
锁机制行级锁表级锁
磁盘空间回收不立即回收(高水位线不变)立即回收(重置高水位线)

5.数据库服务查询应用
bash
查询语句应用01:可以调取数据库变量信息 系统变量:表示数据库服务功能配置信息(查看+修改) 状态变量:表示数据库服务监控状态信息(查看) show variables like "%log%"; -- 查看数据库系统变量(过滤查看) select @@sql_log_bin; 扩展:数据库配置信息修改方法 临时修改: set session 系统变量=配置内容; -- 只是当前会话生效 set global 系统变量=配置内容; -- 可以实现全局配置(影响所有用户 会话断开依然生效),重启数据库失效 永久修改: 编写配置文件 vim /etc/my.cnf [mysqld] 系统变量=配置内容 查询语句应用02:数据库服务函数信息 select user(); -- 查看登录用户信息 select database(); -- 查看切换数据库信息 select now(); -- 查看系统时间信息 https://blog.csdn.net/Fu_lucas/article/details/146054388 查看语句应用03:数据库数据信息查看 单表数据信息查看: select+from+where+group by+having+order by+limit 创建一些测试数据: 下载测试数据: https://downloads.mysql.com/docs/world-db.tar.gz 上传测试数据,并解压缩进行加载 mysql>source /root/world-db/world.sql; select+from+where 查询需求01:查询属于中国的所有城市和人口信息 select name,population,countrycode from city where countrycode='CHN'; 查询需求02:查询中国人口数量大于100w城市信息 select name,population,countrycode from city where countrycode='CHN' or population>1000000; 查询需求03:查询中国和美国人口数量大于100w城市信息 select name,population,countrycode from city where countrycode='CHN' and population>1000000; xxx xxx xxx xxx select name,population,countrycode from city where countrycode='USA' and population>1000000; select name,population,countrycode from city where (countrycode='CHN' or countrycode='USA') and population>1000000 select name,population,countrycode from city where countrycode in ('CHN','USA') and population>1000000 and 表示在前一个条件对表数据过滤后,在利用后面的条件进一步过滤 or 表示在前一个条件对表数据过滤后,和后面条件对表顾虑后的内容做合并 查询需求04:查询中国人口数量大于100w并小400w的城市信息 select name,population,countrycode from city where countrycode='CHN' and population>1000000 and population<4000000; select name,population,countrycode from city where countrycode='CHN' and population between 1000000 and 4000000; 查看需求05:查询中国境内有多少个省份信息 select count(distinct District) from city where countrycode='chn'; select+from+where+group by(分组统计) 查看需求01:统计所有各个国家的人口总数 select sum(population),countrycode from city group by countrycode; group by 分组条件字段(countrycode) 1)需要先进行排序处理 2)将分组后的字段做取重 3)要进行分组后数据聚合处理(求和处理-sum() 计数处理-count() 多行聚合函数-group_concat 求平均值-avg() 求最大值-max() 求最小值-min()) 查询需求02:统计中国境内,每个省份的城市数量; select count(name),District from city where countrycode='CHN' group by District; 查询需求03:统计中国境内,每个省份的城市数量,以及每个省份城市信息 select count(name),District,group_concat(name) from city where countrycode='CHN' group by District; sql_mode ONLY_FULL_GROUP_BY: 此配置表示,在分组后显示的信息必须一对一有对应关系,不能出现一对多的对应关系 select+from+where+group by+having where : 只能根据表中有的字段进行过滤 having :可以根据分组后的聚合信息做过滤 查询需求01:统计所有各个国家的人口总数,将人口总数大于1亿国家信息显示输出 select sum(population),countrycode from city group by countrycode having sum(population)>100000000; 查询需求02:统计中国境内,每个省份的城市数量,将城市数量大于20的省份显示输出 select count(name),District from city where countrycode='CHN' group by District having count(name)>20; select+from+where+group by+having+order by+limit 查询需求01:统计所有各个国家的人口总数,将人口总数大于5千万国家信息显示输出,并排序显示 select sum(population),countrycode from city group by countrycode having sum(population)>50000000 order by sum(population); -- 默认升序排序 select sum(population),countrycode from city group by countrycode having sum(population)>50000000 order by sum(population) desc; -- 修改为降序排序 select sum(population),countrycode from city group by countrycode having sum(population)>50000000 order by sum(population) desc limit 3; 连表数据信息查看:(内连接查询) 创建测试数据: CREATE DATABASE school CHARSET utf8; USE school; CREATE TABLE student ( sno INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学号', sname VARCHAR(20) NOT NULL COMMENT '姓名', sage TINYINT UNSIGNED NOT NULL COMMENT '年龄', ssex ENUM('f','m') NOT NULL DEFAULT 'm' COMMENT '性别' ) ENGINE=INNODB CHARSET=utf8; CREATE TABLE course ( cno INT NOT NULL PRIMARY KEY COMMENT '课程编号', cname VARCHAR(20) NOT NULL COMMENT '课程名字', tno INT NOT NULL COMMENT '教师编号' ) ENGINE=INNODB CHARSET=utf8; CREATE TABLE sc ( sno INT NOT NULL COMMENT '学号', cno INT NOT NULL COMMENT '课程编号', score INT NOT NULL DEFAULT 0 COMMENT '成绩' ) ENGINE=INNODB CHARSET=utf8; CREATE TABLE teacher ( tno INT NOT NULL PRIMARY KEY COMMENT '教师编号', tname VARCHAR(20) NOT NULL COMMENT '教师名字' ) ENGINE=INNODB CHARSET=utf8; # 在数据库与数据表中插入模拟数据 INSERT INTO student(sno,sname,sage,ssex) VALUES (1,'zhang3',18,'m'), (2,'zhang4',18,'m'), (3,'li4',18,'m'), (4,'wang5',19,'f'), (5,'zh4',18,'m'), (6,'zhao4',18,'m'), (7,'ma6',19,'f'), (8,'oldboy',20,'m'), (9,'oldgirl',20,'f'), (10,'oldp',25,'m'); INSERT INTO teacher(tno,tname) VALUES (101,'oldboy'), (102,'xiaoQ'), (103,'xiaoA'), (104,'xiaoB'); INSERT INTO course(cno,cname,tno) VALUES (1001,'linux',101), (1002,'python',102), (1003,'mysql',103), (1004,'go',105); INSERT INTO sc(sno,cno,score) VALUES (1,1001,80), (1,1002,59), (2,1002,90), (2,1003,100), (3,1001,99), (3,1003,40), (4,1001,79), (4,1002,61), (4,1003,99), (5,1003,40), (6,1001,89), (6,1003,77), (7,1001,67), (7,1003,82), (8,1001,70), (9,1003,80), (10,1003,96); SELECT * FROM student; SELECT * FROM teacher; SELECT * FROM course; SELECT * FROM sc; 内连接查询语法应用: mysql> select * from teacher,course where teacher.tno=course.tno; +-----+--------+------+--------+-----+ | tno | tname | cno | cname | tno | +-----+--------+------+--------+-----+ | 101 | oldboy | 1001 | linux | 101 | | 102 | xiaoQ | 1002 | python | 102 | | 103 | xiaoA | 1003 | mysql | 103 | +-----+--------+------+--------+-----+ mysql> select * from teacher join course on teacher.tno=course.tno; +-----+--------+------+--------+-----+ | tno | tname | cno | cname | tno | +-----+--------+------+--------+-----+ | 101 | oldboy | 1001 | linux | 101 | | 102 | xiaoQ | 1002 | python | 102 | | 103 | xiaoA | 1003 | mysql | 103 | +-----+--------+------+--------+-----+ 3 rows in set (0.00 sec) 连表查询数据方法: 1)将数据库中有关联的表进行串联,构建数据库ER模型图 2)根据查询需求,定位需要获取数据的表 3)将多个表利用内连接语句拼接成一张大表 4) 根据查询需求,对大表(单表)进行数据过滤查询 01 统计zhang3,学习了几门课? student sc course select student.sname,count(course.cname) from student join sc on student.sno=sc.sno join course on sc.cno=course.cno where student.sname='zhang3'; 02 查询zhang3,学习的课程名称有哪些? student sc course select student.sname,course.cname from student join sc on student.sno=sc.sno join course on sc.cno=course.cno where student.sname='zhang3'; 03 查询xiaoA老师教的学生名? teacher course sc student select teacher.tname,student.sname from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno join student on sc.sno=student.sno where teacher.tname='xiaoA'; select teacher.tname,student.sname from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno join student on sc.sno=student.sno where teacher.tname='xiaoC'; 04 查询xiaoA老师教课程的平均分数? teacher course sc select teacher.tno,teacher.tname,course.cname,avg(sc.score) from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno where teacher.tname='xiaoA' group by teacher.tno,course.cname; 连表练习题目: https://www.cnblogs.com/oldboy-heqing/articles/16868031.html 利用系统视图:tables 视图为例 01:获取数据库资产信息 (实例 有多少数据库 有多少张数据表)

3、数据库服务优化设置

1.数据库存储引擎应用
特性InnoDBMyISAM关键影响
默认引擎 (MySQL版本) (MySQL 5.5 及以后) (MySQL 5.5 之前默认)现代安装默认就是 InnoDB。
事务 (ACID)支持不支持InnoDB 适合需要保证数据完整性的场景(如银行交易、订单)。MyISAM 不适合。
锁机制行级锁 (默认,可升级为表锁)表级锁InnoDB 并发写性能极高(多用户同时写互不阻塞)。MyISAM 并发写性能(写操作会阻塞所有读写)。
外键约束支持不支持InnoDB 能强制维护表间关系。MyISAM 需要应用层保证引用完整性。
崩溃恢复强大 (通过 redo log 实现)较弱 (依赖REPAIR TABLE​,可能丢数据)InnoDB 在服务器崩溃后通常能自动恢复且数据丢失风险低。MyISAM 风险较高。
主键/聚簇索引 (主键索引叶子节点存储行数据) (主键索引叶子节点存储数据指针)InnoDB 主键查询极快,但辅助索引需要回表(二次查找主键)。MyISAM 所有索引结构相同。
MVCC支持不支持InnoDB 提供非锁定一致性读,提高并发读性能。MyISAM 读会加共享锁。
数据文件.ibd​ (独立表空间) 或 ibdata*​ (系统表空间).MYD​ (数据), .MYI​ (索引)InnoDB 文件管理更集中/灵活(可配置独立表空间)。
表压缩支持 (页级别压缩)支持 (只读压缩表)两者都支持压缩,但 MyISAM 压缩表只读。
全文索引 (FULLTEXT)支持 (MySQL 5.6+)支持 (较早支持)早期版本 MyISAM 是唯一选择,现在 InnoDB 也完全支持且功能更强。
COUNT(*) 性能较慢 (需扫描表或索引)极快 (维护行计数器)MyISAM 对无 WHERE 的 COUNT(*)​ 非常快。InnoDB 需要实际计算。
推荐使用场景OLTP、高并发读写、事务型应用、Web应用只读/读多写少、简单查询、日志(不推荐新用)现代应用首选 InnoDB。MyISAM 仅限遗留或非常特定场景,不推荐新项目。
主要缺点相对复杂、空间占用稍高、无WHERE的COUNT慢表锁导致并发差、无事务/外键、崩溃恢复弱
bash
MyISAM存储引擎:(MySQL 5.5之前的默认存储引擎) MyISAM是MySQL较早的存储引擎之一,它不支持事务处理和行级锁定,但提供了全文索引、高速缓存等特性; MyISAM适用于读多写少,数据完整性要求不高的场景,如博客,新闻网站等; InnoDB存储引擎:(MySQL 5.5之后的默认存储引擎) InnoDB是MySQL目前的默认存储引擎,由于支持事务特性、聚簇索引功能,行级锁,以及自动故障恢复功能,广泛在应用中使用; InnoDB适用于对数据存储安全性,一致性和完整性高的场景,比如:金融行业、游戏行业、电商网站平台等。 # 实战项目:利用InnoDB存储引擎,实现数据库异常独立表空间迁移数据 独立表空间迁移: 步骤一:创建测试数据 mysql>source /root/t100w_oldboy.sql; 步骤二:获取数据表结构信息 mysql> desc create table t100w; 步骤三:模拟数据库服务故障 /etc/init.d/mysqld stop 步骤四:部署新的数据库实例 mysqld --defaults-file=/data/3307/my.cnf & 步骤五:在新的数据库中创建原有库和表 create database oldboy; mysql> use oldboy; CREATE TABLE `t100w` ( `id` int DEFAULT NULL, `num` int DEFAULT NULL, `k1` char(2) DEFAULT NULL, `k2` char(4) DEFAULT NULL, `dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; 步骤六:迁移表空间文件(表文件),新库执行 # 执行前 [root@db02 ~]#ll /data/3307/data/oldboy/ alter table oldboy.t100w discard tablespace; # 执行后 [root@db02 ~]#ll /data/3307/data/oldboy/ total 0 cp -a /data/3306/data/oldboy/t100w.ibd /data/3307/data/oldboy/ [root@db-01 oldboy 16:58]# ll /data/3307/data/oldboy/ total 57344 -rw-r----- 1 mysql mysql 58720256 Jun 11 16:47 t100w.ibd mysql> alter table oldboy.t100w import tablespace;
2.数据库索引功能应用
bash
数据库设置索引作用: 可以减少磁盘的IO消耗,从而提高数据库存储和读取数据的效率; 索引优点: 1.提高数据检索速度,降低数据库IO成本(IO就是数据对磁盘的输入输出操作,包括硬盘读写操作和内存缓存操作,数据库性能优化主要集中在IO操作的优化上) 2.通过创建唯一索引,可以保证数据库表中每一行数据的唯一性 索引缺点: 1.创建索引和维护索引要耗费时间 2.索引需要占用磁盘空间 3.虽然提高了查询速度,同时却会降低表的更新速度,当对表中数据进行增删改时,索引也要动态维护 数据库设置索引作用: 可以减少磁盘的IO消耗,从而提高数据库存储和读取数据的效率; 数据库索引应用机制: 遍历机制: 逐行查找数据信息(全表扫描) 缺陷:找寻速度慢/会造成内存溢出 二叉树机制:可以减少一半的磁盘IO消耗,有效提高数据查询效率 缺陷:无法实现数据查找的均衡性 B+Tree树机制: 结构: 页节点(16KB): 主要存储数据信息和索引列信息 支节点(16KB): 主要存储索引列范围信息和对应页节点指针信息 根节点(16KB): 主要存储索引列范围信息和对应支节点指针信息(只有一个) 优点: 1)查找表中任意数据可以消耗IO资源更加均衡(查询效率几乎相等) 2)利用此机制可以便于数据库进行范围查询数据信息 数据库索引如何应用: 聚簇索引(主键索引): 可以获取某行所有数据信息的索引 辅助索引(一般索引): 可以帮助使用者利用非主键列快速调取数据 回表:如果想查找完整用户记录值的话,先根据二级索引B+树先确定要查找记录的主键值,根据主键值通过聚簇索引中继续查找用户完整记录,因为聚簇索 引的叶子节点储存了所有列的值。二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键找到行数据聚簇索引存储的就是我们的数据记录, 二级索引存储的是根据某个字段构建的索引值与主键值。 数据库索引设置方法: 普通索引创建:(经常作为条件查询的列) 方法一:创建表时创建索引 mysql> create table t1 ( -> id int, -> name char(5), -> index idx_name(name)); Query OK, 0 rows affected (0.30 sec) 方法二:创建表后创建索引 CREATE TABLE `t2` ( `id` int DEFAULT NULL, `name` char(5) DEFAULT NULL ) create index idx_name on t2(name); alter table t3 add index idx_name(name); 唯一索引创建:(可以提高查询效率) 方法一:创建表时创建索引 create table t4 (id int,name char(5),UNIQUE index unidx_name(name)); 方法二:创建表后创建索引 create unique index unidx_name on t5(name); alter table t6 add unique index idx_name(name); 主键索引设置方法 (可以避免回表操作) 方法一:创建表时创建索引 create table t6 (id int,name char(5),primary key (id)); 方法二:创建表后创建索引 alter table t7 add primary key(id); 联合索引设置方法:(可以减少辅助索引回表查询次数) 方法一:创建表时创建索引 mysql> create table t1 ( -> id int, -> name char(5), -> index idx_name(name,age,gender)); Query OK, 0 rows affected (0.30 sec) 方法二:创建表后创建索引 CREATE TABLE `t2` ( `id` int DEFAULT NULL, `name` char(5) DEFAULT NULL ) create index idx_name on t2(name,age,gender); alter table t3 add index idx_name(name,age,gender); 数据库索引应用压测: 测试方法: mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='oldboy' --query="select * from oldboy.t100w where k2='VWlm'" engine=innodb --number-of-queries=2000 -uroot -p123123 -h10.0.0.51 -verbose --concurrency=100 -- 模拟并发压力测试客户端数量(并发量) --iterations=1 -- 压力测试轮训几次 --create-schema -- 对哪个数据库进行访问压力测试 --query -- 压力测试语句 --number-of-queries=2000 -- 发送处理请求次数
3.数据库服务事务机制(稳定性 数据安全性)
bash
如何保证数据安全性 A(原子特性 atomicity) 数据库服务完成一系列任务语句操作时,要么都成功,要么都失败 举例说明: 银行转账,A账户(100),B账户(50),A-->B 50; update 账户表 set 余额=50 where 账户信息=A; -- 成功 -- 失败 update 账户表 set 余额=100 where 账户信息=B; -- 失败 -- 实现事务回滚 C(一致特性 consistency) 数据库出现故障时,故障前有的数据和故障恢复后有的数据必须一致 实现方式: redo:记录内存中的操作信息的 undo:记录回滚信息文件 dblwr:双写文件 I (隔离特性 isolation) 可以对写的隔离:利用锁隔离 可以对读写隔离:利用隔离机制(隔离级别) D (持久特性 durability) 保证数据可以有效保存到磁盘中 数据库事务提交方式 方式一:实现事务自动提交 mysql> select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 1 | +--------------+ 1 row in set (0.00 sec) # autocommit=1(默认): 所有语句执行后,会自动完成事务的提交(将内存数据存储到磁盘--落盘) # autocommit=0 所有语句执行后,不会自动完成事务提交,需要人为执行提交命令(commit) 作为数据库管理者,对数据库进行SQL语句操作管理,建议设置为1 对于业务连接数据库,完成逻辑业务处理过程时,需要设置autocommit=0(保证业务处理的原子性) 方式二:实现事务隐式提交 执行完后不提交紧接着执行DDL DCL语句会触发隐式自动提交事务 隐式回滚:(autocommit=0) 1)当数据库连接会话关闭后,会触发隐式回滚(rollback) 2)当数据库服务进程突然停止,会触发隐式回滚 3)在事务操作过程中,出现事务冲突死锁了,会进行隐式自动回滚;
4、数据库事务隔离级别
bash
# 查看获取当前使用的隔离级别 mysql> select @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | REPEATABLE-READ | # 表示可重复读 +-------------------------+ 1 row in set (0.00 sec) **类型一:RU(READ-UNCOMMITTED 表示读未提交)** 可以读取到事务未提交的数据,隔离性差,会出现脏读(当前内存读),不可重复读,幻读问题; **类型二:RC(READ-COMMITTED 表示读已提交)** 可以读取到事务已提交的数据,隔离性一般,不会出现脏读问题,但是会出现不可重复读,幻读问题; **类型三:RR(REPEATABLE-READ 表示可重复读)**`默认` 可以防止脏读(当前内存读),防止不可重复读问题,防止会出现的幻读问题,但是并发能力较差; 会使用next lock锁进制,来防止幻读问题,但是引入锁进制后,锁的代价会比较高,比较耗费CPU资源,占用系统性能; **类型四:SR(SERIALIZABLE 可串行化)** 隔离性比较高,可以实现串行化读取数据,但是事务的并发度就没有了; 这是事务的最高级别,在每条读的数据上,加上锁,使之不可能相互冲突 # 脏读问题: 脏读主要表示在一个事务窗口中,没有数据修改提交操作前,另一个事务就可以看到内存中数据页的修改; 简单理解:在一个事务窗口中,可以读取到别人没有提交的数据信息; # 不可重复读问题: 不可重复读表示在一个事务中,利用相同的语句多次查询,获取的数据信息是不同的; # 幻读问题: - 当对表中数据进行范围处理时,突然插入了符合条件范围的数据,会造成读取数据异常 transaction_isolation 事务隔离级别配置项(系统变量) RU:会出现脏读 幻读 不可重复读 (并行处理能力最强) RC: 解决脏读问题,但仍然会有幻读 不可重复读问题 RR:解决脏读问题,解决幻读问题,解决不可重复读问题 SR:解决脏读问题,解决幻读问题,解决不可重复读问题 (并行处理能力最弱) 创建测试隔离级别读取的数据: create table t1 ( id int not null primary key auto_increment, a int not null, b varchar(20) not null, c varchar(20) not null ) charset=utf8mb4 engine=innodb; insert into t1(a,b,c) values (5,'a','aa'), (7,'c','ab'), (10,'d','ae'), (13,'g','ag'), (14,'h','at'), (16,'i','au'), (20,'j','av'), (22,'k','aw'), (25,'l','ax'), (27,'o','ay'), (31,'p','az'), (50,'x','aze'), (60,'y','azb'); commit; 设置RU级别: set global transaction_isolation='READ-UNCOMMITTED'; (重新连接数据库) 演示脏读情况: A会话进行操作: update t1 set a=20 where id=3; select * from t1; | 3 | 20 | d | ae | B会话进行操作: | 3 | 20 | d | ae | 演示不可重复读情况: A会话进行操作: update t1 set a=20 where id=3; select * from t1; | 3 | 20 | d | ae | B会话进行查看: mysql> select sum(a) from t1; +--------+ | sum(a) | +--------+ | 315 | +--------+ 1 row in set (0.00 sec) mysql> select sum(a) from t1; +--------+ | sum(a) | +--------+ | 320 | +--------+ 1 row in set (0.00 sec) 幻读情况演示: A会话进行操作: update t1 set b='P8' where a>20; commit; (等B会话插入完) B会话进行操作: insert into t1 values (14,22,'P7','www'); (在A会话修改后进行) 设置RU级别: set global transaction_isolation='READ-COMMITTED'; (重新连接数据库) 验证脏读情况:解决 验证不可重复读情况:存在 验证幻读读情况: 存在 设置RR级别: set global transaction_isolation='REPEATABLE-READ'; (重新连接数据库) 验证脏读情况:解决 验证不可重复读情况:解决(因为应用了MVCC机制原理) 验证幻读读情况: 解决(利用锁机制 RU RC --- 记录锁/行锁 RR 记录锁/间隙锁--临键锁) 设置SR级别: set global transaction_isolation='SERIALIZABLE'; 应用了表锁,解决了并行会话读取数据问题 表锁应用:读锁可以共存 读锁/写锁互斥 写锁/写锁互斥 面试题: 1.不可重复读具体解决的原理,RU、RC不能解决不可重复读问题,RR可以? 因为应用了MVCC机制原理; 2.为什么RR级别下可以解决幻读问题? 因为利用了锁机制,如果是RU、RC级别有记录锁和行锁但是没有临键锁,RR级别存在记录锁,间隙锁,同时出现称为临键锁; ‍```

4、数据库日志备份恢复

1.数据库服务日志管理
bash
# 日志信息查看方法 mysql> show variables like '%log%'; | general_log | OFF | | general_log_file | /data/3306/data/db01.log | | log_error | ./db01.err | | log_bin | ON | | log_bin_basename | /data/3306/data/binlog | | slow_query_log | OFF | | slow_query_log_file | /data/3306/data/db01-slow.log
序号日志名称解释说明
01general_log表示查询日志(通用日志),默认日志`状态处于关闭,可以进行在线调整配置作用:记录了客户端从会话连接开始,执行过的所有SQL语句信息;
02log_error表示错误日志(运行日志),默认日志状态处于激活作用:记录了数据库服务启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息;
03log_bin表示二进制日志(binlog日志),默认日志状态处于激活(8.0之后)作用:记录了所有的DDL语句和DML语句,但是不包括数据库查询语句;语句以事件的形式保存,描述了数据的更改过程,此日志对于灾难时的数据恢复起着极其重要的作用。
04slow_query_log表示慢查询日志,记录了所有执行时间超过参数long_query_time设置值并且扫描记录数小于min_examined_row_limit的所有SQL语句的日志。
1、general_log
bash
数据库服务日志种类: mysql> show variables like '%general_log%'; +------------------+--------------------------+ | Variable_name | Value | +------------------+--------------------------+ | general_log | OFF | | general_log_file | /data/3306/data/db01.log | +------------------+--------------------------+ 1.通用日志:记录登录用户信息/用户登录后操作行为 (日志量大)(了解) general_log=OFF # 默认日志功能处于关闭,建议在需要做调试工作时(功能测试、语句审计)可以打开; general_log_file=/data/3306/data/db01.log # 定义日志文件存储的路径信息,建议日志文件路径与数据存放路径进行分离; # 开启 mysql > set global general_log=1; # 关闭 mysql > set global general_log=0; # 开启后查看日志 [root@db01 ~]#tail -f /data/3306/data/db01.log /usr/local/mysql/bin/mysqld, Version: 8.0.36 (MySQL Community Server - GPL). started with: Tcp port: 3306 Unix socket: /tmp/mysql.sock Time Id Command Argument 2025-06-13T06:11:40.951849Z 8 Query show variables like '%log%' 2025-06-13T06:12:43.135162Z 8 Query show databases 2025-06-13T06:12:49.303587Z 8 Query SELECT DATABASE() 2025-06-13T06:12:49.310405Z 8 Init DB oldboy 2025-06-13T06:12:49.311555Z 8 Query show databases 2025-06-13T06:12:49.312555Z 8 Query show tables 2025-06-13T06:12:49.314584Z 8 Field List t100w 2025-06-13T06:12:57.656062Z 8 Query show tables 2025-06-13T06:13:18.904299Z 8 Query select * from t100w 2025-06-13T06:13:24.302228Z 9 Connect root@localhost on using Socket
2、log_error
bash
2.错误日志:记录数据库启动运行信息/数据库运行过程中错误情况 (关注) log_error= ./db01.err mysql> show variables like '%log_error%'; +----------------------------+----------------------------------------+ | Variable_name | Value | +----------------------------+----------------------------------------+ | binlog_error_action | ABORT_SERVER | | log_error | ./db01.err | | log_error_services | log_filter_internal; log_sink_internal | | log_error_suppression_list | | | log_error_verbosity | 2 | +----------------------------+----------------------------------------+ # 修改日志存储路径(永久配置): [root@xiaoq ~]# vim /etc/my.cnf log_error=/tmp/mysql3306.err -- 配置文件编写完毕后,需要重启数据库服务生效 # 模拟故障,chmod修改权限 [root@db01 ~]#chmod 000 /data/3306/data/ [root@db01 ~]#/etc/init.d/mysqld restart Shutting down MySQL..... ERROR! The server quit without updating PID file (/data/3306/data/db01.pid). ERROR! Failed to stop running server, so refusing to try to start. # 查看错误日志,发现是权限不够导致无法启动 [root@db01 /data/3306/data]#tail -f db01.err 2025-06-13T09:47:26.404576Z 0 [System] [MY-013172] [Server] Received SHUTDOWN from user <via user signal>. Shutting down mysqld (Version: 8.0.36). 2025-06-13T09:47:28.731112Z 0 [Warning] [MY-010909] [Server] /usr/local/mysql/bin/mysqld: Forcing close of thread 10 user: 'root'. 2025-06-13T09:47:28.742649Z 0 [Warning] [MY-010909] [Server] /usr/local/mysql/bin/mysqld: Forcing close of thread 12 user: 'root'. 2025-06-13T09:47:29.755162Z 0 [ERROR] [MY-011945] [InnoDB] Cannot open '/data/3306/data/ib_buffer_pool.incomplete' for writing: Permission denied # chmod修改成755权限 [root@db01 ~]#chmod 755/data/3306/data/
3、binlog
bash
二进制日志(binlog): 1)二进制日志可以记录用户事务操作信息(DDL DML DCL--commit DQL不会记录-select show),可以用于修复数据 2)利用二进制日志文件,可以实现主从同步数据 # 查看是否开启 mysql> show variables like '%log_bin%'; +---------------------------------+------------------------------+ | Variable_name | Value | +---------------------------------+------------------------------+ | log_bin | ON | | log_bin_basename | /data/3306/data/binlog | | sql_log_bin | ON | | sync_binlog | 1 | | binlog_format | ROW | # binlog配置信息 /data/3306/data/binlog:可以配置二进制日志开启或关闭功能/指定二进制日志存储路径 sql_log_bin=1: 是否激活事务记录功能,1表示事务信息会记录到二进制日志 0表示事务信息不会记录到二进制日志在进行数据修复时,可以将记录binlog日志功能临时关闭 sync_binlog: 是否把日志信息写入磁盘文件 binlog binlog_format: 影响DML语句信息记录方式 statement(SBR):表示DML语句如何执行的,就如何记录到binlog日志中便于读取DML语句信息,生成DML语句日志信息量少 row(RBR):表示DML语句执行后,只会将执行后的行数据信息进行记录可以保证数据恢复和主从同步的一致性 mixed(MBR):由数据库服务自行判断,采用是SBR还是RBR格式进行记录DML语句 # 修改为statement测试 # 1.修改binlog_format mysql> set global binlog_format='statement'; Query OK, 0 rows affected, 1 warning (0.00 sec) 重新登录查看 mysql> select @@binlog_format +-----------------+ | @@binlog_format | +-----------------+ | statement | +-----------------+ # 2.查看binlog日志信息记录 mysql> show master status; +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000011 | 157 | | | | +---------------+----------+--------------+------------------+---------------- # 3.创建t2表 mysql> use oldboy mysql> create table t5(id int,date1 time); mysql> insert into t5()values(1,now()); # 4.查看binlog.000011 [root@db01 /data/3306/data]#mysqlbinlog binlog.000011 create table t5(id int,date1 time) # 上面的建表语句 /*!*/; /*!80001 SET @@session.original_commit_timestamp=1749813222685854*//*!*/; /*!80014 SET @@session.original_server_version=80036*//*!*/; /*!80014 SET @@session.immediate_server_version=80036*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; SET TIMESTAMP=1749813222/*!*/; BEGIN /*!*/; insert into t5()values(1,now()) # 上面的插入语句,会把语句原封不动的拿过来 /*!*/; # 修改为row测试 # 1.修改row mysql> set global binlog_format='ROW'; 重新登录查看 # 2.查看binlog日志信息记录 mysql> select @@binlog_format; +------+ | ; | +------+ | ROW | +------+ 1 row in set, 1 warning (0.00 sec) # 3.创建数据 mysql> create table t6(id int,date1 time); mysql> insert into t6()values(1,now()); # 4.查看binlog.000011,显示乱码 create table t4(id int) BINLOG JApMaBMBAAAAMgAAAAcGAAAAAGAAAAAAAAEABm9sZGJveQACdDQAAQMAAQEBAMnb/cA= JApMaB4BAAAAKAAAAC8GAAAAAGAAAAAAAAEAAgAB/wADAAAAQYhi5g== # 5.解码查看内容 [root@db01 /data/3306/data]#mysqlbinlog --base64-output=decode-rows -vvv binlog.000011 create table t6(id int,date1 time) INSERT INTO `oldboy`.`t6` SET @1=1 /* INT meta=0 nullable=1 is_null=0 */ @2='19:39:10' /* TIME(0) meta=0 nullable=1 is_null=0 */ # 这里会发现上面插入语句中的函数在这里有了值 # 总结: 如果有函数的情况下,比如now(),如果是statement的情况下,会把执行语句原封不动的记录下来,因此取到的insert拿到新的库里执行会生成新的 时间而row是把函数执行后的结果拿过来,这样可以保持数据的一致性 # 查看日志: show binary logs; # 显示当前数据库实例中,所有生成binlog日志信息,并且是当前存在的; mysql> show binary logs; +---------------+-----------+-----------+ | Log_name | File_size | Encrypted | +---------------+-----------+-----------+ | binlog.000001 | 180 | No | | binlog.000002 | 157 | No | | binlog.000003 | 157 | No | | binlog.000004 | 180 | No | | binlog.000005 | 667 | No | | binlog.000006 | 21841468 | No | +---------------+-----------+-----------+ mysql>show master status; # 查看主库binlog日志信息记录情况 +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000002 | 1010 | | | | +---------------+----------+--------------+------------------+-------------------+ File: 表示当前数据库实例正在使用binlog日志; Position:事务完成之后的“位置点”用于可以截取日志信息,完成特定数据的修复/还可以便于进行主从同步 create database A-- 200 --- create table t1 --- 300 -- insert xxx --- 400 create database B-- 500 --- create table t1 --- 800 -- insert xxx --- 1200 如果误删除drop table A.t1,通过位置点修复数据 200 create table t1 insert xxx 400 Binlog_Do_DB: 表示指定某个或某几个数据库的事务操作,会记录到binlog日志中; Binlog_Ignore_DB:表示指定某个或某几个数据库的事务操作,不会记录到binlog日志中; # 记录oldboy库的事务操作:修改/etc/my.cnf 如果想记录多个可以这样修改 binlog_ignore_db=school binlog_ignore_db=oldboy

image

bash
重启数据库 [root@db01 ~]#/etc/init.d/mysqld restart Shutting down MySQL. SUCCESS! Starting MySQL.... SUCCESS! 可以看到 mysql> show master status; +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000012 | 157 | oldboy | | | +---------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) # 测试,分别在oldboy库跟world库创建t7表,通过mysqlbinlog binlog.000012查看日志发现只有oldboy的t7表,因为这是白名单

image

bash
# 如果建表插入数据binlog没有记录,第一个通过show master status看是否有黑名单白名单的设置,第二个看一下sql_log_bin是否开启 # 在数据库中查看binlog日志内容 mysql> show binlog events in 'binlog.000011'; +---------------+------+----------------+-----------+-------------+---------------------------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +---------------+------+----------------+-----------+-------------+---------------------------------------------------------------+ | binlog.000011 | 4 | Format_desc | 1 | 126 | Server ver: 8.0.36, Binlog ver: 4 | | binlog.000011 | 126 | Previous_gtids | 1 | 157 | | | binlog.000011 | 157 | Anonymous_Gtid | 1 | 234 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | #日志切割: 1.方式一:采用手动方式进行切割 flush logs; mysqladmin -uroot -p123456 -S /tmp/mysql_xiaoQ.sock flush-logs; 2.方式二:采用自动方式进行切割 利用手动切割的命令信息,编写脚本文件+定时任务 根据日志大小进行切割,默认1g # 指定日志切割大小,当大于配置项指定的大小后,会自动进行日志切割 mysql> select @@max_binlog_size; +-------------------+ | @@max_binlog_size | +-------------------+ | 3073741824 | +-------------------+ 1 row in set (0.00 sec) # 1.设置为30M mysql> set global max_binlog_size=10485760 # 2。查看当前binlog日志 mysql> show master status; +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000013 | 11510290 | oldboy | | | +---------------+----------+--------------+------------------+-------------------+ # 3.扩充数据 mysql> source /root/t100w_oldboy.sql; # 4.发现binlog.000013到达13M后已经停了,并且自己切割了binlog.000014日志 [root@db01 /data/3306/data]#ll -h binlog.000013 -rw-r----- 1 mysql mysql 30M Jun 13 20:31 binlog.000013 [root@db01 /data/3306/data]#ll -rw-r----- 1 mysql mysql 30698964 Jun 13 20:31 binlog.000013 -rw-r----- 1 mysql mysql 11510290 Jun 13 20:32 binlog.000014 日志清理:不能清理正在使用的,要清理存在时间长的 方式一:可以实现自动清理日志信息 mysql> select @@binlog_expire_logs_seconds; # 默认日志切割后存30天后,就会进行删除清理 +------------------------------+ | @@binlog_expire_logs_seconds | +------------------------------+ | 2592000 | expire_logs_days --日志切割后存在多少天后,就会进行删除清理,默认关闭 # 修改时间 [root@db01 /data/3306/data]#date -s 2025-8-14 # 已自动切割了 [root@db01 /data/3306/data]#ll total 6951616 -rwxr-x--- 1 mysql mysql 56 Jun 9 12:34 auto.cnf -rw-r----- 1 mysql mysql 201 Aug 14 00:00 binlog.000016 -rw-r----- 1 mysql mysql 157 Aug 14 00:00 binlog.000017 方式二:可以实现手工清理日志信息 mysql> purge binary logs to 'binlog.000018'; -- 指定binlog18之前的日志都清理掉 mysql> PURGE BINARY LOGS BEFORE '2019-04-02 22:46:26'; -- 根据指定时间信息,将历史binlog日志进行清理 远程备份:(实现数据额外补偿功能) # 创建目录 [root@db02 ~]#mkdir /backup/db-01 [root@db02 ~]#cd /backup/db-01/ [root@db02 ~]#mysqlbinlog -R --host=10.0.0.51 --user=root --password=123456 --raw --stop-never binlog.000009 & -- 以上操作命令信息,可以在单独日志备份服务器上进行执行 # 查看文件备份成功 [root@db02 /backup/db-01]#ll total 603580 -rw-r----- 1 root root 201 Jun 13 21:03 binlog.000018 -rw-r----- 1 root root 157 Jun 13 21:03 binlog.000019 # 如果51数据库有日志切割 mysql> flush logs; Query OK, 0 rows affected (0.54 sec) # 那么备份目录下就会有实时的新log [root@db02 /backup/db-01]#ll total 603584 -rw-r----- 1 root root 201 Jun 13 21:03 binlog.000018 -rw-r----- 1 root root 201 Jun 13 21:05 binlog.000019 -rw-r----- 1 root root 157 Jun 13 21:05 binlog.000020 # 如何利用binlog日志,实现数据修复: 步骤一:创建测试数据 mysql> create database bindb; mysql> use bindb; mysql> create table t1 (id int); mysql> begin; mysql> insert into t1 values(1); mysql> commit; 步骤二:删除数据信息 mysql> drop database bindb; 步骤三:找寻需要恢复数据信息 mysql> show master status; +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000021 | 157 | oldboy | | | +---------------+----------+--------------+------------------+-------------------+ mysql> show binlog events in 'binlog.000021'; 截取恢复数据信息:binlog.000013 157~811 步骤四:在数据库服务器的目录下截取binlog日志有效数据并进行数据恢复 mysqlbinlog --start-position=234 --stop-position=811 binlog.000021 [root@db01 /data/3306/data]#mysqlbinlog --start-position=234 --stop-position=811 binlog.000021 >/backup/xiaoQ.sql 步骤四:导入 [root@db01 ~]#mysql -uroot -p123456 </backup/xiaoQ.sql mysql: [Warning] Using a password on the command line interface can be insecure. # 这个命令也可以 mysql> source /backup/xiaoQ.sql 步骤五:导入成功 mysql> show databases; +--------------------+ | Database | +--------------------+ | bindb | 痛点01:需要恢复数据信息,有些内容对应的binlog日志文件被清理了; 痛点02:需要恢复数据信息,被分散保存在不同的binlog日志文件中,如何过滤出来 痛点03:只有少量损坏的行数据,如果从大量binlog日志中找到需要恢复的数据
4、slow_query_log
bash
慢查询日志 1)给DBA管理员,提供进行数据配置和架构优化的建议; 2)对于运维人员关注慢查询日志,主要确认慢查询日志的数据量,如果相同慢查询语句出现次数过多,可以告知DBA做优化 slow_query_log=0 -- 是否开启慢查询日志记录功能,默认是关闭 slow_query_log_file -- 定义慢查询日志保存路径和名称信息 long_query_time -- 超过参数指定时间语句信息会记录慢查询日志 log_queries_not_using_indexes -- 当没有应用索引的语句会记录到慢查询日志 set global slow_query_log=1; set global long_query_time=0.01; set global log_queries_not_using_indexes=1; # 查询测试 mysql> select * from t100w; # 记录已经有了 [root@db01 ~]#cat /data/3306/data/db01-slow.log /usr/local/mysql/bin/mysqld, Version: 8.0.36 (MySQL Community Server - GPL). started with: Tcp port: 3306 Unix socket: /tmp/mysql.sock Time Id Command Argument # Time: 2025-06-13T13:31:36.035120Z # User@Host: root[root] @ localhost [] Id: 11 # Query_time: 1.888895 Lock_time: 0.000004 Rows_sent: 1000000 Rows_examined: 1000000 use oldboy; SET timestamp=1749820378; select * from t100w; mysqldumpslow -s c -t 3 /data/3306/data/db01-slow.log -- 根据慢查询出现次数,进行综合分析慢查询日志 -s:排序 -c:根据慢查询出现的次数 3:超过3次 r:输出的行数 t:最慢的时间
2、数据库数据备份恢复
1、备份恢复方式方法:

逻辑备份

bash
方法一:采用逻辑备份恢复方式 备份数据量少(50G) 原理:是对数据库中产生的数据语句进行备份 优势:可以灵活备份和恢复数据 缺陷:备份或恢复数据时间较长 逻辑备份恢复:mysqldump 备份:(远程备份/本地备份) 本地备份: mysqldump -uroot -p123456 -S 套接字文件 备份参数 >/backup/mysql_backup.sql 远程备份: mysqldump -u用户 -p密码 -h 数据库服务IP地址 -P端口 备份参数 >/backup/mysql_backup.sql # 全备数据:可以完全备份数据、表结构、函数、存储过程、触发器等,但是不包括用户权限 mysqldump -uroot -p123456 -S /tmp/mysql_xiaoQ.sock -A >/backup/all.sql # 分库备份: mysqldump -uroot -p123456 -S /tmp/mysql_xiaoQ.sock -B school >/backup/db_school.sql mysqldump -uroot -p123456 -S /tmp/mysql_xiaoQ.sock -B school world xiaoA >/backup/db_school_world_xiaoA.sql # 分表备份:school是数据库的名 mysqldump -uroot -p123456 -S /tmp/mysql_xiaoQ.sock school sc >/backup/table_school_sc.sql mysqldump -uroot -p123456 -S /tmp/mysql_xiaoQ.sock school sc student teacher >/backup/table_school_sc_stu_tea.sql 全备和分库备份如何恢复数据: mysql -uroot -p123456 -S /tmp/mysql_xiaoQ.sock </backup/all.sql mysql> source /backup/all.sql 分表备份如何恢复数据: mysql -uroot -p123456 -S /tmp/mysql_xiaoQ.sock school </backup/table_school_sc.sql mysql> use school mysql> source /backup/table_school_sc.sql mysqldump命令备份数据扩展参数 --single-transaction:可以在备份过程中,对备份的数据生成快照信息,备份过程不会影响数据库业务操作 -R: 可以进行数据库存储过程备份 -E: 可以进行数据库计划任务信息备份 --triggers 可以进行数据库触发器需要进行备份

物理备份

bash
方法二:采用物理备份恢复方式 备份数据量大(50G) 原理:是将数据库服务底层数据目录中数据做备份或恢复 优势:备份或恢复数据时间较少 缺陷:不能灵活备份或恢复数据 数据库物理备份: 方式一:直接将数据目录进行备份或压缩(停止数据库服务) mysql> shutdown root@db01 ~]#ps -ef|grep mysql root 11586 2246 0 09:37 pts/2 00:00:00 grep --color=auto mysql # 拷贝整个目录 [root@db01 ~]#cp -r /data/3306/data/ /backup/ # 删除后无法登录 [root@db01 ~]#rm -rf /data/3306/data # 拷贝回来可以登录了 [root@db01 ~]#cp -a /backup/data/* /data/3306/data/ 方式二:利用第三方物理备份工具实现物理热备 www.percona.com/downloads

mmexport1749865660250

bash
xbk物理备份工具可以实现: -- 全备操作,以下针对更换数据库操作 # 1.上传xbk软件程序包 percona-xtrabackup-8.0.28-21-Linux-x86_64.glibc2.17.tar.gz [root@db01 /usr/local]#tar xf mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz # 2.解压mysql包 [root@db01 /usr/local]#tar xf mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz 删除之前做的软连接 [root@db01 /usr/local]#rm -rf mysql 给mysql8.28做软连接 [root@db01 /usr/local]#ln -s mysql-8.0.28-linux-glibc2.12-x86_64 mysql # 3.做软连接 ln -s percona-xtrabackup-8.0.28-21-Linux-x86_64.glibc2.17 xtrabackup # 4.设置环境变量 vim /etc/profile export PATH="$PATH:/usr/local/xtrabackup/bin" # 5.删除之前的数据目录并初始化 [root@db01 /usr/local]#rm -rf /data/3306/data/* [root@db01 /usr/local]#mysqld --initialize-insecure --datadir=/data/3306/data --basedir=/usr/local/mysql/ --user=mysql # 6.更换成现在的配置文件 [root@db01 /usr/local]#mv /etc/init.d/mysqld /tmp [root@db01 /usr/local]#cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld # 7.登录可以看到8.28版本 [root@db01 /usr/local]#/etc/init. d/mysqld start Starting MySQL.Logging to '/data/3306/data/db01.err'. . SUCCESS! [root@db01 /usr/local]#mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.28 MySQL Community Server - GPL # 8.解压xbk [root@db01 /usr/local]#ll drwxrwxr-x 8 root root 101 May 19 2022 percona-xtrabackup-8.0.28-21-Linux-x86_64.glibc2.17 # 9.做xtrabackup软连接 [root@db01 /usr/local]#ln -s percona-xtrabackup-8.0.28-21-Linux-x86_64.glibc2.17/ xtrabackup # 10.添加环境变量,可以补全就是成功 [root@db01 /usr/local/xtrabackup/bin]#tail -1 /etc/profile export PATH="$PATH:/usr/local/mysql/bin:/usr/local/xtrabackup/bin" [root@db01 /usr/local/xtrabackup/bin]#source /etc/profile 全量备份操作: # 1.创建备份目录 [root@db01 ~]#mkdir /data/backup/full -p -- 全备数据保存目录(空目录) # 2.创建测试数据 mysql> source /root/t100w_oldboy.sql; # 3.执行xtrabackup全量备份 [root@db01 /data/backup/full]#xtrabackup --defaults-file=/etc/my.cnf --host=10.0.0.51 --user=root --password=123456 --port=3306 --backup --target-dir=/data/backup/full # --target-dir=/data/backup/full:备份目录 查看 [root@db01 /data/backup/full]#ll total 69684 -rw-r----- 1 root root 475 Jun 14 10:27 backup-my.cnf -rw-r----- 1 root root 157 Jun 14 10:27 binlog.000002 -rw-r----- 1 root root 16 Jun 14 10:27 binlog.index -rw-r----- 1 root root 5914 Jun 14 10:27 ib_buffer_pool -rw-r----- 1 root root 12582912 Jun 14 10:27 ibdata1 drwxr-x--- 2 root root 143 Jun 14 10:27 mysql -rw-r----- 1 root root 25165824 Jun 14 10:27 mysql.ibd drwxr-x--- 2 root root 23 Jun 14 10:27 oldboy drwxr-x--- 2 root root 8192 Jun 14 10:27 performance_schema drwxr-x--- 2 root root 28 Jun 14 10:27 sys -rw-r----- 1 root root 16777216 Jun 14 10:27 undo_001 -rw-r----- 1 root root 16777216 Jun 14 10:27 undo_002 drwxr-x--- 2 root root 68 Jun 14 10:27 world -rw-r----- 1 root root 18 Jun 14 10:27 xtrabackup_binlog_info -rw-r----- 1 root root 105 Jun 14 10:27 xtrabackup_checkpoints -rw-r----- 1 root root 541 Jun 14 10:27 xtrabackup_info -rw-r----- 1 root root 2560 Jun 14 10:27 xtrabackup_logfile -rw-r----- 1 root root 39 Jun 14 10:27 xtrabackup_tablespaces PS: 利用xbk工具可以实现热备,会将磁盘数据和内存数据都会做备份 恢复数据: # 1.关闭数据库 [root@db01 /data/3306]#/etc/init.d/mysqld stop Shutting down MySQL.... SUCCESS! # 2.删除数据模拟故障 [root@db01 /data/3306]#rm -rf /data/3306/data/* # 3.恢复到内存中 [root@db01 /data/backup/full]#xtrabackup --defaults-file=/etc/my.cnf --prepare --target-dir=/data/backup/full prepare -- 表示先将内存备份数据,恢复到内存中 # 4.恢复目录磁盘数据 [root@db01 /data/backup/full]#xtrabackup --defaults-file=/etc/my.cnf --copy-back --target-dir=/data/backup/full # 5.授权 [root@db01 /data/3306]#chown -R mysql.mysql /data/3306/ # 6.启动 [root@db01 /data/3306]#/etc/init.d/mysqld start Starting MySQL.Logging to '/data/3306/data/db01.err'. ... SUCCESS! # 7.查看数据 [root@db01 /data/3306]#mysql -uroot -p123456; 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.28 MySQL Community Server - GPL Copyright (c) 2000, 2022, 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 | +--------------------+ | information_schema | | mysql | | oldboy | | performance_schema | | sys | | world | +--------------------+ 6 rows in set (0.00 sec) -- 增量备份数据 备份操作: rm -rf /data/backup/full/* mkdir /data/backup/full -p mkdir /data/backup/week02 -p mkdir /data/backup/week03 -p # 1.第一次备份:全备 [root@db01 /data/backup/full]#xtrabackup --defaults-file=/etc/my.cnf --host=10.0.0.51 --user=root --password=123456 --port=3306 --backup --parallel=4 --target-dir=/data/backup/full # 2.第二次备份:增量 create database pxb; use pxb create table t1(id int); insert into t1 values(1),(2),(3); commit; [root@db01 /data/backup/full]#xtrabackup --defaults-file=/etc/my.cnf --host=10.0.0.51 --user=root --password=123456 --port=3306 --backup --parallel=4 --target-dir=/data/backup/week02 --incremental-basedir=/data/backup/full --incremental-basedir=/data/backup/full # 跟data/backup/full的目录做对比 --target-dir=/data/backup/week02 # 增量备份的目录 # 经过查看/data/backup/week02目录下多了pxb目录 [root@db01 /data/backup/week02]#ll 。。。 drwxr-x--- 2 root root 45 Jun 14 10:43 pxb 。。。 # 3.第三备份:增量 create database pxb02; use pxb02 create table t1(id int); insert into t1 values(1),(2),(3); commit; [root@db01 /data/backup/full]#xtrabackup --defaults-file=/etc/my.cnf --host=10.0.0.51 --user=root --password=123456 --port=3306 --backup --parallel=4 --target-dir=/data/backup/week03 --incremental-basedir=/data/backup/week02 # 经过查看/data/backup/week03比目录下/data/backup/week02目录多了pxb02目录 [root@db01 /data/backup/week03]#ll drwxr-x--- 2 root root 45 Jun 14 10:46 pxb02 恢复数据: # 1.删除数据模拟故障 [root@db01 /data/3306]#rm -rf /data/3306/data/* # 2.识别全备,增量目录中需要恢复的数据 [root@db01 ~]#xtrabackup --prepare --apply-log-only --target-dir=/data/backup/full -- 识别全备目录中,需要恢复内存的数据/磁盘数据 [root@db01 ~]#xtrabackup --prepare --apply-log-only --target-dir=/data/backup/full --incremental-dir=/data/backup/week02 -- 识别第一次增量目录中,需要恢复内存的数据/磁盘数据 [root@db01 ~]#xtrabackup --prepare --apply-log-only --target-dir=/data/backup/full --incremental-dir=/data/backup/week03 -- 识别第二次增量目录中,需要恢复内存的数据/磁盘数据 # 3.将识别到的数据恢复到内存 [root@db01 ~]#xtrabackup --prepare --target-dir=/data/backup/full -- 将识别全量 第一次增量 第二次增量 所有需要恢复内存的数据,进行内存恢复 # 4.内存恢复到磁盘 [root@db01 ~]#xtrabackup --copy-back --target-dir=/data/backup/full # 5.授权 [root@db01 ~]#chown -R mysql.mysql /data/3306/ # 6.查看数据 [root@db01 /data/3306]#mysql -uroot -p123456; 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 15 Server version: 8.0.28 MySQL Community Server - GPL Copyright (c) 2000, 2022, 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 | +--------------------+ | information_schema | | mysql | | oldboy | | performance_schema | | pxb | | pxb02 | | sys | | world | +--------------------+ 8 rows in set (0.00 sec) 课程作业: 1)练习数据库备份操作过程(逻辑备份 物理备份) 2)binlog日志进行数据恢复的痛点如何处理 3)预习主从同步搭建过程(基础同步 延迟同步 半同步) MHA高可用如何部署(软件安装 环境部署) ProxySQL软件如何安装部署
3、数据库主从同步应用
1、主从同步原理

image

bash
主从集群作用: 1)实现数据实时备份 2)可以利用从库修复数据 3)可以便于构建高可用集群和读写分离集群 数据库主从同步原理: 1)需要在从库编写配置信息 CHANGE MASTER TO (指定主库地址和端口 连接主库用户和密码 以及连接主库binlog文件和位置点) 2)以上配置信息会自动记录到master_info文件中 3)激活主从同步功能(start slave ) 会在从库创建两个线程 Replica has read all relay log; waiting for more updates -- SQL 同步数据信息/回放数据信息 Waiting for an event from Coordinator -- IO 和主库建立会话/接收主库SQL语句 4)利用创建IO线程会通过TCP三次握手主动和主库建立连接,主库验证连接请求通过后,会在主库创建Binlog Dump线程,和从库建立会话、监控binlog日志变化并推送binlog信息 5)从库IO线程接收Binlog dump线程传输的binlog信息,会将binlog信息保存到relay log日志中,/data/3306/data路径可以看到, mysql> show relaylog events in 'db03-relay-bin.000002' 查看详细信息 此时利用IO线程,会更新master_info表中的binlog文件名称和位置点信息 6)SQL线程会加载relaylog中的SQL语句,并进行语句执行 并且会在SQL线程出现异常时,先加载relay log info文件,获取之前SQL线程回放relay log文件的位置点 # 一句话概括: MySQL主从复制中,主库的binlog dump线程将二进制日志发送给从库,从库的I/O线程接收日志并写入中继日志,从库的SQL线 # 程读取中继日志并执行其中的SQL语句实现数据同步。 # 查看主库线程信息,可以看到建立了两个Binlog Dump线程 mysql> show processlist; +----+-----------------+-----------------+------+-------------+-------+-----------------------------------------------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-----------------+-----------------+------+-------------+-------+-----------------------------------------------------------------+------------------+ | 5 | event_scheduler | localhost | NULL | Daemon | 39817 | Waiting on empty queue | NULL | | 27 | repl | 10.0.0.52:59828 | NULL | Binlog Dump | 22607 | Source has sent all binlog to replica; waiting for more updates | NULL | | 30 | repl | 10.0.0.53:54356 | NULL | Binlog Dump | 15009 | Source has sent all binlog to replica; waiting for more updates | NULL | | 34 | root | localhost | NULL | Query | 0 | init | show processlist | +----+-----------------+-----------------+------+-------------+-------+-----------------------------------------------------------------+------------------
2、数据库主从复制实践

方式一:基于位置点进行构建主从集群

bash
# 步骤一:创建主数据库 ......省略..... # 步骤二:创建从数据库,编写配置文件 [root@db02 ~]#cat /etc/my.cnf [mysqld] server_id=2 # 不能和主从server_id数值一致 #重启数据库让配置文件生效 [root@db02 /backup]#/etc/init.d/mysqld restart Shutting down MySQL.... SUCCESS! Starting MySQL.. SUCCESS! # 步骤三:在主库上进行数据备份 [root@db01 ~]#mysqldump -uroot -p123456 -A >/backup/all.sql --source-data --single-transaction source-data: # 会在备份文件中,记录备份结束后的binlog文件和位置点信息(便于建立基于位置点的主从同步) --single-transaction # 这个参数执行过程中不会锁表,可以通过general_log通用日志查看 [root@db02 ~]#head -30 /backup/all.sql CHANGE MASTER TO MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=21104605; -- 备份结束后,最后使用binlog文件是什么,以及备份结束后事务位置点是什么 # 步骤四:在主库上创建同步用户 [root@db01 ~]#create user repl@'%' identified with mysql_native_password by '123456'; [root@db01 ~]#grant replication slave on *.* to repl@'%'; # 步骤五:在从库上恢复数据信息 [root@db01 ~]#scp -rp /backup/all.sql 10.1.12.15:/backup/ [root@db02 ~]#mysql -uroot </backup/all.sql # 步骤六:在从库上开启主从同步功能 配置: CHANGE MASTER TO MASTER_HOST='10.1.12.4', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='123456', MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=2621; # 通过 SHOW MASTER STATUS 查看,导出的sql文件也可以看到 # 在从库激活主从: mysql>start slave; stop slave; # 关闭主从 reset slave all; # 清空配置 # 从库线程状态查看是否生效 mysql>show slave status\G;
内容分类输出内容解释说明
主库的复制信息Master_Host: 192.168.30.101表示连接主库地址信息
- 利于IO线程工作方面Master_User: repl表示连接主库用户信息
Master_Port: 3306表示连接主库端口信息
Connect_Retry: 60表示连接主库重试间隔
Master_Log_File: binlog.000007表示主从同步日志信息
Read_Master_Log_Pos: 1387表示主从同步位置信息
从库的回放信息Relay_Log_File: xiaoQ-01-relay-bin.000002表示中继日志回放文件信息
- 利于SQL线程工作方面Relay_Log_Pos: 683表示中继日志回放位置信息
Relay_Master_Log_File: binlog.000007表示对应主库日志文件信息可以用于帮助判断主从延时的日志量
Exec_Master_Log_Pos: 156表示对应主库日志位置信息可以用于帮助判断主从延时的日志量
从库的线程信息Slave_IO_Running: Yes表示从库同步数据时-IO线程状态
- 利于判断同步线程情况Slave_SQL_Running: Yes表示从库同步数据时-SQL线程状态
Last_IO_Errno: 0表示从库IO线程异常错误代码
Last_IO_Error:表示从库IO线程异常错误原因
Last_SQL_Errno: 0表示从库SQL线程异常错误代码
Last_SQL_Error:表示从库SQL线程异常错误原因
过滤复制的相关信息Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
主从复制的延时情况Seconds_Behind_Master: 0表示主从之间延时秒数信息
延时从库的状态情况SQL_Delay: 0表示延时同步时间间隔情况
SQL_Remaining_Delay: NULL表示最近事件延时剩余时间
主从GTID复制状态情况Retrieved_Gtid_Set:
Executed_Gtid_Set:
bash
# 这样也可以看到CHANGE MASTER TO的配置 mysql> select * from slave_master_info\G *************************** 1. row *************************** Number_of_lines: 33 Master_log_name: binlog.000007 Master_log_pos: 1387 Host: 10.0.0.51 User_name: repl User_password: 123456 Port: 3306 Connect_retry: 60 # 创建删除数据库看是否一致

image

bash
# 在主库查看 mysql> show binlog events in 'binlog.000007'; | binlog.000007 | 1289 | Query | 1 | 1387 | drop database tt /* xid=2849 */ | | binlog.000007 | 1387 | Anonymous_Gtid | 1 | 1464 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | binlog.000007 | 1464 | Query | 1 | 1569 | create database aaa /* xid=3562 */ | | binlog.000007 | 1569 | Anonymous_Gtid | 1 | 1646 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | binlog.000007 | 1646 | Query | 1 | 1747 | drop database aaa /* xid=3567 */ # 在从库查看 mysql> show binlog events in 'binlog.000002 '; | | binlog.000002 | 22503656 | Anonymous_Gtid | 1 | 22503740 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | binlog.000002 | 22503740 | Query | 1 | 22503845 | create database aaa /* xid=491 */ | | binlog.000002 | 22503845 | Anonymous_Gtid | 1 | 22503929 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | binlog.000002 | 22503929 | Query | 1 | 22504030 | drop database aaa /* xid=500 */

方式二:GTID同步复制

bash
GTID(global transaction id)是对于一个已提交事务的唯一编号,并且是一个全局唯一编号(主从复制过程); 是数据库5.6版本开始的一个功能新特性,主要是用于解决主从复制的一致性问题; 复制原理机制: - master节点在更新数据的时候,会在事务前产生GTID信息,一同记录到binlog日志中; - slave节点的io线程将主库推送的binlog写入到本地relay log中; - 然后SQL线程从relay log中读取GTID,设置gtid_next的值为该gtid,然后对比slave端的binlog是否有记录; - 如果有记录的话,说明该GTID的事务已经运行,slave会忽略; - 如果没有记录的话,slave就会执行该GTID对应的事务,并记录到binlog中。 # 实现步骤: # 步骤一:创建主数据库 修改配置文件 [root@db01 /usr/local]#cat /etc/my.cnf ........... gtid-mode=on enforce-gtid-consistency=true # 开启GTID主从同步功能 log-slave-updates=1 # -- 将主库同步binlog信息,也会存储到从库binlog中 配置完重启数据库生效: [root@db01 /usr/local]#/etc/init.d/mysqld restart Shutting down MySQL............. SUCCESS! Starting MySQL................. SUCCESS! 备份数据:会出现建议警告,--set-gtid-purged=OFF [root@db01 /usr/local]#mysqldump -uroot -p123456 -A --single-transaction --source-data >/backup/all01.sql 传输: [root@db01 /usr/local]#scp -rp /backup/all01.sql 10.1.12.15:/backup/ # 步骤二:创建从数据库 编写配置文件 [root@db03 /usr/local]#cat /etc/my.cnf [mysqld] server_id=N ... gtid-mode=on enforce-gtid-consistency=true # 开启GTID主从同步功能 log-slave-updates=1 # 将主库同步binlog信息,也会存储到从库binlog中 初始化: [root@db03 ~]#mysqld --initialize-insecure --datadir=/data/3306/data --basedir=/usr/local/mysql/ --user=mysql 启动数据库: [root@db03 ~]#/etc/init.d/mysqld start Starting MySQL.Logging to '/data/3306/data/db03.err'. ........... SUCCESS! # 清除状态 RESET MASTER; 导入sql文件: [root@db03 ~]#mysql </backup/all.sql # 测试: mysql> create database xxx; Query OK, 1 row affected (0.05 sec) mysql> show master status; +---------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+------------------------------------------+ | binlog.000001 | 157 | | | ac970576-4a4b-11f0-90d2-000c29dc5c04:1-2 | +---------------+----------+--------------+------------------+------------------------------------------+ # 因为开启GTID主从同步功能,所以每完成一个事务都有一个Executed_Gtid_Set编号 # 查看从节点跟主库是一样 mysql> show master status; +---------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+------------------------------------------+ | binlog.000001 | 157 | | | ac970576-4a4b-11f0-90d2-000c29dc5c04:1-2 | +---------------+----------+--------------+------------------+------------------------------------------+ # 主库新增加一个数据库,从库无变化,因为还没设置要推什么,设置下面参数 步骤三:建立主从同步 CHANGE MASTER TO MASTER_HOST='10.1.12.4', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='123456', master_auto_position=1; # 表示从库自己寻找复制同步数据的起点 mysql> start slave; # 已经可以看到最新的节点,最新的数据库 mysql> show master status; +---------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+------------------------------------------+ | binlog.000001 | 346 | | | ac970576-4a4b-11f0-90d2-000c29dc5c04:1-3 | +---------------+----------+--------------+------------------+------------------------------------------+ 1 row in set (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | bbb |

方式三:数据库集群延迟同步复制

bash
作用:可以用于修复误操作的数据信息(误删除 误修改 误添加) # 步骤一:创建好主数据库 ........省略...... # 步骤二:正常建立从库,可以保证正常同步 ........省略..... # 步骤三:调整从库为延时从库 mysql> stop slave sql_thread; # 先关闭sql线程 mysql> show slave status\G; Slave_IO_Running: Yes Slave_SQL_Running: No mysql>change master to master_delay=300; # 调整等待300秒再同步从库 mysql>start slave sql_thread; # 再开启sql线程 # 测试 1.主库创建ppp数据库 mysql> create database ppp; Query OK, 1 row affected (0.00 sec) 2.从库查看日志,发现有创建命令 mysql> show relaylog events in 'db03-relay-bin.000003'; db03-relay-bin.000003 | 528 | Query | 1 | 1069 | create database ppp 3.查看状态,等待300s,还有88s执行,等到0s mysql> show slave status\G; SQL_Delay: 300 SQL_Remaining_Delay: 88 4.数据库ppp从库也有了 mysql> show databases; +--------------------+ | Database | +--------------------+ | ppp | # 数据库修复: 1、模拟主库数据误操作 误删除数据表的操作 mysql> drop table city; Query OK, 0 rows affected (0.97 sec) 2、利用延时从库修复数据 停止SQL线程 mysql>stop slave sql_thread; Slave_IO_Running: Yes Slave_SQL_Running: No mysql>change master to master_delay=0; # 取消延迟,保证正常操作运行 mysql>start slave until sql_before_gtids="780d5da0-4abc-11f0-8940-000c29dc5c04:67"; # 回放到最后一个正确的操作,不回放删除的操作 # 结合relaylog确定回放点,恢复到drop table上面那一条 mysql> show master status; mysql> show relaylog events in 'db03-relay-bin.000002'; | db03-relay-bin.000003 | 633 | Gtid | 1 | 1146 | SET @@SESSION.GTID_NEXT= '780d5da0-4abc-11f0-8940-000c29dc5c04:68' | | db03-relay-bin.000003 | 710 | Query | 1 | 1277 | use `world`; DROP TABLE `city` /* generated by server */ /* xid=1 3、在延迟从库备份数据信息 [root@db03 /usr/local]#mysqldump -uroot world city >/backup/city.sql; 4、恢复从库备份数据信息 mysql> source /backup/city.sql PS: 如果没有延时从库,如何修复数据 1)利用binlog文件修复数据 2)利用备份文件修复数据 3)利用数据闪回工具修复数据 https://github.com/danfengcao/binlog2sql

方式四:增强型半同步主从复制

7c2c81e8db3fa0b0c9eb69eb179bbc4d

bash
主从同步数据传输方式: - 异步方式主从同步数据 - 半同步方式主从同步数据 - 全同步方式主从同步数据 增强半同步主从复制: # 步骤一:在主库和从库安装半同步功能插件 mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; # 在主库安装插件 验证: mysql> show plugins; | rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL | mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; # 在从库安装插件 rpl_semi_sync_slave | ACTIVE | REPLICATION | semisync_slave.so | GPL # 步骤二:编写主库和从库配置文件信息 编写主库配置文件/etc/my.cnf rpl_semi_sync_master_enabled=on # 主库半同步功能启停设置,on为激活设置 rpl_semi_sync_master_timeout=10000 # 主库接收从库确认信息的超时时间设置(单位毫秒) rpl_semi_sync_master_wait_point=after_sync # 确保半同步复制是增强型半同步 重启 [root@db01 ~]#/etc/init.d/mysqld restart Shutting down MySQL........... SUCCESS! Starting MySQL..... SUCCESS! 编写从库配置文件/etc/my.cnf rpl_semi_sync_slave_enabled=on # 从库半同步功能启停设置,on为激活设置 重启 [root@db03 /data/3306/data]#/etc/init.d/mysqld restart Shutting down MySQL... SUCCESS! Starting MySQL...... SUCCESS! # 模拟故障状态 mysql> insert into xxx()values(2); Query OK, 1 row affected (10.00 sec) # 等待10秒后插入,因为设置的默认延迟是10秒,等不带默认降级为异步状态 mysql> start slave io_thread; # 恢复后插入 Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select * from xxx; +------+ | id | +------+ | 1 | | 2 | | 3 | | 4 | +------+

5、数据库集群高可用实战

1、数据库高可用软件介绍
bash
MHA主要有两部分组成:MHA Manager(管理节点) 可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave上。 MHA Node(数据节点) 运行在每台MySQL服务器上
节点信息软件组件作用介绍
MHA Manager(管理节点)masterha_manger用于启动MHA
masterha_check_ssh用于检查MHA的SSH配置互信状况
masterha_check_repl用于检查MySQL复制状态,以及配置信息
masterha_master_monitor用于检测master是否宕机
masterha_check_status用于检测当前MHA运行状态
masterha_master_switch用于控制故障转移(自动或者手动)
masterha_conf_host添加或删除配置的server信息
MHA Node(数据节点)save_binary_logs保存和复制master的二进制日志
apply_diff_relay_logs识别差异的中继日志事件并将其差异的事件应用于其他slave
purge_relay_logs清除中继日志(不会阻塞SQL线程)
2、数据库高可用环境构建
1、服务无法启动解决流程
bash
错误案例: # 1.没有/etc/init.d/mysqld文件, cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld # 拷贝 # 2.启动报错 [root@mysql local]# /etc/init.d/mysqld start Starting MySQL.2025-06-16T17:01:57.875232Z mysqld_safe error: log-error set to /var/log/mariadb/mariadb.log', however file don't exists. Create writable for user 'mysql'. ERROR! The server quit without updating PID file (/var/lib/mysql/mysql.pid). # 没有/etc/my.cnf文件,编写/etc/my.cnf文件 [mysql] socket=/tmp/mysql.sock [mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/3306/data socket=/tmp/mysql.sock
2、高可用环境构建
bash
# 步骤一:高可用系统环境准备 准备数据库主从实例节点 3个节点 一主两从 建立三个实例节点的主从关系 51节点为主52和53节点为从 建立三个实例节点的互信关系 ssh 节点地址 date # 1.所有节点均执行以上操作,因为MHA程序加载数据库命令,会默认在/usr/bin下面进行加载(会影响数据补偿和监控功能) [root@xiaoQ-01 ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog [root@xiaoQ-01 ~]# ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql # 2.配置各节点互信 [root@mysql ~]# rm -rf /root/.ssh [root@mysql ~]# ssh-keygen [root@mysql ~]# cd /root/.ssh [root@mysql .ssh]# mv id_rsa.pub authorized_keys [root@mysql .ssh]# scp -r /root/.ssh 10.0.0.51:/root [root@mysql .ssh]# scp -r /root/.ssh 10.0.0.52:/root [root@mysql .ssh]# scp -r /root/.ssh 10.0.0.53:/root # 步骤二:安装运行高可用服务程序 # 1、在所有主从节点安装-node程序包 yum install perl-DBD-MySQL -y rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm # 2、在管理节点安装-manger程序包 yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes rpm -ivh /usr/local/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm 注意:如果安装过程中显示缺依赖那就是yun镜像问题 1、wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo 2、yum clean all && yum makecache 3、yum install -y perl-Config-Tiny perl-DBD-MySQL perl-DBI \ perl-Log-Dispatch perl-Parallel-ForkManager # 3、管理节点编写配置文件信息 [root@mysql ~]# mkdir -p /etc/mha -- MHA程序目录(存储配置文件) [root@mysql ~]# mkdir -p /var/log/mha/app11 -- MHA程序日志目录 # 4、主库创建:选择mysql_native_password插件 mysql> create user mha@'10.0.0.%' identified with mysql_native_password by 'mha'; mysql> grant all privileges on *.* to mha@'10.0.0.%'; # 5、创建配置文件,根据实际配置修改 cat > /etc/mha/app1.cnf <<EOF [server default] manager_log=/var/log/mha/app1/manager -- MHA的工作日志设置 manager_workdir=/var/log/mha/app1 -- MHA的工作目录 master_binlog_dir=/data/3306/data/ -- 主库的binlog目录 user=mha -- 监控用户,利用此用户连接各个节点,做心跳检测(主要是检测主库的状态) password=mha -- 监控密码 ping_interval=2 -- 心跳检测的间隔时间 repl_password=123456 -- 复制密码 repl_user=repl -- 复制用户(用于告知从节点通过新主同步数据信息的用户信息) ssh_user=root -- ssh互信的用户(可以利用互信用户从主库scp获取binlog日志信息,便于从库进行数据信息补偿) [server1] -- 节点信息.... hostname=10.0.0.51 port=3306 [server2] hostname=10.0.0.52 port=3306 #candidate_master=1 [server3] hostname=10.0.0.53 port=3306 EOF # 6、检查MHA服务运行环境 [root@mysql ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf [info] All SSH connection tests passed successfully # 如果验证不通过,底层之间互相的免密要没成功,重新做一遍 # 7、检查主从状态 [root@mysql ~]# masterha_check_repl --conf=/etc/mha/app1.cnf MySQL Replication Health is OK. # 8、开启MHA-manager,在管理管理节点执行 [root@db04 mha]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null> /var/log/mha/app1/manager.log 2>&1 & # 9、查看MHA状态 [root@db04 mha]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:21953) is running(0:PING_OK), master:10.0.0.51

edc976427be776d292b51132d80dd0d1

bash
# 报错,显示检测没有活着的节点 masterha_check_repl一直显示失败,部署的一主二从一管理节点,在管理节点执行检查主从状态的时候报错了,前面用GTID做的主从同步,SSH免密钥 也打通了。最后发现是根据配置文件主节点跟从节点都创建了mha用户,但是host跟密码插件主从不一致导致的。 通过mysql> select user,host,plugin from mysql.user;删除从库配置,重新配置。运行成功
bash
# 步骤三:MHA服务功能配置 # 1、解压后的\mha\mha_script拖拽到/usr/local/bin目录下 [root@db04 bin]# pwd /usr/local/bin [root@db04 bin]# ll -rw-r--r--. 1 root root 2230 10月 10 2022 master_ip_failover -rw-r--r--. 1 root root 10312 10月 10 2022 master_ip_online_change -rw-r--r--. 1 root root 789 10月 10 2022 mha_check.sh -rw-r--r--. 1 root root 114178 2月 14 2023 mha.zip -rw-r--r--. 1 root root 2238 10月 10 2022 send_report # 1)先完成配置VIP地址漂移功能: [root@db04 bin]#chmod +x /usr/local/bin/* [root@db04 bin]#vim master_ip_failover 13 my $vip = '10.0.0.50/24'; 14 my $key = '1'; 15 my $if = 'ens33'; 16 my $ssh_start_vip = "/sbin/ifconfig $if:$key $vip"; 17 my $ssh_stop_vip = "/sbin/ifconfig $if:$key down"; 18 my $ssh_Bcast_arp= "/sbin/arping -I $if -c 3 -A 10.0.0.50"; # 修改配置文件 [root@db04 bin]# vim /etc/mha/app1.cnf [server default] master_ip_failover_script=/usr/local/bin/master_ip_failover # 重启MHA服务 [root@db04 bin]# masterha_stop --conf=/etc/mha/app1.cnf [root@db04 bin]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null> /var/log/mha/app1/manager.log 2>&1 & # 核实此时的MHA的主库节点 [root@xiaoQ-03 bin]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:103046) is running(0:PING_OK), master:10.0.0.51 # 手工在主库上添加VIP [root@db01 /usr/local]#yum install -y net-tools # 先安装这个命令 [root@db01 /usr/local]#ifconfig ens33:1 10.0.0.50/24 # 在主库节点手工添加vip地址信息 # 2)再实现高可用故障切换报警功能 [root@db04 bin]# vim send_report 28 my $smtp='smtp.163.com'; -- smtp服务器地址域名 29 my $mail_from='13406161615@163.com'; -- 发件箱信息配置 30 my $mail_user='13406161615@163.com'; -- 用户名 QQ号 31 my $mail_pass='BVdLmV8HfZfMCMeV'; -- 邮箱授权码 32 my $mail_to='1360821977@qq.com'; or my $mail_to=['to1@qq.com','to2@qq.com']; # 修改配置文件 vim /etc/mha/app1.cnf [server default] report_script=/usr/local/bin/send_report # 3)最后高可用额外补偿功能配置 mkdir -p /data/binlog_server/ chown -R mysql.mysql /data/* cd /data/binlog_server binlog.000005 # 在备份服务器同步binlog [root@db04 bin]# cd /data/binlog_server [root@db04 binlog_server]# mysqlbinlog -R --host=10.0.0.51 --user=mha --password=mha --raw --stop-never binlog.000005 & [root@db04 binlog_server]# ll 总用量 4 -rw-r-----. 1 root root 373 6月 17 14:43 binlog.000005 [root@db04 binlog_server]# vim /etc/mha/app1.cnf [binlog1] no_master=1 # 不参与竞选 hostname=10.0.0.54 # 将日志额外补偿到哪个主机上 master_binlog_dir=/data/binlog_server/ # 保存额外补偿的路径 # 重启mha功能 [root@db04 binlog_server]#masterha_stop --conf=/etc/mha/app1.cnf [root@db04 binlog_server]#nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null> /var/log/mha/app1/manager.log 2>&1 & [root@db04 binlog_server]# masterha_check_status --conf=/etc/mha/app1.cnf # 连接vip测试

image

3、测试主库宕机
bash
# 主库停止后,vip飘移到db02 [root@db01 /usr/local]#/etc/init.d/mysqld stop Shutting down MySQL........... SUCCESS! [root@db02 ~]#ip a 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:d9:45:58 brd ff:ff:ff:ff:ff:ff inet 10.0.0.52/24 brd 10.0.0.255 scope global noprefixroute ens33 inet 10.0.0.50/24 brd 10.0.0.255 scope global secondary ens33:1 # 会看到master成了52 [root@db04 binlog_server]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:25347) is running(0:PING_OK), master:10.0.0.52 # 这里也能看到 mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for source to send event Master_Host: 10.0.0.51

image

image

正常收到邮件

image

4、高可用集群架构修复
bash
# 步骤一:根据主节点错误日志信息修复数据 主库可以恢复运行 ... -- 恢复主库变为从 主库无法恢复运行 --- 重新创建新的主库实例 --- 加载原主库备份数据信息 -- 新主库变为从库 # 恢复完后先成为从库,数据恢复一段时间后再变为主库 1、启动数据库 [root@db01 /usr/local]#/etc/init.d/mysqld start Starting MySQL.. SUCCESS! 2、添加配置 CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='123456', master_auto_position=1; 3、查看主从配置关系 mysql> show slave status\G; Slave_IO_Running: Yes Slave_SQL_Running: Yes # 步骤二:将主库配置信息添加的MHA配置文件中 [root@db04 bin]# vim /etc/mha/app1.cnf [server1] hostname=10.0.0.51 port=3306 # 步骤三:重新设置额外补偿功能 cd /data/binlog_server \rm -rf ./* mysqlbinlog -R --host=10.0.0.52 --user=mha --password=mha --raw --stop-never binlog.000001 & [root@db04 binlog_server]# ll 总用量 8 -rw-r-----. 1 root root 523 6月 17 15:45 binlog.000001 # 步骤四:进行互信和主从同步检查 masterha_check_ssh --conf=/etc/mha/app1.cnf masterha_check_repl --conf=/etc/mha/app1.cnf # 步骤五:重新运行启动MHA服务 nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null> /var/log/mha/app1/manager.log 2>&1 & 检查 [root@db04 binlog_server]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:26222) is running(0:PING_OK), master:10.0.0.52
3、数据库高可用功能配置
01 MHA软件启动

根据启动命令,分析MHA软件启动原理:

bash
[root@db04 mha]#nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null> /var/log/mha/app1/manager.log 2>&1 & remove_dead_master_conf: # 参数表示在主节点出现宕机情况时,将会从集群中被踢出,即从配置文件中删除掉故障节点; ignore_last_failover: # 默认MHA服务是不能频繁进行故障切换的,需要有一定的间隔时间,加此参数表示忽略切换的间隔时间; < /dev/null>: # 避免产生交互信息而等待
02 MHA实现监控

利用MHA启动脚本文件masterha_manager​会自动调用监控脚本文件masterha_master_monitor​,并且每隔配置文件指定时间;

ping_interval=2​ 进行脚本监控一次,从而判断主节点是否处于存活状态,连续4次还没有主库心跳,即说明主库宕机;

bash
# 监控脚本验证主节点存活方法 [root@xiaoQ-03 ~]# mysql: [Warning] Using a password on the command line interface can be insecure. +-------------------+ | user() | +-------------------+ | mha@xiaoQ-03 | +-------------------+ # MHA怎么做监控:通过管理用户连接到主节点做一个查询语句,能返回主库还或者,不能返回就说明挂了,就会进行选主
03 MHA选主过程

在MHA中进行选主时,根据选主源码文件信息分析,主要会利用到四个数组:alive latest pref bad,并且会识别节点编号信息;

在进行选主时,主要会关注竞选新主节点的日志量、以及是否设置candidate_master参数配置信息;

数组信息简述作用说明
alive存活数组主要用于探测存活的节点状态;当主库宕机后,探测的就是两个从库节点
latest最新数组表示获取日志最新的从库信息,即数据量最接近主库的从库(根据GTID信息 或 position信息)
pref备选数组在数组中具有candidate_master参数判断条件,此参数可以放入配置文件节点中,便于节点优先选择为新主
bad不选数组如果设定了参数:no_master=1,表示相应节点不参与竞选主;如果设定了参数:log_bin=0(二进制日志没开),表示相应节点不参与竞选主;如何设定了参数:check_slave_delay,检查从库延迟主库100M数据信息日志量,表示节点不参与竞选主
bash
MHA选主判断总结(利用if判断选主的情况) - 循环对比latest数组和pref数组的slave,如果存在相同的slave,并且这个slave不在bad数组当中,该slave会被推选为新的master DB02节点即满足latest数组信息,又满足perf数组信息,但不满足bad数据信息,即会被选为新主,有多个按照号码顺序选举; - 如果pref和bad数组当中的个数为0,则选择latest数组当中的第一个slave为master; DB02节点没有candidate_master参数配置,又没有不选数组里的三种情况配置,即db02恰好是latest,为新主; - 循环对比alive数组和pref数组当中的slaves,如果有一个slave相同,并且不在bad数组当中,该节点就会成为新的master; DB02节点即不满足latest,也不满足bad,但是满足pref,也会被选择作为新主; - 循环latest数组,如果又循环到slave不在bad数组当中,这个slave就会成为master,就算添加了candidate_master=1参数; 该slave也不一定会成为主库; DB02节点即满足latest数组,不是bad数组,也会成为新的主; - 从活着的slave当中进行循环,如果循环到slave不在bad数组当中,那么这个slave就会成为主库; DB02节点是活着的,不满足bad,也可以成为新的主; - 如果进行了多次选择都找不到主库,那么主库选择失败,failover失败;
04 MHA数据补偿
bash
# 如果成为新主,而数据量相差太大会进行数据补偿,数据补偿之后成为新主,防止数据差异量太大 在进行数据补偿之前,需要让新主库与原有宕机主库进行对比,获悉需要补偿的数据量情况,即对比差的数据日志量信息; 然后可以从binlog日志中,进行补充数据信息的截取,随之进行数据信息补偿,但是有种特殊情况,若原有主库无法访问了; 所以进行数据补偿操作,也需要分各种情景进行处理: - 原主库SSH连接正常: 各个从节点自动调用:`save_binary_logs`脚本文件,立即保存缺失部分的bin_log,到各节点/var/tmp/目录; - 原主库SSH连接异常: 各个从节点自动调用:`apply_diff_relay_logs`脚本文件,进行relay_log日志差异信息补偿; - 额外特殊数据补充:(利用主库日志冗余机制) MHA提供了binlog_server功能,可以实时拉取主库的binlog日志到备份节点,从而进行数据额外补偿;
4、主从同步常见问题
bash
01 主从同步常见异常问题 show slave status\G Slave_IO_Running: Yes Slave_SQL_Running: Yes -- 以上信息,只要有一个不为YES,都表示主从同步异常 Last_IO_Errno: 0 -- IO线程异常错误编码 Last_IO_Error: -- 详细介绍IO线程出现问题错误说明 Last_SQL_Errno: 0 -- SQL线程异常错误编码 Last_SQL_Error: -- 详细介绍SQL线程出现问题错误说明 IO线程常见错误: 1)显示状态为 connecting (连接不上) - 连接地址、端口、用户、密码信息不对可能会导致连接异常; - 防火墙安全策略阻止连接建立、网络通讯配置异常影响连接建立; - 到达数据库服务连接数上限,造成主从连接产生异常; mysql> select @@max_connections; max_connections=151 # 数据库服务并发连接数的最大上限 mysql> set global max_connections=4; # 修改连接数为4 mysql> show processlist # 查看进程 通过kill id(连接会话编号) -- 将休眠状态的占用连接数的会话做清理 2)显示状态为 no - IO线程在请求日志信息失败,有可能binlog日志信息被无意清理了; 方法一:可以重新指定同步位置点 (仅能恢复主从同步,但可能会出现主从不一致) 方法二:备份主库数据信息,重新指定同步位置点 - IO线程在请求主库建立连接时,有可能主从配置的标识信息重复冲突了; 主从之间:server_id信息不能一致 server_uuid(auto.cnf删除)信息也不能一致 SQL线程常见错误: 1)显示状态为 no - 读取的relaylog文件被清理删除 方法一:备份主库数据信息,重新指定同步位置点 - 利用SQL线程回放relaylog日志中语句失败 从库中有冲突数据信息(操作数据库节点出错 主从高可用故障转移) 解决问题方式一:可以将冲突数据信息删除 解决问题方式二:忽略数据冲突错误信息 sql_slave_skip_counter -- 忽略指定错误数量 ??? slave_skip_errors -- 忽略指定错误编码 PS:控制从库只能读取数据,不能添加数据信息 read_only=1 -- 限制普通用户, 不能在从库中添加 修改 删除数据; super_read_only=1 -- 限制管理员用户,不能在从库中添加 修改 删除数据;
5、数据库高可用手工切换
1、MHA高可用集群如何实现手工切换主备节点
bash
功能描述:此脚本可以在线进行切换时,自动锁定原主库,以及将原主库VIP地址进行自动飘移; 编写应用切换脚本文件信息: # 步骤一:编写master_ip_online_change_script脚本文件 cd /usr/local/bin/ [root@db04 bin]# vim master_ip_online_change 21 my $vip = "10.0.0.50/24"; 22 my $key = "1"; 23 my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip"; 24 my $ssh_stop_vip = "/sbin/ifconfig ens33:$key $vip down"; 25 my $ssh_Bcast_arp= "/sbin/arping -I ens33 -c 3 -A 10.0.0.50"; 需要在配置文件中加载此脚本文件: [root@db04 bin]#vim /etc/mha/app1.cnf [root@db04 bin]#master_ip_online_change_script=/usr/local/bin/master_ip_online_change # 步骤二:需要停止MHA服务状态,防止出现多个vip [root@db04 bin]# masterha_stop --conf=/etc/mha/app1.cnf Stopped app1 successfully. [2]+ 退出 1 nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1(工作目录:/data/binlog_server) (当前工作目录:/usr/local/bin) [root@db04 bin]# masterha_check_status --conf=/etc/mha/app1.cnf app1 is stopped(2:NOT_RUNNING). # 检查主从节点线程是否正常 [root@db04 bin]# masterha_check_repl --conf=/etc/mha/app1.cnf Failed to save binary log: Binlog not found from /data/binlog_server/! If you got this error at MHA Manager, please set "master_binlog_dir=/path/to/binlog_directory_of_the_master" correctly in the MHA Manager's configuration file and try again. at /usr/bin/save_binary_logs line 123. eval {...} called at /usr/bin/save_binary_logs line 70 main::main() called at /usr/bin/save_binary_logs line 66 Tue Jun 17 18:31:46 2025 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln161] Binlog setting check failed! Tue Jun 17 18:31:46 2025 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln267] Binlog server configuration failed. Tue Jun 17 18:31:46 2025 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln427] Error happened on checking configurations. at /usr/bin/masterha_check_repl line 48. Tue Jun 17 18:31:46 2025 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln525] Error happened on monitoring servers. Tue Jun 17 18:31:46 2025 - [info] Got exit code 1 (Not master dead)'. # 禁用远程补偿功能 [root@db04 bin]# vim /etc/mha/app1.cnf #[binlog1] #hostname=10.0.0.54 #master_binlog_dir=/data/binlog_server/ #no_master=1 # 再次测试成功 [root@db04 bin]# masterha_check_repl --conf=/etc/mha/app1.cnf IN SCRIPT TEST====/sbin/ifconfig ens33:1 down==/sbin/ifconfig ens33:1 10.0.0.50/24=== Checking the Status of the script.. OK Tue Jun 17 18:39:01 2025 - [info] OK. Tue Jun 17 18:39:01 2025 - [warning] shutdown_script is not defined. Tue Jun 17 18:39:01 2025 - [info] Got exit code 0 (Not master dead). MySQL Replication Health is OK. # 步骤三:进行MHA服务手工在线切换: [root@db04 bin]# masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=alive --new_master_host=10.0.0.51 --orig_master_is_new_slave --running_updates_limit=10000 ...省略部分信息... It is better to execute FLUSH NO_WRITE_TO_BINLOG TABLES on the master before switching. Is it ok to execute on 192.168.30.102(192.168.30.102:3306)? (YES/no): yes -- FLUSH NO_WRITE_TO_BINLOG TABLES 命令在原有主库节点需要再执行一次; Starting master switch from 192.168.30.102(192.168.30.102:3306) to 192.168.30.101(192.168.30.101:3306)? (yes/NO): yes Tue Jun 17 18:29:30 2025 - [info] 10.0.0.51: Resetting slave info succeeded. Tue Jun 17 18:29:30 2025 - [info] Switching master to 10.0.0.51(10.0.0.51:3306) completed successfully. # 查看db02的vip已经没了 [root@db02 ~]#ip a # db01已经有vip [root@db01 /usr/local]#ip a inet 10.0.0.50/8 brd 10.255.255.255 scope global ens33:1 # db03已经看到主节点是10.0.0.51 mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for source to send event Master_Host: 10.0.0.51 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: binlog.000006 Read_Master_Log_Pos: 213 Relay_Log_File: db03-relay-bin.000002 Relay_Log_Pos: 367 Relay_Master_Log_File: binlog.000006 Slave_IO_Running: Yes Slave_SQL_Running: Yes
6、mysql数据库读写分离架构
1、概述介绍
bash
在应用数据库主从架构或者数据库冗余架构时,都可以有效保证数据库逻辑故障或物理故障对业务的影响; 但是,这两种架构进行应用时,业务访问过程只是访问主数据库节点,进行读写操作,当并发量大时无型中会对主节点造成不小压力; 因此,可以设计一种新型的业务访问架构方式,可以实现将写数据请求发送到主节点,将读数据请求发送到从节点; 最终,可以有效减少主节点的业务访问压力,这样设计的数据库架构称之为读写分离架构;
2、读写分离架构搭建
bash
# 数据库中间件,所有的请求通过中间件过度,实现分布式存储 部署过程:ProxySQL # 步骤一:下载安装软件程序包 [root@db04 local]#rpm -ivh proxysql-2.4.6-1-centos7.x86_64.rpm 启动服务 [root@db04 local]#systemctl start proxysql 查看服务 [root@db04 local]#netstat -lntup Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:6032 0.0.0.0:* LISTEN 83020/proxysql tcp 0 0 0.0.0.0:6033 0.0.0.0:* LISTEN 83020/proxysql 6032 -- 作为管理员,可以登录访问proxySQL程序,做配置的端口 (管理端口) 6033 -- 作为客户端,可以登录访问proxySQL程序,向程序发送SQL请求(业务端口) #登录 [root@db04 local]#mysql -uadmin -padmin -h127.0.0.1 -P6032 # 步骤二:进行proxysql配置 配置方法:配置层次结构 保存配置:内存配置表---save---磁盘disk 应用配置:内存配置表--load---runtime_表

image

bash
ProxySQL整套配置系统分为三层: 第一层:RUNTIME: 代表proxySQL当前正在使用的配置,无法直接修改此配置,必须要从下一层(MEM层)load加载进来; 第二层:MEMORY(主要修改的配置表) memory层上面连接runtime层,下面连接disk持久化存储层; 在这层可以在线操作ProxySQL配置,随意进行修改,不会影响生产环境,确认正常之后再加载到runtime和持久化保存到磁盘上 具体修改操作方法为:insert、update、delete、select; 第三层:DISK/CFG FILE 持久化配置信息,重启时可以从磁盘快速加载回来;
bash
# 配置proxySQL内存表: 1:mysql_replication_hostgroups (配置读组信息 和写组信息) 主库节点 -- 写组 10 read_only=0 51 从库节点 -- 读组 20 read_only=1 51 52 53 proxySQL会根据server的read only的取值将服务器进行分组: - read_only=0的server,即master会被分到编号为10的写组; - read_only=1的server,即slave会被分到编号为20的读组; # 所以需要将从库设置:set global read_only=1 # 插入写组编号10,读组编号20 mysql> insert into mysql_replication_hostgroups(writer_hostgroup,reader_hostgroup,comment) values(10,20,'proxy'); mysql> load mysql servers to runtime; # 将配置加载到运行时层,使其立即生效 mysql> save mysql servers to disk; # 保存配置 2:mysql_servers (设置组中的成员节点) insert into mysql_servers(hostgroup_id,hostname,port) values (10,'10.0.0.50',3306); # 写vip地址,因为如果高可用有故障,写的请求没法转发。如果是vip会飘移到别的节点 insert into mysql_servers(hostgroup_id,hostname,port) values (20,'10.0.0.51',3306); insert into mysql_servers(hostgroup_id,hostname,port) values (20,'10.0.0.52',3306); insert into mysql_servers(hostgroup_id,hostname,port) values (20,'10.0.0.53',3306); mysql> load mysql servers to runtime; mysql> save mysql servers to disk; mysql> select * from mysql_servers; +--------------+-----------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | hostgroup_id | hostname | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment | +--------------+-----------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | 20 | 10.0.0.50 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 20 | 10.0.0.51 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 20 | 10.0.0.52 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 20 | 10.0.0.53 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | # 创建监控用户,并开启监控 # 利用监控用户对后端节点的运行情况进行监控数据同步,一旦后端节点出现数据同步异常,就不要再向故障节点发送相应业务请求; 3:global_variables (配置监控用户信息以及密码信息),主库创建 create user monitor@'%' identified with mysql_native_password by '123'; grant replication client on *.* to monitor@'%'; # 创建完用户,从节点也要检查 update global_variables set variable_value='monitor' where variable_name='mysql-monitor_username'; update global_variables set variable_value='123' where variable_name='mysql-monitor_password'; load mysql variables to runtime; save mysql variables to disk; # 查看监控信息 mysql> select * from mysql_server_connect_log; | 10.0.0.50 | 3306 | 1750163517508452 | 2536 | NULL | | 10.0.0.50 | 3306 | 1750163576273021 | 1973 | NULL | | 10.0.0.51 | 3306 | 1750163576657593 | 2311 | NULL | | 10.0.0.53 | 3306 | 1750163577041535 | 3993 | NULL | | 10.0.0.52 | 3306 | 1750163577426029 | 1469 | NULL | | 10.0.0.52 | 3306 | 1750163636275246 | 1281 | NULL | | 10.0.0.51 | 3306 | 1750163636691953 | 2082 | NULL | | 10.0.0.50 | 3306 | 1750163637108393 | 2216 | NULL 4: mysql_users (创建应用用户信息) # 创建数据库应用用户信息,利用应用用户,可以使proxySQL进行数据库节点的操作管理; create user root@'%' identified with mysql_native_password by '123'; grant all on *.* to root@'%'; # 在proxy_sql执行 mysql> insert into mysql_users(username,password,default_hostgroup) values('root','123',10); load mysql users to runtime; save mysql users to disk; 5:mysql_query_rules (定义读写分离策略),根据匹配原则进行分配 insert into mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) values (1,1,'^select.*for update$',10,1); # 写组 insert into mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) values (2,1,'^select',20,1); # 读组 load mysql query rules to runtime; save mysql query rules to disk; # 验证是否可以实现读写分离: [root@db04 redis]#mysql -uroot -p123 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit"; # 写 mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 1 | +-------------+ mysql -uroot -p123 -P6033 -h127.0.0.1 -e "select @@server_id;commit"; # 读 #轮询返回server_id [root@db04 redis]# mysql -uroot -p123456 -P6033 -h127.0.0.1 -e "select @@server_id;commit"; mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 2 | +-------------+ [root@db04 redis]# mysql -uroot -p123456 -P6033 -h127.0.0.1 -e "select @@server_id;commit"; mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 1 | +-------------+ [root@db04 redis]# mysql -uroot -p123456 -P6033 -h127.0.0.1 -e "select @@server_id;commit"; mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 3 | +-------------+

基于端口进行读写分离路由

bash
# 步骤四:读写分离架构软件配置扩展 # 修改proxySQL监听SQL流量的端口号,监听多端口信息 mysql>set mysql-interfaces='0.0.0.0:6033;0.0.0.0:6034'# 使监听端口配置信息生效 mysql>save mysql variables to disk; # 重启服务 [root@db04 redis]#systemctl restart proxysql # 查看是否有多个端口 [root@db01 /usr/local]#netstat -tnulp|grep proxysql [root@db04 redis]# ss -tnulp|grep proxysql tcp LISTEN 0 128 *:6032 *:* users:(("proxysql",pid=37141,fd=43)) tcp LISTEN 0 128 *:6033 *:* users:(("proxysql",pid=37141,fd=35)) tcp LISTEN 0 128 *:6033 *:* users:(("proxysql",pid=37141,fd=34)) tcp LISTEN 0 128 *:6033 *:* users:(("proxysql",pid=37141,fd=33)) tcp LISTEN 0 128 *:6033 *:* users:(("proxysql",pid=37141,fd=31)) tcp LISTEN 0 128 *:6034 *:* users:(("proxysql",pid=37141,fd=39)) tcp LISTEN 0 128 *:6034 *:* users:(("proxysql",pid=37141,fd=38)) tcp LISTEN 0 128 *:6034 *:* users:(("proxysql",pid=37141,fd=37)) tcp LISTEN 0 128 *:6034 *:* users:(("proxysql",pid=37141,fd=36)) # 设定相应读写分离路由规则 delete from mysql_query_rules; -- 为了测试效果,先清空已有规则信息 insert into mysql_query_rules(rule_id,active,proxy_port,destination_hostgroup,apply) values(1,1,6033,10,1),(2,1,6034,20,1); load mysql query rules to runtime; save mysql query rules to disk; #测试 mysql -uroot -p123456 -P6033 -h127.0.0.1 -e "select @@server_id;" # 写,只有一个server_id mysql -uroot -p123456 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit" # 写,只有一个server_id mysql -uroot -p123456 -P6034 -h127.0.0.1 -e "begin;select @@server_id;commit" # 读,全部server_id [root@db04 redis]# mysql -uroot -p123456 -P6034 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 3 | +-------------+ [root@db04 redis]# mysql -uroot -p123456 -P6034 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 1 | +-------------+ [root@db04 redis]# mysql -uroot -p123456 -P6034 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 2 | +-------------+

基于用户进行读写分离路由

bash
# 确认有用户,主库创建用户 mysql> CREATE USER 'write'@'%' IDENTIFIED WITH mysql_native_password BY '123'; mysql> GRANT ALL ON *.* TO 'write'@'%'; mysql>create user reader@'%' identified with mysql_native_password by '123'; mysql>grant all on *.* to reader@'%'; # mysql_users添加用户 > insert into mysql_users(username,password,default_hostgroup) values ('write','123',10),('reader','123',20); > load mysql users to runtime; > save mysql users to disk; # 测试,先删除原有数据 > delete from mysql_query_rules; # insert into mysql_query_rules(rule_id,active,username,destination_hostgroup,apply) values (1,1,'write',10,1),(2,1,'reader',20,1); # mysql_query_rules 添加数据 mysql>INSERT INTO mysql_query_rules (active, match_digest, destination_hostgroup, apply) VALUES (1, '^START TRANSACTION READ ONLY', 20, 1); > load mysql users to runtime; > save mysql users to disk; # 读测试 [root@db04 redis]# mysql -ureader -p123 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 2 | +-------------+ [root@db04 redis]# mysql -ureader -p123 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 3 | +-------------+ [root@db04 redis]# mysql -ureader -p123 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 1 | +-------------+ # 写测试 [root@db04 redis]# mysql -uwrite -p123 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 1 | +-------------+ [root@db04 redis]# mysql -uwrite -p123 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 1 | +-------------+ [root@db04 redis]# mysql -uwrite -p123 -P6033 -h127.0.0.1 -e "begin;select @@server_id;commit" mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 1 | +-------------+
3、读写分离配置过程总结:
步骤操作说明涉及数据表信息涉及操作信息
01设置从库只读模式read_only=1
02添加主机组信息mysql_replication_hostgroups
03添加主机组节点信息mysql_servers
04添加用户信息(监控用户 应用用户)global_variablesmysql_users
05添加读写分离规则mysql_query_rules

2、Redis

1、Redis服务概述介绍

bash
Redis是数百万开发人员使用的开源内存数据存储服务,经常被用于数据库、缓存、数据流引擎、以及消息中间件; 简单理解:Redis 是完全开源的,遵守BSD协议,是一个高性能的 key-value 数据库; Redis服务属于NoSQL数据库产品系列,早期出现在网站架构中,主要是配合关系型数据库(RDBMS)完成某些工作任务的; - 对于关系型数据库主要负责核心业务数据的存储和查询; - 对于非关系性数据库主要作为配合数据库存储和查询的缓存业务; 对于非关系性数据库也是存在很多种类的:Redis(缓存型)、MongoDB(文档型)、ES(日志型)... 缓存服务产品-Redis - Redis具有丰富的数据类型可以进行应用,其中包括:key-value、list、set、zset、hash等数据结构类型; - Redis具有持久化存储能力,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用; - Redis具有多种内存分配和回收的解决方案; - Redis具有原有关系型数据库的事务处理能力(弱事务); A事务能力 ??? - Reids具有消息队列相关功能,支持消息订阅能力,但是不支持消息回溯和消息堆积; - Redis具有原生态的高可用架构构建技术; 哨兵模式 - Redis具有数据的备份能力,即master-slave模式的数据备份; - Redis具有原生态的分布式架构和分片集群; 单个redis数据库服务存储数据 --- 分散存储到不同的缓存服务器中 缓存服务产品-Memcache - Memcache具有高性能读写能力; - Memcache具有客户端式的分布式集群,以及一致性hash功能; - Memcache具有多核结构,多线程读写能力;
比对项MemcacheRedis
持久化存储不具有持久化存储能力具有持久化存储能力
缓存穿透问题节点故障可能出现缓存穿透具有原生态高可用和主从复制能力
分布式能力分布式需要客户端实现具有原生态分布式集群
数据迁移能力跨机房数据同步困难具有跨机房数据迁移能力
架构扩容能力架构扩容复杂度高具有架构扩容解决方案
性能读写能力支持多线程读写能力,读写能力快支持单线程读写能力,读写能力较低
数据类型支持单一数据类型支持多种数据类型 name=oldboy
虚拟内存定义不支持自定义虚拟内存具有自定义虚拟内存能力

多种缓存服务产品的应用场景:

缓存服务应用场景
Memcached多核的缓存服务,更加适合于多用户并发访问次数较少的应用场景
Redis单核的缓存服务,单节点情况下,更加适合于少量用户,多次访问的应用场景

说明:Redis在500并发量的处理能力是比较强的,一般采用单机多实例架构,并且配合构建集群应用;

2、服务安装部署

bash
1、上传软件包 [root@db02 /usr/local]#ll -rw-r--r-- 1 root root 2490833 Jan 17 2023 redis-6.2.10.tar.gz 2、解压 [root@db02 /usr/local]# tar xf redis-6.2.10.tar.gz [root@db02 /usr/local]# ln -s redis-6.2.10 redis [root@db02 /usr/local]# ll -d redis lrwxrwxrwx 1 root root 12 2月 21 01:45 redis -> redis-6.2.10 # 部署redis服务的虚拟主机尽量将内存空间调大,建议调整为4G; 3、缓存服务安装部署: [root@db02 /usr/local]# yum install -y gcc automake autoconf libtool make [root@db02 /usr/local]# cd redis 4、编译: [root@master redis]# make 5、配置服务环境变量: [root@db02 /usr/local]#vim /etc/profile export PATH=/usr/local/redis/src:$PATH [root@db02 /usr/local]# source /etc/profile # 在Redis子目录src中存储了缓存服务应用的相关命令信息 6、简单启动服务测试: [root@master redis]# redis-server & [root@master redis]# netstat -lntup|grep redis tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 23667/redis-server tcp6 0 0 :::6379 :::* LISTEN 23667/redis-server

image

bash
缓存服务登录操作: [root@master redis]# redis-cli 127.0.0.1:6379> set a 1 OK 127.0.0.1:6379> get a "1" -- 测试是否正常登录缓存服务,进行简单缓存服务key-values数据类型设置

3、服务基础管理操作

1、缓存服务配置文件介绍
bash
# 编写基础配置文件信息: [root@db04 redis]# mkdir -p /data/6379 [root@db04 redis]# cat >/data/6379/redis.conf<<EOF daemonize yes -- 表示定义服务程序在后台以守护进程方式运行 port 6379 -- 表示定义服务的默认端口 logfile /data/6379/redis.log -- 表示服务运行日志存放路径 dir /data/6379 -- 表示定义数据目录路径,用于持久化应用时存储数据 dbfilename dump.rdb -- 表示持久化存储的数据文件名称 EOF # 缓存服务应用配置文件: [root@master redis]# redis-cli shutdown 23667:M 21 Feb 2021 02:21:00.018 # User requested shutdown... 23667:M 21 Feb 2021 02:21:00.018 * Saving the final RDB snapshot before exiting. 23667:M 21 Feb 2021 02:21:00.019 * DB saved on disk 23667:M 21 Feb 2021 02:21:00.019 # Redis is now ready to exit, bye bye... [1]+ 完成 redis-server(工作目录:/usr/local/redis/src) (当前工作目录:/usr/local/redis) # 关闭原有启动的redis服务程序 # 加载指定缓存服务配置文件,进行服务启动 [root@master redis]# redis-server /data/6379/redis.conf [root@master redis]# netstat -lntup|grep redis tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 23706/redis-server tcp6 0 0 :::6379 :::* LISTEN 23706/redis-server [root@master redis]# redis-cli 127.0.0.1:6379> set name xiaoQ OK 127.0.0.1:6379> get name "xiaoQ" -- 进行简单缓存服务配置操作测试
2、缓存服务安全配置应用(远程配置)
bash
Redis默认开启了安全保护模式,只允许本地回环地址登录并访问缓存服务数据库,无法实现远程连接缓存服务数据库; 需要禁用protected-mode模式,才能实现redis服务的远程连接; # Redis处于protected-mode默认开启的状态 [root@master redis]# redis-cli -h 192.168.30.101 -p 6379 192.168.30.101:6379> set a 1 (error) DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. -- 可以执行命令关闭protected-mode,执行的命令为CONFIG SET protected-mode no 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. -- 可以编写配置文件关闭保护模式,并设置protected mode option to 'no' 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. -- 可以在启动服务时,添加protected-mode no参数,实现关闭protected-mode 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside. -- 可以设置地址绑定或认证密码方式,在不关闭保护模式情况下,实现外网远程连接redis服务; -- 进行key-values设置失败,显示redis已经运行了protected-mode,并且处于启用状态 192.168.30.101:6379> get name Error: Connection reset by peer -- 查看key-values设置失败,由于redis已经运行了protected-mode,并且处于启用状态 # 1、修改配置文件 [root@db04 redis]# cat /data/6379/redis.conf daemonize yes port 6379 logfile /data/6379/redis.log dir /data/6379 dbfilename dump.rdb bind 10.0.0.54 127.0.0.1 # 设置监听本地远程连接地址和本地回环地址,实现地址bind绑定 requirepass 123456 # 设置远程连接认证密码信 # 2、进行监听地址和密码信息设置后,需要重启redis服务程序 [root@master redis]# redis-cli shutdown [root@master redis]# redis-server /data/6379/redis.conf # 3、登录redis [root@master redis]# redis-cli 127.0.0.1:6379> set a 1 (error) NOAUTH Authentication required. # 此时本地登录缓存服务也需要进行密码验证才可以 # 密码设置后登录方式1 [root@master redis]# redis-cli -a 123456 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> set a 1 OK 127.0.0.1:6379> get a "1" # 或者 [root@master redis]# redis-cli 127.0.0.1:6379> auth 123456 # 输入密码信息
3、缓存服务查看修改配置
bash
对于Redis缓存服务可以进行在线的查看配置和修改配置信息,无需对缓存服务进行重启操作: # 在线查看缓存服务所有配置信息 [root@master redis]# redis-cli -h 10.0.0.54 -p 6379 -a 123456 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 10.0.0.54:6379> CONFIG GET * 1) "rdbchecksum" 2) "yes" 3) "daemonize" 4) "yes" 5) "io-threads-do-reads" 6) "no" 7) "lua-replicate-commands" ... 省略部分信息 291) "notify-keyspace-events" 292) "" 293) "bind" 294) "10.0.0.54 127.0.0.1" 295) "oom-score-adj-values" 296) "0 200 800" -- 默认redis服务总共有148个配置信息(针对6.2.10版本) # 在线修改密码信息,避免重启服务 10.0.0.54:6379> CONFIG SET requirepass 123 # 在线修改缓存服务配置信息后,最好还要在配置文件中实现永久修改 OK 10.0.0.54:6379> CONFIG GET requirepass 1) "requirepass" 2) "123" [root@master redis]# redis-cli -h 10.0.0.54 -p 6379 -a 123 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. AUTH failed: WRONGPASS invalid username-password pair or user is disabled.
4、缓存服务实现数据存储
bash
Redis缓存服务可以实现将内存中的数据信息,持久化保存到磁盘中,实现缓存数据信息的永久保存,便于缓存数据信息的快速调取生成 Redis实现持久化存储:(具有两种持久化方式)
1、RDB持久化存储缓存数据
bash
Reids利用RDB持久化,可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot) 优点:存储速度快,适合于用作备份,缓存主从复制也是基于RDB持久化功能实现的; 缺点:由于全部缓存都做持久化,可能出现持久化不及时情况,并且持久化快照会覆盖上一次的,会存在数据丢失情况; # 1、RDB持久化存储手工实现方式: [root@db04 redis]# redis-cli -h 10.0.0.54 -p 6379 -a 123456 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 10.0.0.54:6379> save # 实现手动保存缓存数据信息,进行数据持久化存储(立即同步更新到磁盘) OK 或者 10.0.0.54:6379> bgsave # 实现手动保存缓存数据信息,进行数据持久化存储(等待键值对没有被修改时再更新到磁盘) Background saving started 10.0.0.54:6379> quit [root@master redis]# ll /data/6379/ 总用量 12 -rw-r--r-- 1 root root 129 2月 25 11:50 dump.rdb -rw-r--r-- 1 root root 137 2月 23 02:24 redis.conf -rw-r--r-- 1 root root 3938 2月 25 11:50 redis.log

image

bash
# 2、RDB持久化存储核心配置参数:(自动持久化) [root@db04 redis]# vim /data/6379/redis.conf dir /data/6379 # 表示定义数据目录路径,用于持久化应用时存储数据 dbfilename dump.rdb # 表示持久化存储的数据文件名称 save 900 1 # 当 900 秒(15分钟)内有至少 1 个键发生改变时触发快照,可能会存在900秒内redis服务挂掉,数据丢失 save 300 10 # 当 300 秒(5分钟)内有至少 10 个键发生改变时触发快照 save 60 10000 # 当 60 秒内有至少 10000 个键发生改变时触发快照
2、AOF持久化存储缓存数据
bash
Reids利用AOF持久化,会记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集; AOF文件中的命令全部以redis协议的格式来保存,新命令会被追加到文件的末尾; 优点:可以最大程度保证数据不丢; 缺点:日志记录量级比较大,因为是追加且不能切割; AOF持久化存储核心配置参数: [root@master redis]# vim /data/6379/redis.conf dir /data/6379 # 表示定义数据目录路径,用于持久化应用时存储数据 dbfilename dump.rdb # 表示持久化存储的数据文件名称 appendonly yes # 是否打开aof日志功能 appendfsync always(安全考虑) # 表示每1个命令,都立即同步到AOF appendfsync everysec # 表示每秒写1次 appendfsync no(性能考虑) # 写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到AOF # 配置AOF [root@db04 local]# cat /data/6379/redis.conf 。。。 appendonly yes appendfsync always # 重启redis [root@db04 local]# redis-cli -a 123456 shutdown [root@db04 local]# redis-server /data/6379/redis.conf # 登录新增key测试 [root@db04 local]# redis-cli -h 10.0.0.54 -p 6379 10.0.0.54:6379> auth 123456 OK 10.0.0.54:6379> set xiaoQ 123 OK # 产生aof文件 [root@db04 local]# ll /data/6379/ 总用量 20 -rw-r--r--. 1 root root 56 6月 18 19:46 appendonly.aof # 查看文件内容 [root@db04 local]# cat /data/6379/appendonly.aof *2 $6 SELECT $1 0 *3 $3 set $5 xiaoQ $3 123
3、Redis持久化方式有哪些?有什么区别?
bash
RDB:基于快照的持久化,速度更快,一般用作备份,主从复制也是依赖于RDB持久化功能; AOF:以追加的方式记录redis操作日志的文件,可以最大程度的保证redis数据安全,类似于mysql的binlog;
5、服务数据类型介绍
1、常用数据类型介绍说明
序号数据类型解释说明
01String字符数据类型
02Hash字典数据类型
03List列表数据类型
04Set集合数据类型
05Sorted Set有序集合类型
...
2、数据类型通用操作说明
bash
在Redis缓存服务中,默认进行数据信息存储和读取时,都是采用Key-values方式进行的,其中values可以对应不同的数据类型; 在进行key-values操作时常用命令为:
3、Strings (字符类型)
bash
应用:有些经常变化的数据信息,需要快速加载到网站页面中 # 实现缓存计数器功能(可以实时关注数据信息变化) 10.0.0.54:6379> set 001_001_dianzan 0 # 设置001_001_dianzan的key value值为0 OK 10.0.0.54:6379> incr 001_001_dianzan # incr对key value的值进行累加 (integer) 1 10.0.0.54:6379> get 001_001_dianzan # 查看 "1" # 实现计数器递增功能(模拟每点一次关注,都执行一次以上命令) 10.0.0.54:6379> mset 001_001_diancan 0 001_001_toubi 0 001_001_shoucang 0 # mset可以做多个key value的值设置 OK 10.0.0.54:6379> incr 001_001_diancan # incr对key value的值进行累加 (integer) 1 10.0.0.54:6379> get 001_001_diancan "1" 10.0.0.54:6379> get 001_001_toubi "0" 10.0.0.54:6379> decr 001_001_diancan # decr对key value的值进行累加 (integer) 0 10.0.0.54:6379> get 001_001_diancan "0" 10.0.0.54:6379> mget 001_001_diancan 001_001_toubi 001_001_shoucang # 批量设置 # 查看已经存在的所有key名称信息: [root@db04 redis]# redis-cli -h 10.0.0.54 -p 6379 -a 123456 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 10.0.0.54:6379> keys * 1) "xiaoQ" 2) "001_001_shoucang" 3) "001_001_dianzan" 4) "001_001_toubi" 5) "001_001_diancan" 10.0.0.54:6379> keys a # 表示显示redis缓存服务中的指定key信息,尽量精细化查找所需的key信息; 1) "a" 10.0.0.54:6379> keys a* 1) "ab" 2) "a" # 返回键所存储数据的类型 10.0.0.54:6379> type 001_001_shoucang string
4、Hash (字典类型==数据库存储结构)
bash
应用:可以将redis服务作为数据库的缓存服务,当用户需要加载数据库信息时,可以先访问缓存数据库 如果缓存数据库服务没有需要的数据,可以再访问数据库服务,并将访问后的结果会进行缓存,比如大量用户登录请求 # 进行缓存数据存储操作,hmset存放,stu01相当于表名 10.0.0.54:6379> hmset stu01 id 101 name xiaoQ age 20 gender m OK # 进行缓存数据读取操作 10.0.0.54:6379> hmget stu01 id 1) "101" 10.0.0.54:6379> hmget stu01 id name 1) "101" 2) "xiaoQ" # 返回键所存储数据的类型 10.0.0.54:6379> type stu01 hash # 以秒/毫秒为单位设定生存时间,以及返回生存时间(EXPIRE/PEXPIRE TTL/PTTL)
5、list (列表类型)
bash
应用:更多使用此方式存储redis缓存数据,可以将redis服务作为消息队列服务使用 # 创建生成数据列表信息 LPUSH wechat "insert" # LPUSH 队列信息数据存储 LPUSH wechat "update" LPUSH wechat "delete" # 查看调取数据列表信息 10.0.0.54:6379> lrange wechat 0 -1 1) "delete" 2) "update" 3) "insert" # 读取第3个值,redis默认从0开始 10.0.0.54:6379> lrange wechat 2 2 1) "insert" 10.0.0.54:6379> lrange wechat 1 2 1) "update" 2) "insert"
6、set (集合类型)
bash
应用:可以对有些数据做交集 并集 差集处理; # 设置xiaoQ01是key,后面是集合 10.0.0.54:6379> sadd xiaoQ01 xiaoA xiaoB oldgirl oldbaby tom (integer) 5 10.0.0.54:6379> type xiaoQ01 set # 设置oldboy01 是key,后面是集合 10.0.0.54:6379> sadd oldboy01 oldgirl oldbaby oldli Lucy tom (integer) 5 10.0.0.54:6379> type oldboy1 none # 并集处理 10.0.0.54:6379> SUNION xiaoQ01 oldboy01 1) "oldli" 2) "xiaoB" 3) "xiaoA" 4) "tom" 5) "oldbaby" 6) "oldgirl" 7) "Lucy" # 交集处理,显示相同的 10.0.0.54:6379> SINTER xiaoQ01 oldboy01 1) "oldbaby" 2) "oldgirl" 3) "tom" # 差集,xiaoQ01有,oldboy01没有的 10.0.0.54:6379> SDIFF xiaoQ01 oldboy01 1) "xiaoA" 2) "xiaoB" # 差集,oldboy01有,xiaoQ01没有的 10.0.0.54:6379> SDIFF oldboy01 xiaoQ01 1) "Lucy" 2) "oldli"
7、zset (有序集合类型)
bash
应用:当网站信息有动态排序需求时,可以在缓存中将信息排序 10.0.0.54:6379>zadd topN 0 smlt 0 fskl 0 fshkl 0 lzlsfs 0 wdhbx 0 wxg # 更新数量 10.0.0.54:6379>ZINCRBY topN 100000 smlt 10.0.0.54:6379>ZINCRBY topN 10000 fskl 10.0.0.54:6379>ZINCRBY topN 1000000 fshkl 10.0.0.54:6379>ZINCRBY topN 100 lzlsfs 10.0.0.54:6379>ZINCRBY topN 10 wdhbx 10.0.0.54:6379>ZINCRBY topN 100000000 wxg # 查看排名信息 10.0.0.54:6379> ZREVRANGE topN 0 2 1) "wxg" 2) "fshkl" 3) "smlt" 10.0.0.54:6379> type topN zset
6、主从复制功能
bash
复制功能是Redis提供的多机功能中最基础的一个,这个功能是通过主从复制(master-slave replication)模式实现的; 允许用户为存储着目标数据库的服务器创建出多个拥有相同数据库副本的服务器。 - 其中存储目标数据库的服务器被称为主服务器(master server); - 然而存储数据库副本的服务器被称为从服务器(slave server); > 说明:redis只能提供单主复制功能,而不能实现多主复制功能。
1、缓存服务主从复制概述
bash
通过持久化功能,Redis保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据; 但是由于数据是存储在一台服务器上的,因此如果这台服务器出现硬盘故障等问题,也会导致数据丢失; 为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障; 其他服务器依然可以继续提供服务,为此,redis提供了复制(replication)功能; 实现在一个数据库中的数据库更新后,自动将更新的数据同步到其它数据库上。
2、缓存服务主从复制原理
bash
Redis缓存的服务主从复制功能又称为主副本集(Master-Replicaset),具体实现原理如下: 当一个从数据库启动后,会向主数据库发送SYNC命令。 同时主数据库接收到SYNC命令后会开始在后台保存快照 - 副本库通过slaveof 192.168.30.101 6379命令,连接到主库缓存服务,并发送SYNC给主库; - 主库收到SYNC数据后,会立即触发BGSAVE,在后台保存RDB信息,并发送给副本库; - 副本库接收后会应用RDB快照信息; - 主库会陆续将中间产生的新操作数据,保存并发送给副本库,至此主复制集就正常工作了 - 后面应用过程中,主库只要发生新的操作,都会以命令传输的形式自动发送给副本库; set -- 从 - 所有复制相关的信息,从info信息中都可以查到,即使重启任何节点,它的主从关系依然都在; - 如果发生主从关系断开时,从库数据没有任何损坏,在下一次重连之后,从库发送PSYNC给主库; - 主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的;
3、缓存服务主从数据配置
bash
# 进行主从复制实例配置: [root@db02 /usr/local/redis]#mkdir -p /data/638{0..2} [root@db02 /usr/local/redis]# cat >>/data/6380/redis.conf <<EOF port 6380 daemonize yes pidfile /data/6380/redis.pid loglevel notice logfile "/data/6380/redis.log" dbfilename dump.rdb dir /data/6380 requirepass 123 masterauth 123 # 填写连接主库的密码 EOF [root@db02 /usr/local/redis]# cat >>/data/6381/redis.conf <<EOF port 6381 daemonize yes pidfile /data/6381/redis.pid loglevel notice logfile "/data/6381/redis.log" dbfilename dump.rdb dir /data/6381 requirepass 123 masterauth 123 EOF [root@db02 /usr/local/redis]# cat >>/data/6382/redis.conf <<EOF port 6382 daemonize yes pidfile /data/6382/redis.pid loglevel notice logfile "/data/6382/redis.log" dbfilename dump.rdb dir /data/6382 requirepass 123 masterauth 123 EOF # 运行启动多实例缓存服务: [root@db02 /usr/local/redis]# redis-server /data/6380/redis.conf [root@db02 /usr/local/redis]# redis-server /data/6381/redis.conf [root@db02 /usr/local/redis]# redis-server /data/6382/redis.conf [root@db02 /usr/local/redis]# netstat -lntup|grep redis tcp 0 0 0.0.0.0:6380 0.0.0.0:* LISTEN 27453/redis-server tcp 0 0 0.0.0.0:6381 0.0.0.0:* LISTEN 27459/redis-server tcp 0 0 0.0.0.0:6382 0.0.0.0:* LISTEN 27465/redis-server # 登录6380创建测试数据 [root@db02 /usr/local/redis]#redis-cli -a 123 -h 10.0.0.52 -p 6380 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 10.0.0.52:6380> set xiaoA 123 OK 10.0.0.52:6380> set xiaoB 456 OK 10.0.0.52:6380> set xiaoC 789 OK # 先登录6381测试,没有数据 [root@db02 /usr/local/redis]#redis-cli -a 123 -h 10.0.0.52 -p 6381 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 10.0.0.52:6381> get xiaoA (nil) # 在从库服务上开启主从同步: [root@db02 /usr/local/redis]#redis-cli -p 6381 -a 123 slaveof 127.0.0.1 6380 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. OK [root@db02 /usr/local/redis]#redis-cli -p 6382 -a 123 slaveof 127.0.0.1 6380 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. OK # 登录6381端口从库查看 [root@db02 /usr/local/redis]#redis-cli -a 123 -h 10.0.0.52 -p 6381 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 10.0.0.52:6381> get xiaoA "123"

image

bash
# 查看主从状态 10.0.0.52:6380> info replication # Replication role:master # 主人 connected_slaves:2 slave0:ip=127.0.0.1,port=6381,state=online,offset=574,lag=1 slave1:ip=127.0.0.1,port=6382,state=online,offset=574,lag=0 master_failover_state:no-failover master_replid:80e9f5107090a25e1c7e415163f3ed8338430c19 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:574 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:574 10.0.0.52:6380> 10.0.0.52:6382> info replication # Replication role:slave # 从节点 master_host:127.0.0.1 master_port:6380 master_link_status:up master_last_io_seconds_ago:8 master_sync_in_progress:0 slave_read_repl_offset:574 slave_repl_offset:574 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:80e9f5107090a25e1c7e415163f3ed8338430c19 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:574 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:15 repl_backlog_histlen:560 # 在从数据库服务器上解除和主库的关联: # 解除主从同步关系状态 [root@master ~]# redis-cli -p 6382 -a 123 slaveof no one 或者 [root@master ~]# redis-cli -p 6382 -a 123 replicaof no one
7、高可用-哨兵模式
1、哨兵架构组成介绍
bash
对于Redis主从复制功能,仅仅只是实现了数据的同步保存功能,但是并没有实现架构环境的高可用功能; 所以,对于Redis缓存服务,也需要设计一个合理的架构环境,保证主库业务的状态监控,和出现异常的切换操作; 可以利用sentinel(哨兵)功能组件,对集群架构进行管理,实现主库监控,故障切换,以及新节点加入集群等操作; redis-sentinel功能组件作用说明: - 可以实现架构监控功能; - 可以实现自动选主切换;(6381 slaveof no one) 采用的是raft分布式一致性协议进行选主,数据接近主,可以和大部分节点联系,少数服从多数; - 可以实现重构主从关系; - 可以保证应用切换透明;(代码 脚本) - 可以实现自动处理故障节点;
2、哨兵架构搭建过程
bash
安装部署哨兵服务 # 步骤一:编写哨兵服务配置文件 mkdir /data/26380 cd /data/26380 vim sentinel.conf port 26380 dir "/data/26380" daemonize yes # 实现哨兵服务可以守护进程方式运行 sentinel monitor mymaster 127.0.0.1 6380 1 # 监控集群架构中主库服务状态(数值1表示发现主库异常的票数,当发现有1票提出主库宕机,就立刻切换) sentinel down-after-milliseconds mymaster 5000 # 当主库进行监控心跳检测时,如果5s内没有反馈,就认为主库服务已经宕机 sentinel auth-pass mymaster 123 # 设置连接主库服务的认证密码信息 # 步骤二:加载哨兵服务配置文件启动哨兵服务 [root@db02 /data/26380]#redis-sentinel /data/26380/sentinel.conf &>/tmp/sentinel.log & [root@db02 /data/26380]#ss -tnulp|grep 26380 tcp LISTEN 0 128 0.0.0.0:26380 0.0.0.0:* users:(("redis-sentinel",pid=34282,fd=6)) tcp LISTEN 0 128 [::]:26380 [::]:* users:(("redis-sentinel",pid=34282,fd=7)) # 可以看到主节点是6380 10.0.0.52:6382> info replication role:slave master_host:127.0.0.1 master_port:6380 # 步骤三:验证高可用功能 # 模拟6380故障 [root@db02 /data/26380]#redis-cli -a 123 -h 127.0.0.1 -p 6380 shutdown Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe # 登录6381发现6382成了主节点 [root@db02 ~]#redis-cli -a 123 -h 10.0.0.52 -p 6381 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 10.0.0.52:6381> info replication role:slave master_host:127.0.0.1 master_port:6382 master_link_status:u

8、服务集群架构功能实现
1、缓存服务集群架构介绍说明
bash
作用功能: 1)可以缓解单个缓存节点数据存储压力 2)可以缓解单个缓存节点并发访问压力 为了满足并发数据写入的高效性,会创建生成多缓存服务主节点,并将需要存储的数据分布存储到不同节点上; 具体实现高性能存储机制如下: - 在多分片节点中,将16384个槽位,均匀分布到多个分片节点中; - 存储数据时,将key信息做crc16(key)运算,然后和16384进行取模,得出槽位值(0~16384之间); - 根据计算得出的槽位值,找到相对应的分片节点的主节点,存储到相应槽位上; - 如果客户端当时连接的节点不是将来要存储分片节点,分片集群会将客户端连接切换至真正存储节点进行数据存储; 具体实现高可用存储机制如下: 在搭建集群时,会为每一个分片的主节点,对应一个从节点,实现slaveof的功能,当主节点宕机,实现类似于sentinel的自动切换功能 - Redis缓存服务会有多组分片构成(3组); - Redis cluster使用固定个数的slot存储数据(总共16384slot); - Redis cluster中每组分片分得1/3 slot个数(0~5500 5501~11000 11001~16383) - 基于CRC16(KEY)的加密数值/16384数值进行取模运算,得到数值就是存储数据的槽位位置;

image

2、缓存服务集群架构构建过程
bash
# 集群架构环境规划准备: 6个redis实例,一般会放在3台硬件服务器上; 在企业规划中,一个分片的两个分到不同的物理机,防止硬件主机宕机造成的整个分片数据丢失; # 集群架构环境节点配置: [root@master ~]# mkdir /data/{7000..7007} [root@master ~]# cat >/data/7000/redis.conf <<EOF port 7000 daemonize yes pidfile /data/7000/redis.pid loglevel notice logfile "/data/7000/redis.log" dbfilename dump.rdb dir /data/7000 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF -- 实例01节点配置信息(主库) [root@master ~]# cat >/data/7001/redis.conf <<EOF port 7001 daemonize yes pidfile /data/7001/redis.pid loglevel notice logfile "/data/7001/redis.log" dbfilename dump.rdb dir /data/7001 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF -- 实例02节点配置信息(主库) [root@master ~]# cat >/data/7002/redis.conf <<EOF port 7002 daemonize yes pidfile /data/7002/redis.pid loglevel notice logfile "/data/7002/redis.log" dbfilename dump.rdb dir /data/7002 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF -- 实例03节点配置信息(主库) [root@master ~]# cat >/data/7003/redis.conf <<EOF port 7003 daemonize yes pidfile /data/7003/redis.pid loglevel notice logfile "/data/7003/redis.log" dbfilename dump.rdb dir /data/7003 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF -- 实例04节点配置信息(从库) [root@master ~]# cat >/data/7004/redis.conf <<EOF port 7004 daemonize yes pidfile /data/7004/redis.pid loglevel notice logfile "/data/7004/redis.log" dbfilename dump.rdb dir /data/7004 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF -- 实例05节点配置信息(从库) [root@master ~]# cat >/data/7005/redis.conf <<EOF port 7005 daemonize yes pidfile /data/7005/redis.pid loglevel notice logfile "/data/7005/redis.log" dbfilename dump.rdb dir /data/7005 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF -- 实例06节点配置信息(从库) # 集群架构节点启动运行: [root@master ~]# redis-server /data/7000/redis.conf [root@master ~]# redis-server /data/7001/redis.conf [root@master ~]# redis-server /data/7002/redis.conf [root@master ~]# redis-server /data/7003/redis.conf [root@master ~]# redis-server /data/7004/redis.conf [root@master ~]# redis-server /data/7005/redis.conf # 查看服务 [root@master ~]# ps -ef|grep redis root 27618 1 0 01:31 ? 00:00:00 redis-server *:7000 [cluster] root 27624 1 0 01:31 ? 00:00:00 redis-server *:7001 [cluster] root 27630 1 0 01:31 ? 00:00:00 redis-server *:7002 [cluster] root 27636 1 0 01:31 ? 00:00:00 redis-server *:7003 [cluster] root 27642 1 0 01:31 ? 00:00:00 redis-server *:7004 [cluster] root 27648 1 0 01:31 ? 00:00:00 redis-server *:7005 [cluster] # 集群架构节点添加管理: [root@master ~]# redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1 --cluster create # Redis CLI 的集群创建模式,用于自动初始化集群。 127.0.0.1:7000 到 127.0.0.1:7005 # 这是参与集群的 6 个 Redis 实例地址(本机 + 不同端口)。 --cluster-replicas 1 # 指定每个主节点有 1 个从节点(副本),实现高可用。 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 127.0.0.1:7004 to 127.0.0.1:7000 Adding replica 127.0.0.1:7005 to 127.0.0.1:7001 Adding replica 127.0.0.1:7003 to 127.0.0.1:7002 >>> Trying to optimize slaves allocation for anti-affinity [WARNING] Some slaves are in the same host as their master M: 7589f4823899fe4f09733579426417b0653c3696 127.0.0.1:7000 slots:[0-5460] (5461 slots) master M: eb6d587d4fa8ad02cfc8805bbe7a25cadcac8ce8 127.0.0.1:7001 slots:[5461-10922] (5462 slots) master M: de0895545ec5ba9f310649b8e8dc8ac3f457a27d 127.0.0.1:7002 slots:[10923-16383] (5461 slots) master S: 819736a82001f09fe1d2cf946cffce43c75fcd96 127.0.0.1:7003 replicates de0895545ec5ba9f310649b8e8dc8ac3f457a27d S: 832fc34e9eb05508bacae9be3e68b47eee24b759 127.0.0.1:7004 replicates 7589f4823899fe4f09733579426417b0653c3696 S: 940b262ce9dbd0399986f7e7b6caae1c4661d6bd 127.0.0.1:7005 replicates eb6d587d4fa8ad02cfc8805bbe7a25cadcac8ce8 Can I set the above configuration? (type 'yes' to accept): yes -- 确认是否同意进行集群架构环境自动创建 >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join ... >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 7589f4823899fe4f09733579426417b0653c3696 127.0.0.1:7000 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 940b262ce9dbd0399986f7e7b6caae1c4661d6bd 127.0.0.1:7005 slots: (0 slots) slave replicates eb6d587d4fa8ad02cfc8805bbe7a25cadcac8ce8 M: de0895545ec5ba9f310649b8e8dc8ac3f457a27d 127.0.0.1:7002 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: eb6d587d4fa8ad02cfc8805bbe7a25cadcac8ce8 127.0.0.1:7001 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: 819736a82001f09fe1d2cf946cffce43c75fcd96 127.0.0.1:7003 slots: (0 slots) slave replicates de0895545ec5ba9f310649b8e8dc8ac3f457a27d S: 832fc34e9eb05508bacae9be3e68b47eee24b759 127.0.0.1:7004 slots: (0 slots) slave replicates 7589f4823899fe4f09733579426417b0653c3696 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. # -- 至此集群构建过程完成 # 集群架构状态信息查看: # 集群主节点状态情况 [root@master ~]# redis-cli -p 7000 cluster nodes|grep master 7589f4823899fe4f09733579426417b0653c3696 127.0.0.1:7000@17000 myself,master - 0 1677347184000 1 connected 0-5460 eb6d587d4fa8ad02cfc8805bbe7a25cadcac8ce8 127.0.0.1:7001@17001 master - 0 1677347183000 2 connected 5461-10922 de0895545ec5ba9f310649b8e8dc8ac3f457a27d 127.0.0.1:7002@17002 master - 0 1677347184515 3 connected 10923-16383 # 集群从节点状态情况 [root@master ~]# redis-cli -p 7000 cluster nodes|grep slave 819736a82001f09fe1d2cf946cffce43c75fcd96 127.0.0.1:7003@17003 slave de0895545ec5ba9f310649b8e8dc8ac3f457a27d 0 1677347216530 3 connected 832fc34e9eb05508bacae9be3e68b47eee24b759 127.0.0.1:7004@17004 slave 7589f4823899fe4f09733579426417b0653c3696 0 1677347217134 1 connected 940b262ce9dbd0399986f7e7b6caae1c4661d6bd 127.0.0.1:7005@17005 slave eb6d587d4fa8ad02cfc8805bbe7a25cadcac8ce8 0 1677347216630 2 connected
3、缓存服务集群架构节点添加
bash
在原有缓存服务集群节点中添加(扩容)新的节点: 集群新的节点信息创建: # 创建新的集群节点实例 [root@master ~]# mkdir /data/7006 [root@master ~]# mkdir /data/7007 # 编写新的节点配置文件 [root@master ~]# cat >/data/7006/redis.conf <<EOF port 7006 daemonize yes pidfile /data/7006/redis.pid loglevel notice logfile "/data/7006/redis.log" dbfilename dump.rdb dir /data/7006 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF [root@master ~]# cat >/data/7007/redis.conf <<EOF port 7007 daemonize yes pidfile /data/7007/redis.pid loglevel notice logfile "/data/7007/redis.log" dbfilename dump.rdb dir /data/7007 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF # 启动运行新的节点服务程序: [root@master ~]# redis-server /data/7006/redis.conf [root@master ~]# redis-server /data/7007/redis.conf [root@master ~]# ps -ef|grep redis root 27713 1 0 01:58 ? 00:00:00 redis-server *:7006 [cluster] root 27719 1 0 01:58 ? 00:00:00 redis-server *:7007 [cluster] # 进行新的节点架构集群添加:把新的节点7006连接到7000所在的集群环境里 [root@master ~]# redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 # 重新给新的集群节点分配槽位,用于存储key value [root@master ~]# redis-cli --cluster reshard 127.0.0.1:7000 How many slots do you want to move (from 1 to 16384)? 800 # 取出多少给槽位 进行分配 What is the receiving node ID? d186f6fb61fee6ef96c1dcff5b79534d7fb3cec8 # 将取出的槽位分配给哪个集群节点 Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. # 设置all 表示从所有节点中,取出指定槽位数,分配给指定节点 Type 'done' once you entered all the source nodes IDs. # 执行槽位分配操作 Source node #1: 353dd2c100de7e65f26ea7e5c083e54ad7f510b7 # 指定从哪个节点取出槽位数分配给指定节点 Source node #1: done

fbc6daa3f6ef49626affa5d0c7557102

6042ef1ede0bff1433c7920bceceba68

bash
新添加的节点从三台节点共分配100槽位信息

添加新的从节点信息

bash
# 扩容从节点:新添加的从节点跟扩容的7006相关联,21d8aaf99d663a15652599d61d8466be9fac0179是7006的id [root@db04 local]# redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id 21d8aaf99d663a15652599d61d8466be9fac0179 >>> Adding node 127.0.0.1:7007 to cluster 127.0.0.1:7000 >>> Performing Cluster Check (using node 127.0.0.1:7000) M: d8b8c2ae04400f1651af51e1825503488144fe9a 127.0.0.1:7000 slots:[33-5460] (5428 slots) master 1 additional replica(s) S: 08057190805f19f03742c90402b08e70507b1d4f 127.0.0.1:7005 slots: (0 slots) slave replicates 668763fe42e48d66d7b3269e2f4506a5012ad9b7 M: 21d8aaf99d663a15652599d61d8466be9fac0179 127.0.0.1:7006 slots:[0-32],[5461-5494],[10923-10955] (100 slots) master M: 668763fe42e48d66d7b3269e2f4506a5012ad9b7 127.0.0.1:7002 slots:[10956-16383] (5428 slots) master 1 additional replica(s) S: d7eba5b24f843e1b7d6e2ceb1eff2dd72a511750 127.0.0.1:7003 slots: (0 slots) slave replicates d8b8c2ae04400f1651af51e1825503488144fe9a S: 1c67cd8f5238c81249da1510209afe227ac8c0aa 127.0.0.1:7004 slots: (0 slots) slave replicates e614f7e5f7eb7113520f71d0183eaade1fdec82b M: e614f7e5f7eb7113520f71d0183eaade1fdec82b 127.0.0.1:7001 slots:[5495-10922] (5428 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. >>> Send CLUSTER MEET to node 127.0.0.1:7007 to make it join the cluster. Waiting for the cluster to join >>> Configure node as replica of 127.0.0.1:7006. [OK] New node added correctly. # 查看从节点信息 [root@db04 local]# redis-cli -p 7000 cluster nodes|grep slave 6caefa494730fb1a1837036ab50316e633523314 127.0.0.1:7007@17007 slave 21d8aaf99d663a15652599d61d8466be9fac0179 0 1750255349000 7 connected 08057190805f19f03742c90402b08e70507b1d4f 127.0.0.1:7005@17005 slave 668763fe42e48d66d7b3269e2f4506a5012ad9b7 0 1750255348000 3 connected d7eba5b24f843e1b7d6e2ceb1eff2dd72a511750 127.0.0.1:7003@17003 slave d8b8c2ae04400f1651af51e1825503488144fe9a 0 1750255349702 1 connected 1c67cd8f5238c81249da1510209afe227ac8c0aa 127.0.0.1:7004@17004 slave e614f7e5f7eb7113520f71d0183eaade1fdec82b 0 1750255349000 2 connected
4、缓存服务集群架构节点删除
bash
在进行节点删除时,可以先将节点中槽位移走 # 1、删除主节点 # 分片槽位第一次移动 [root@db04 local]# redis-cli --cluster reshard 127.0.0.1:7000 >>> Performing Cluster Check (using node 127.0.0.1:7000) M: d8b8c2ae04400f1651af51e1825503488144fe9a 127.0.0.1:7000 slots:[33-5460] (5428 slots) master 1 additional replica(s) S: 6caefa494730fb1a1837036ab50316e633523314 127.0.0.1:7007 slots: (0 slots) slave replicates 21d8aaf99d663a15652599d61d8466be9fac0179 S: 08057190805f19f03742c90402b08e70507b1d4f 127.0.0.1:7005 slots: (0 slots) slave replicates 668763fe42e48d66d7b3269e2f4506a5012ad9b7 M: 21d8aaf99d663a15652599d61d8466be9fac0179 127.0.0.1:7006 slots:[0-32],[5461-5494],[10923-10955] (100 slots) master 1 additional replica(s) M: 668763fe42e48d66d7b3269e2f4506a5012ad9b7 127.0.0.1:7002 slots:[10956-16383] (5428 slots) master 1 additional replica(s) S: d7eba5b24f843e1b7d6e2ceb1eff2dd72a511750 127.0.0.1:7003 slots: (0 slots) slave replicates d8b8c2ae04400f1651af51e1825503488144fe9a S: 1c67cd8f5238c81249da1510209afe227ac8c0aa 127.0.0.1:7004 slots: (0 slots) slave replicates e614f7e5f7eb7113520f71d0183eaade1fdec82b M: e614f7e5f7eb7113520f71d0183eaade1fdec82b 127.0.0.1:7001 slots:[5495-10922] (5428 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. How many slots do you want to move (from 1 to 16384)? 100 # 移走100个槽位 What is the receiving node ID? d8b8c2ae04400f1651af51e1825503488144fe9a # 7000端口接受,填写id Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1: 21d8aaf99d663a15652599d61d8466be9fac0179 # 要缩容的是哪个 Source node #2: done # 完成 # 显示已经没有槽位信息 [root@db04 local]# redis-cli -p 7000 cluster nodes|grep master d8b8c2ae04400f1651af51e1825503488144fe9a 127.0.0.1:7000@17000 myself,master - 0 1750255654000 8 connected 0-5494 10923-10955 21d8aaf99d663a15652599d61d8466be9fac0179 127.0.0.1:7006@17006 master - 0 1750255656275 7 connected 668763fe42e48d66d7b3269e2f4506a5012ad9b7 127.0.0.1:7002@17002 master - 0 1750255654000 3 connected 10956-16383 e614f7e5f7eb7113520f71d0183eaade1fdec82b 127.0.0.1:7001@17001 master - 0 1750255654000 2 connected 5495-10922 # 删除7006节点,对应id为21d8aaf99d663a15652599d61d8466be9fac0179 [root@db04 local]# redis-cli --cluster del-node 127.0.0.1:7006 21d8aaf99d663a15652599d61d8466be9fac0179 >>> Removing node 21d8aaf99d663a15652599d61d8466be9fac0179 from cluster 127.0.0.1:7006 >>> Sending CLUSTER FORGET messages to the cluster... >>> Sending CLUSTER RESET SOFT to the deleted node. [root@db04 local]# redis-cli -p 7000 cluster nodes|grep master d8b8c2ae04400f1651af51e1825503488144fe9a 127.0.0.1:7000@17000 myself,master - 0 1750255869000 8 connected 0-5494 10923-10955 668763fe42e48d66d7b3269e2f4506a5012ad9b7 127.0.0.1:7002@17002 master - 0 1750255870516 3 connected 10956-16383 e614f7e5f7eb7113520f71d0183eaade1fdec82b 127.0.0.1:7001@17001 master - 0 1750255868502 2 connected 5495-10922 # 2、删除从节点7007,对应id为6caefa494730fb1a1837036ab50316e633523314 [root@db04 local]# redis-cli --cluster del-node 127.0.0.1:7007 6caefa494730fb1a1837036ab50316e633523314 >>> Removing node 6caefa494730fb1a1837036ab50316e633523314 from cluster 127.0.0.1:7007 >>> Sending CLUSTER FORGET messages to the cluster... >>> Sending CLUSTER RESET SOFT to the deleted node. [root@db04 local]# redis-cli -p 7000 cluster nodes|grep slave 08057190805f19f03742c90402b08e70507b1d4f 127.0.0.1:7005@17005 slave 668763fe42e48d66d7b3269e2f4506a5012ad9b7 0 1750256012933 3 connected d7eba5b24f843e1b7d6e2ceb1eff2dd72a511750 127.0.0.1:7003@17003 slave d8b8c2ae04400f1651af51e1825503488144fe9a 0 1750256013538 8 connected 1c67cd8f5238c81249da1510209afe227ac8c0aa 127.0.0.1:7004@17004 slave e614f7e5f7eb7113520f71d0183eaade1fdec82b 0 1750256011524 2 connected

4、云计算-redis技能掌握

bash
1、redis安装部署 2、redis基础管理 3、redis简单语句应用 4、redis主从架构、高可用架构、集群架构搭建部署

3、MongoDB

bash
> use admin > db.createUser ( user: "<name>" pwd: "<cleartext password>" roles: [ { role: "<role>", db: "<database>" } | "<role>", ... ] )

本文作者:张龙龙

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!