数据库

29;6一、基础概念

常用词汇★★★

table 表 drop删除 like复制 on索引 show查看表库 desc查看表结构

add 添加 modify 替换 distinct 去重 order by 升序降序 limit提取数据

tadabase数据库 group 分组 truncate 清空表内数据

 use school;
 #切换库

SELECT * FROM student; 
 #查看表中所有信息
  SHOW DATABASES; 
 #查看所有库
 SHOW TABLES;   
 #查看库里的所有表
 
 DESC student;  
 # 查看表结构
 SELECT * FROM students WHERE name LIKE '%张%';
# 模糊查询,查询所有带张的
 
  DROP DATABASE IF EXISTS test; 
 # 删数据库
DROP TABLE IF EXISTS student; 
# 删除表 student
ALTER TABLE student DROP COLUMN name;
#删除 student 表的 name 字段
 DELETE FROM student  WHERE age < 18;
 得儿雷特 from student  where 
 #删除 student 表中年龄小于 18 的行
 DROP INDEX idx_name ON student;
#删除 `student` 表上名为 `idx_name` 的索引
DROP VIEW IF EXISTS v_student;
 # 删除 v_student 视图
 DROP PROCEDURE IF EXISTS proc_student;
 #  删除存储过程 proc_student
 
 INSERT INTO student(id,name,gender,password,phone) VALUE(1,'武大郎','男','123''321');    
 #添加内容,多加的话后面加括号,(),()
ALTER TABLE student ADD birthday DATE;  
 # 给student添加birthday字段
 ALTER TABLE student MODIFY age TINYINT; 
  #修改`student`表的`age`字段为`TINYINT`
CREATE TABLE student_backup LIKE student;
 #复制`student`表结构到`student_backup

#查询索引方法 
SHOW INDEX FROM zhang;

一. 什么是数据库?数据库的功能是什么?

  • 存储数据的仓库 DB (DataBase)
  • 数据库管理系统 DBMS
  • 对数据进行增、删、改、查
  • 数据 (data) : 对客观事务的记录,数字、文字、图形、符号、声音、视频…
  • 信息 (info) : 进过加工后的数据

\2. 数据库的分类?

  • 模型:

    • 关系模型
    • 非关系模型
  • 部署:

    • 本地
  • 用途:

    • OLTP: 在线事务处理
    • OLAP: 在线分析处理
    • HTAP:混合
  • 架构:

    • 集中式
    • 分布式
    • 云原生
  • 介质:

    • 磁盘
    • 内存

\3. 关系型数据库和非关系型数据库的区别?

  • 结构化数据:例如:表格由行和列构成,每一列都要固定的格式和类型。
  • 半结构数据:例如:html、xml、json、yaml
  • 非结构化数据:聊天记录、评论… •
  • 关系型数据库RDBMS:结构化存储、SQL语句 ◦ Oracle、MySQL、Microsoft SQL Server、PostgreSQL、Snowflake、IBM Db2、SQLite
  • 非关系型数据库NoSQL:非结构化存储、半结构化存储 ◦
    • MongoDB:文档数据库、适合存储JSON数据。 ◦
    • Redis:内存型数据库,适合做缓存 ◦
    • Elasticsearch:适合全文搜索

\4. 了解数据库 top10?国产信创数据库有哪些?

1.Oracle 甲骨文公司,收费的大型数据库,银行、金融、民航、电力…

2.MySQL 是一个C/S关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品,目前依旧开源免费。MariaDB是MySQL的开源分支,是由原作者重新开源的产品。在互联网公司使用极为普遍。

3.Microsoft SQL Server 在Windows Server使用的数据库,常用于财务管理系统、餐饮管理系统等。

4.PostgreSQL 世界上最** 先进 **的开源关系数据库。诞生在加州大学伯克利分校。

5.MongoDB 文档 数据库、适合存储JSON数据。

6.Snowflake 数据库是一款基于云的高性能数据仓库,具有独特的架构和强大的功能。

7.Redis 开源的基于内存型、key-value结构的数据库,用于数据缓存,实现高并发。

8.IBM Db2 和IBM服务器绑定使用。

9.Elasticsearch 搜索引擎,适合全文搜索、 日志 分析等功能。

10.SQLiet 微型关系数据库,以文件的方式存储数据,支持SQL,嵌入式设备、手机、App后台数据存储。

国产信创数据库

* 达梦数据库

* 金仓数据库

* OceanBase

* openGauss

5.SQL 是什么?

SQL:(Structured Query Language) 结构化查询语言,用于操作关系型数据的语言。

二:二进制安装MySQL

企业一般使用 MySQL 二进制包安装 MySQL8.0

另外还有 yum/apt、源码、Shell 一键安装、容器化安装 (Docker 一键安装) 安装方式

  • 1.安装依赖环境
yum install -y libaio libaio-devel ncurses ncurses-devel openssl openssl-devel 
  • 2.下载二进制包
# wget  https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz 
wget http://192.168.56.200/Software/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz 
  • 3.设置安装路径与权限
# 解压
tar  -xvf mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz
# 将mysql文件夹,剪切并改名
 mv mysql-8.0.20-linux-glibc2.12-x86_64 /usr/local/mysql
 #创建 mysql 用户
 useradd mysql -M -s /sbin/nologin
 #创建数据库数据目录
 mkdir /usr/local/mysql/data
 #更改 mysql 目录权限
 chown mysql:mysql -R /usr/local/mysql
  • 4.修改配置与初始化
1 # 修改 MySQL 配置文件
2 cat <<EOF> /etc/my.cnf
3 [mysqld]
4 port = 3306
5 basedir = /usr/local/mysql
6 datadir = /usr/local/mysql/data
7 log-error = /usr/local/mysql/data/error.log
8 pid-file = /usr/local/mysql/data/mysql.pid
9 socket = /tmp/mysql.sock
10 character-set-server=utf8mb4
11 collation-server=utf8mb4_unicode_ci
12 default-storage-engine=InnoDB
13 default-authentication-plugin=mysql_native_password
14 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
15 EOF

17 # 执行初始化
18 /usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
19
20 cat /usr/local/mysql/data/error.log
21 2025-08-01T01:59:17.918526Z 0 [Warning] [MY-010915] [Server] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release.
22 2025-08-01T01:59:17.918080Z 0 [System] [MY-013169] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.0.20) initializing of server in progress as process 1361
23 2025-08-01T01:59:17.955395Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
24 2025-08-01T01:59:18.606916Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
25 2025-08-01T01:59:19.405704Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: 5wp7=Y3<TZp;
26
27 #初始化成功后,启动MySQL
28 /usr/local/mysql/support-files/mysql.server start
29 Starting MySQL.. SUCCESS!
30
31 netstat -lnutp|grep 3306
32 tcp6 0 0 :::33060 :::* LISTEN 1672/mysqld
33 tcp6 0 0 :::3306 :::* LISTEN 1672/mysqld


  • 5.设置环境变量(为了让系统可以识别二进制)
 # 修改系统环境变量
# 想要在任意目录执行 mysql 的命令需要修改 /etc/profile
 # PATH: 可执行命令的目录路径
 vim /etc/profile
 # 最后一行添加
export PATH=$PATH:/usr/local/mysql/bin
# 重新加载
 source /etc/profile

  • 6.修改密码
 # 使用你的初始密码登录 MySQL
 mysql -uroot -p'5wp7=Y3<TZp;'
 # 修改密码
  alter user 'root'@'localhost' identified by 'root123';
  • 7.设置开机启动
# 将启动脚本复制到 /etc/init.d/ 目录,这是启动脚本的默认目录。
 cp -a /usr/local/mysql/support-files/mysql.server/etc/init.d/mysqld

 # 配置 mysqld 开机启动后,可以使用 systemctl 管理 mysqld
 systemctl enable mysqld
 systemctl restart mysqld
 systemctl status mysqld
  • 8.设置远程登录
# 服务端本地登录MySQL
mysql -uroot -proot123

# 创建远程登录账号
mysql> create user 'root'@'%' identified with mysql_native_password by 'root123';
Query OK, 0 rows affected (0.01 sec)

# 设置开放权限
mysql> grant all on *.* to 'root'@'%';
Query OK, 0 rows affected (0.00 sec)

# 刷新使权限生效
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

# 客户端-命令行 
# mysql:官方的客户端
yum install mariadb  
apt install mysql-client
mysql -uroot -proot123 -h192.168.8.20

# mycli:Python实现的mysql客户端,拥有关键字提示功能。
apt install mycli
mycli -uroot -proot123 -h"192.168.8.20"

# CentOS7上安装mycli
yum install python3-pip
pip3 install mycli==1.10
pip3 install pymysql==0.8
# 客户端-图形化
phpmyadmin
Navicat
SQLyou
Workbench

三、SQL基础语法

  • SQL的分类:DML、DDL、DQL、DCL
  • SQL的关键字
  • 创建库、创建表
  • SQL 的分类:
  • DDL:(数据定义语言)(Data Definition Language)对库和表进行操作
    • create 创建库、表、索引、视图、用户
    • alter 修改库字符集、表结构、索引、视图、用户、密码
    • drop 删除各种结构、库、表、视图、索引、用户
  • DML:(数据操纵语言)(Data Manipulation Language)对表中的数据进行添加、修改、删除

    • insert 在表中插入、添加数据
    • update 修改表中的内容
    • delete 删除表中的内容
  • DQL:数据查询语言

  • DCL:(数据控制语言)(Data Control Language)对数据库进行权限管理、用户管理、事务管理

    • use 切换数据库
    • grant 权限设置
    • revoke 移除权限
  • DTL:(事务控制语言)(Data Transaction Language)

    • commit 事务提交
    • rollback 回滚
  • SQL 的关键字

  • 库操作

    • 查看所有库:show databases;
    • 创建库:create database 库名charset utf8mb4;
    • 删除库:drop database 库名; -- 当删除库时,库中所有的内容都会被删除
    • 修改库的字符集:alter database test charset utf8mb4;
    CREATE DATABASE `test` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT ENCRYPTION='N' 
    关键字 / 语法片段	作用说明
    CREATE DATABASE	SQL 语句的核心指令,用于创建数据库,明确操作类型是 “新建数据库”
    test	数据库的名称,实际使用时需替换为你想要创建的数据库名(自定义标识符,需符合命名规范)
    DEFAULT CHARACTER SET	设置数据库的默认字符集,utf8mb4 是常用的通用字符集,支持几乎所有 Unicode 字符(含 emoji 等)
    utf8mb4	具体的字符集类型,utf8mb4 比传统 utf8 更完善,支持完整 Unicode 范围
    COLLATE	用于指定排序规则,决定字符比较、排序的逻辑
    utf8mb4_unicode_ci	基于 utf8mb4 字符集的排序规则,_ci 表示不区分大小写(Case Insensitive )排序
    DEFAULT ENCRYPTION='N'	设置数据库是否默认加密,'N' 表示不加密(若需加密可改为 'Y' ,依赖数据库版本 / 支持)
    简单来说,这条语句的作用是:创建一个名为 test 的数据库,指定用 utf8mb4 字符集存储数据,用 utf8mb4_unicode_ci 规则排序,且默认不加密 。
    
    • 表操作:

    • mysql -u root -p 进入mysql

    • use test 进入test

    • desc user; 打开名为user的表格

      • 查看表:

        • 查看库中所有的表:show tables;
        • 查看表的结构
      • 创建表

      31
      32 * Field 字段 (列名) : 字母、数字、下划线、不要和 mysql 关键字冲突,不要有特殊符号和空格。
      33 * Type 数据类型:数字类型、字符类型、日期时间类型、二进制数据、json 等...
      34 * Null 是否可为空: YSE 可为空,NO 不能为空,Not Null
      35 * Key 键:主键、外键、唯一
      36 * Default 默认值:在 insert 时,没有设置内容时,自动添加的内容
      37 * Extra: 扩展,例如: auto_increment (自动增长,一般用于序号自动 + 1)
      
      
      • 修改表结构 alter
      alter table(修改表) user_info(被修改的表名) add(新增) age(新家内容名称) tinyint(数据类型) UNSIGNED;(表示无符号整数0-255)
      # 简单说:这条 SQL 是给 user_info 表新增一个无符号 tinyint 类型的字段 age ,用于存储年龄等小范围整数值。
      
      
      
      
      • 删除表: drop table 表名;

数据类型

  • 作用:对数据进行分类,对相同类型的数据给予相同大小的存储空间。
    整数、浮点数、字符串、时间日期

\1. 整数类型

    1. 整数型
    类型 字节 范围(有符号) 范围(无符号)
    TINYINT(m) 1 (-128,127) (0,255)
    SMALLINT(m) 2 (-32768,32767) (0,65535)
    MEDIUMINT(m) 3 (-8388608,8388607) (0,16777215)
    INT(m) 4 (-2147483 648,2147483647) (0,4294967295)
    BIGINT(m) 8 (-9223372036854775808,9223372036854775807) (0,18446744073709551615)

2.浮点数和定点数

  • float 4字节 (小数位过多时不精确,会自动四舍五入)
  • double 8字节 相对floaat精确一些
  • decimal(M总长度,D小数长度)M>D decimal(6.2)相当于1000.00(总共6位,两位小数)
    • decimal是以字符串方式存储的数字。

3.日期时间

  • 类型 字节 范围 格式 用途
    DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
    TIME 3 '-838:59:59'/'838:59:59' HH:MM:SS 时间值或持续时间
    YEAR 1 1901/2155 YYYY 年份值
    DATETIME 8 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值
    TIMESTAMP 4 1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和时间值,时间戳

4.字符类型

  • char(n) 0~255字节 定长字符串,适合手机号,身份证号,有可能浪费空间,但查询效率高
  • varchar(n),0~65535字符,变长字符串,姓名,密码,地址,简介,标题,短文
  • blob 0~65535字节 二进制字符
  • text 0~65535字节 普通文本,评论,简介,短文
  • longtext 0 - 4294967295字节 超长的文本,例如:一本书、

1. 主键约束(PRIMARY KEY)

  • 作用:唯一标识表中的每条记录,确保记录不重复且非空。
  • 特点:一个表只能有一个主键,主键字段的值不能为 NULL,也不能重复。
  • 示例:
CREATE TABLE students (
  id INT PRIMARY KEY, -- id作为主键
  name VARCHAR(50)
);

2. 非空约束(NOT NULL)

  • 作用:强制列不能存储 NULL 值,确保该字段必须有值。
  • 示例:
CREATE TABLE users (
  id INT PRIMARY KEY,
  username VARCHAR(50) NOT NULL -- 用户名不能为空
);

3. 唯一约束(UNIQUE)

  • 作用:确保列中所有值都是唯一的(不重复),但允许 NULL(最多一个 NULL )。
  • 示例:
CREATE TABLE emails (
  id INT PRIMARY KEY,
  email VARCHAR(100) UNIQUE  -- 邮箱地址不能重复
);

4. 默认约束(DEFAULT)

  • 作用:当插入数据时未指定该列的值,自动使用默认值填充。
  • 示例:
CREATE TABLE products (
  id INT PRIMARY KEY,
  status VARCHAR(20) DEFAULT 'active'  -- 默认为"active"状态
);

5. 检查约束(CHECK)

  • 作用:限制列中值的范围或条件(MySQL 8.0.16 及以上支持)。
  • 示例:
CREATE TABLE employees (
  id INT PRIMARY KEY,
  salary DECIMAL(10,2) CHECK (salary > 0)  -- 工资必须大于0
);

6. 自增约束(AUTO_INCREMENT)

  • 作用:自动为新记录生成唯一的递增数值,通常与主键配合使用。
  • 示例:
CREATE TABLE articles (
  id INT PRIMARY KEY AUTO_INCREMENT,  -- 自动生成1,2,3...
  title VARCHAR(100)
);

外键(FOREIGN KEY)

外键是用于关联两个表的约束,确保表之间的数据关联性和一致性。

  • 主表:被从表(包含外键的表)通过主键关联。
  • 核心作用强制从表(含外键的表)的某个字段值必须对应主表(被引用的表)中已存在的主键值。

  • 示例场景
    主表students(学生信息)和从表scores(成绩信息)通过外键关联,确保成绩表中的学生必须是学生表中已存在的。

    -- 主表:学生表
    CREATE TABLE students (
      id INT PRIMARY KEY,
      name VARCHAR(50)
    );
    
    -- 从表:成绩表(含外键)
    CREATE TABLE scores (
      score_id INT PRIMARY KEY,
      student_id INT,  -- 关联学生表的id
      score INT,
      -- 定义外键:student_id必须对应students表的id
      FOREIGN KEY (student_id) REFERENCES students(id)
        ON DELETE CASCADE  -- 主表删除学生时,从表关联成绩也删除
    );
    
  • 外键规则
    当主表数据被修改时,可通过ON DELETEON UPDATE定义从表的行为(如CASCADE级联删除、SET NULL设为NULL等)。

数据完整性(Data Integrity)

完整性指数据库中的数据符合预定规则,不存在无效或错误信息,主要分为四类:

  1. 实体完整性
    确保表中每条记录都是唯一且可识别的,通过主键唯一约束实现(如学生表中“学号”唯一)。

  2. 域完整性
    确保列中数据符合特定格式或范围,通过数据类型非空约束检查约束等实现(如“年龄”必须是正整数)。

  3. 参照完整性
    确保多表之间的关联关系合法,通过外键实现(如成绩表的学生必须在学生表中存在)。

  4. 用户定义完整性
    根据业务需求自定义的规则(如“订单金额必须大于0”),可通过CHECK约束或触发器实现。

唯一性(Uniqueness)

唯一性是指表中某个字段的值不允许重复,主要通过两种方式实现:

  1. 主键(PRIMARY KEY)

    • 不仅要求唯一,还不允许NULL,一个表只能有一个主键。
    • 示例:id INT PRIMARY KEY
  2. 唯一约束(UNIQUE)

    • 仅要求值唯一,允许NULL(但最多一个NULL),一个表可以有多个唯一约束。
    • 示例:email VARCHAR(100) UNIQUE
  • 区别:主键是“唯一标识记录”,唯一约束是“确保字段值不重复”,主键本质上是一种特殊的唯一约束(加非空限制)。

总结

  • 约束条件是保障数据规则的“工具集”(主键、外键、非空等);
  • 外键是约束的一种,专门用于维护表之间的关联关系;
  • 完整性是数据符合规则的“状态”(实体、域、参照等维度);
  • 唯一性是数据的“属性”,确保字段值不重复(通过主键或唯一约束实现)。

合理使用这些机制,能有效保证数据库数据的准确性、一致性和可靠性。

四、SQL 复杂查询

五、MySQL 权限管理

创建用户

1. CREATE USER 用户名@地址 IDENTIFIED BY [PASSWORD] 密码(字符串);                     i迪特反特
2. CREATE USER 'tom'@'localhost' IDENTIFIED BY '12345678';
3. create user 'lisi'@'%' identified by 'lisi@123';
4. # MySQL中的用户由两部分构成
5. username 例如: root
6. host 例如: localhost (本机)、192.168.8.20、192.168.8.%、%

8.'tom'@'localhost' 和 'tom'@'%' 主机名不同,不是同一个用户

登录用户

mysql  -u用户名 -p  -hIP地址

mysql -ulily -p12345678 -h192.168.8.100

删除用户

drop user 用户名@'%';
drop user 用户名@localhost;

# 或者
use mysql;
delete from user where user="用户名";

修改用户名

rename user '旧的用户名'@'旧的ip地址'  to '新的用户名'@'新的ip地址'

rename user 'admin1'@'%'  to 'lily'@'192.168.8.%';

查看所有的用户

use mysql
select user,host form user;

修改密码

root 修改自己的密码
set password = password (' 密码 ');
修改其他用户的密码
SET PASSWORD FOR 'tom'@'%' = PASSWORD ( '12345678' );
set password for 'tom'@'%' = '12345678';

# MySQL8.x,修改密码
alter user '用户'@'地址' identified by '密码';
ALTER USER 'tom'@'%' IDENTIFIED BY '12345678';

 FLUSH PRIVILEGES;  
 # 重启

 

给用户设置权限

show grants;

查看当前用户权限

show grants for admin@localhost;

查看其他 MySQL 用户(admin)权限

revoke 撤销权限

* all       除了授权之外的所有权限
* select    查询表内容的权限
* update    修改表内容权限
* insert    在表中添加内容的权限
* delete    删除表中内容的权限
GRANT ALL PRIVILEGES ON school.* TO "tom"@"%";

 grant 权限列表 on 库.表 to '用户'@'地址';  
 
 GRANT ALL PRIVILEGES ON school.* TO "tom"@"%";  
 
 grant select,update,insert,delete *.* to 'zhangsan'@'192.168.8.%';  
 
grant select on *.* to admin1@localhost; -- admin1
  授权查询在所有*库*表的权限给admin1
 可以查询 MySQL 中所有数据库中的表
 
 grant select on admindb.* to admin@localhost;  -- admin 
 授权 查询 在admindb的库里的所有表给admin用户
 可以查询 admindb中的表
 
 grant select(id, name, age) on admindb.goods_log to admin@localhost;
 授权查询id,name,age,数据库admindb里名为goods_log的表,给用户admin
 
 函数、存储过程与授权的关系,本质是数据库通过权限控制,确保用户只能合法地使用这些预定义程序,既保证业务需求,又防止滥用。具体关联是
授权是使用函数 / 存储过程的前提
通过授权实现 “间接操作”,提升安全性
权限粒度可精确到单个程序
权限继承与回收

六、MySQL 备份

备份数据库

选项
option	含义
-u	用户名
-p	密码
-h	服务器 ip, localhost 默认
-p	连接端口, 3306 默认
输出选项
option	含义
-n	剔除数据库创建语句(只保存数据库数据)
-t	剔除数据表创建语句 (只保存表数据)
-d	剔除数据(只保存结构)
-T	生成两文件,一个. sql 表结构,一个. txt 数据文件非 insert(备份双份)

查看 MySQL 信任的导出路径
show variables like 'secure_file_priv'
# var/lib/mysql-file/
导出
mysqldump -uroot -proot123 -T /var/lib/mysql-files/ db_name file_name
1. 备份单个数据库
如果你想备份名为testdb的数据库,假设 MySQL 用户名是root,密码是password,可以在命令行中执行以下命令:
mysqldump -u root -p password testdb > backup_testdb.sql
-u root:指定连接 MySQL 服务器的用户名是root。
-p password:指定用户密码
testdb:是要备份的数据库名称。
> backup_testdb.sql:将备份结果输出到名为backup_testdb.sql的文件中
2. 备份整个 MySQL 服务器上的所有数据库
要备份所有数据库,使用以下命令:
mysqldump -u root -p --all-databases > all_databases_backup.sql
或者
mysqldump -u root -p -A > all_databases_backup.sql
这里--all-databases或-A选项表示备份所有数据库。
3. 备份指定数据库中的特定表
如果只想备份testdb数据库中的users表和orders表,可以执行:
mysqldump -u root -p testdb users orders > backup_testdb_tables.sql
4. 恢复备份
当需要从备份文件恢复数据时,可以使用mysql命令。假设要将之前备份的backup_testdb.sql恢复到testdb数据库中,先登录 MySQL:
mysql -u root -p
然后在 MySQL 命令行中选择目标数据库:
USE testdb;
最后执行恢复操作:
SOURCE /path/to/backup_testdb.sql;
source /path/to/backup_testdb.sql;
source +路径
这里/path/to/需要替换为备份文件实际所在的路径。
mysqlimport -uroot -p12345 db_name /var/file_name.txt
也是恢复备份,把db_name导出到后面路径
5. 其他常用选项
指定服务器 IP 和端口:如果 MySQL 服务器不在本地,或者端口不是默认的 3306,可以使用以下方式:
mysqldump -u root -p -h 192.168.1.100 -P 3307 testdb > backup_testdb.sql
其中-h 192.168.1.100指定服务器 IP,-P 3307指定端口。
忽略某些表:如果在备份数据库时,想忽略某些表,可以使用--ignore-table选项,例如:
mysqldump -u root -p testdb 
--ignore-table=testdb.logs --ignore-table=testdb.temp
> backup_testdb_except.sql
忽略test下面的logs和temp
这条命令会备份testdb数据库,但会忽略logs表和temp表。

数据库备份

  • 为了防止数据丢失、方便数据迁移,建议定期备份数据中的数据。

  • 方式:

    • 逻辑备份:将数据库中库和表转换为SQL语句,生成sqql文件。还原数据时只需要运行改SQL语句。适合中小规模的数据,30GB以内数据。数据量过大时,转换效率慢。

    • 物理备份:将数据库的data目录,直接复制备份。

      • 冷备份:关闭MySQL—Server后进行的备份
      • 热备份:使用专业的数据备份工具,在服务运行中备份。
      • 全量备份:每次备份都备份所有数据。
      • 增量备份(差异备份):之备份新增的数据或不一样的数据
# 冷备份
systemctl stop mysql
关机
mkdir -p /bak/2025/8/11/
创存放数据的文件
cp -r /usr/local/mysql/data  /bak/2025/8/11/data
复制
systemctl start mysql
开机

# 还原
systemctl stop mysql
关机
rm -rf /usr/local/mysql/data
删除
cp -r  /bak/2025/8/11/data  /usr/local/mysql/
复制(恢复)
chown mysql.mysql -R /usr/local/mysql/data
把mysql权限重回给mysql(因为上面复制后可能更改所有人为root)
systemctl start  mysql
开机
  • 物理热备:
    • Xtrabackup:percona 免费的数据热备工具。
    • Hotbackup:收费版数据热备工具。
删除超过一周的备份及自动备份数据库的方式会因操作系统及具体数据库类型有所不同。下面以常见的 MySQL 和 PostgreSQL 数据库为例,为你介绍相关实现方法:
删除超过一周的备份
在 Windows 系统中
若为 MySQL 数据库,可用 forfiles 命令删除超一周的备份文件。像备份文件保存在 C:\mysql_backups 目录时,创建 .bat 文件写入以下内容并执行即可:
forfiles /p "C:\mysql_backups" /d -7 /c "cmd /c del @file"
在 Linux 系统中
借助 find 命令识别并删除符合条件的文件。例如,PostgreSQL 备份文件在 /beifen/zhujian/all/ 目录,文件名以 zj-beifen 开头,可创建脚本如 delete_zhujian.sh 来删除旧备份:
find /beifen/zhujian/all/ -name "zj-beifen*" -mtime +7 -exec rm -rf {} \;
针对 MySQL 备份在 /tmp/mysqlbackup 目录的场景,删除脚本命令可写为:
find /tmp/mysqlbackup/ -mtime +7 -exec rm -f {} \;
自动备份数据库
MySQL 数据库
Windows 环境:编写备份脚本 .bat 文件,内容可参考:
plaintext
set TIMESTAMP=%date:~-4,4%_%date:~-10,2%_%date:~-7,2%_%time:~0,2%_%time:~3,2%_%time:~6,2%
set MYSQL_USER=root
set MYSQL_PASSWORD=yourpassword
set DATABASE_NAME=your_database
set BACKUP_PATH=C:\mysql_backups
mysqldump -u %MYSQL_USER% -p%MYSQL_PASSWORD% %DATABASE_NAME% > %BACKUP_PATH%\%DATABASE_NAME%_%TIMESTAMP%.sql
然后,通过 “任务计划程序” 创建基本任务,按提示设定定时运行该 .bat 文件的周期与时刻。
Linux 环境:创建 backup.sh 备份脚本,示例代码如下:
plaintext
#!/bin/bash
date=$(date +"%Y%m%d")
backup_filename="db_backup_${date}.sql"
backup_path="/home/your_username/backups"
mysqldump -u your_username -p your_password --all-databases > $backup_path/$backup_filename
并通过 chmod +x backup.sh 赋予其执行权限。再用 crontab -e 编辑定时任务,若想每天凌晨 3 点 30 分备份,可添加:
30 3 * * * /bin/bash /home/your_username/backup.sh
PostgreSQL 数据库
通常在 Linux 下利用 pg_dump 与 cron 定时任务配合。先创建备份脚本,如备份 postgres 数据库至 /beifen/zhujian/all 目录的脚本内容可为:
plaintext
echo "开始执行 PostgreSql 数据库 postgres 的备份!nowtime=$(date +%F+%T)"
/usr/local/postgresql/bin/pg_dump --file "/beifen/zhujian/all/zj-beifen-"$nowtime".backup" --host "192.168.1.163" --port "5432" --username "postgres" "postgres" --verbose --role "postgres" --format=c --blobs --encoding "UTF8"
echo "数据库 postgres 备份结束!"

保存后用 chmod +x 赋予权限。之后 crontab -e 设置定时任务,例如每天 23 点备份,添加配置:
0 23 * * * /beifen/zhujian/对应的备份脚本文件名.sh

七、MySql进阶

事务

事务:一组数据库的操作(SQL)集合,这个集合中的操作(SQL)要么都执行,要么都不执行。

保证数据库的完整性与一致性。保证数据安全。

案例:银行转账;

​ 张三->李四转钱;

注意:

mysql的事务默认自动提交的,也就是说当执行完一条DML语句时,MySQL 会立即隐式提交事务。

在数据库增、删、改时,才需要开启事务,查询不会改变数据内容。

一组 SQL 都执行成功了,提交(commit);
任意一条语句执行失败,则回滚(rollback);

# 简单案例:
drop table if exists account;
create table account(
    id int primary key AUTO_INCREMENT comm
'ID',
    name varchar(10) comment '姓名',
    money double(10,2) comment '余额'
    )comment '账户表';
 insert into account(name,money)VALUES('张三',2000) ,('李四',2000);  
    
--开启事务
START transaction;
或
-- begin;
14 SELECT * FROM account WHERE name = '张三';
15 UPDATE account SET money = money - 1000 WHERE name = '张三';
16 UPDATE account SET money = money + 1000 WHERE name = '李四';
17 -- 提交事务
18 COMMIT;
19 -- 事务回滚
20 ROLLBACK;

事务的四大特性(ACID)

  • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务完成时,必须使所有数据都保持一致状态。
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
  • 持久性(Durability):事务一旦提交或回滚,他对数据库中的改变就是永远的

数据库并发问题:

  • 脏读:一个事务读取到另一个事务的数据
  • 不可重复读:一个事务先后读取同一个数据,但是结果不一致。
  • 幻读:一个事务在查询时候没有对应数据,在添加或修改时候突然出现了

事物的隔离级别:

  • read uncommitted (读未提交)
    • 允许读取没有提交的数据,容易引发脏读
  • Read committed(读已提取)
    • 只允许读取已提交的数据,可以避免脏读,但是可能出现不可重复读。
  • Repeatable read(可重复读)
    • 保证一个事务多次读取是一致的,但有可能出现幻读。
  • Serializable(可串行化,序列化)
    • 最高的隔离级别,避免脏读、幻读、不可复读,会降低数据库的性能。

视图

视图(view):是虚拟的表,通常用于简化复杂的查询。

视图中的数据来源于基表(基础表)。基表发生变动,视图会受到影响。视图中的数据时动态生成的,它是一条 Select 语句的结果集。

  • 视图的功能:
    • 简化复杂查询
# 创建
create view 视图名称 as select ...
## 例如:
create view user_view as select * from users where age <= 30;
# 使用:方法与“表”一致
select * from user_view;
# 修改: 创建或替换CREATE OR REPLACE
create or replace view  user_view as select username,city from users where age <= 30;
# 删除
drop view user_view;

存储引擎

存储引擎:实现对数据增、删、改、查、事务、索引的数据库核心组件。

MySQL服务端的组成:

  • 连接层:通过网络或本地socket和客户端通信,登录、安全、授权认证等安全方案。
  • 服务层:接受SQL语句,进行语句分析,下发指令让引擎层执行。
  • 引擎层:存储引擎真正的负责了 MySQL 中数据的存储和提取,不同的需求可以使用不同的引擎。
  • 存储层:文件系统用于存储数据,并完成与存储引擎的交互。
    • 常用引擎:
      • InnoDB(默认):支持事务(ACID)、支持行级锁、聚簇索引,适合高并发、高安全场景,金融、电商、订单系统。
      • MyIsAM:不支持事务、支持表级锁,适合对事务没要求、读多写少的场景。
      • MEMORY:内存型存储引擎,支持哈希(hash)索引,优点:读写速度快;缺点:断电数据会丢失。适合缓存临时数据。
      • CSV:文本存储,列与列默认用”逗号“分隔;优点:可直接用文本编辑器查看或修改数据,兼容性强(适合与其他系统交换数据)。缺点:性能差,不支持事务、索引、锁,适合:简单的数据存储例如:日志

索引

index(索引、目录、下表标)

定义:加快数据查询的一类数据结构。类似于字典的目录,可以帮助我们快速找到我们想要的数据内容。

注意:索引是和存储引擎关联的,不同的存储引擎提供索引类型不同。

优点:

  • 数据量大时,对于查询速度有较为明显的提升。

缺点:

  • 1.会占用一定的存储空间;
  • 2.会影响写入速度(增、删、改);

索引的分类:

  • 数据结构
    • B+tree:InnoDB、MyIsAM
      • 所有数据存储叶子节点
      • 所有数据存储在叶子节点,且叶子节点通过双向链表连接,支持范围查询的高效遍历。
      • 非叶子节点仅存储索引键,用于快速定位区间,减少单次查询的 IO 次数。
      • 高度通常为 3 - 4 层,可存储千万级数据(单节点存储多个键值)。
    • hash:Memory键值对,哈希函数,使用了哈希算法
      • 哈希算法:将所有数据相加,经过取模(x%y)运算,得到固定长度的值。这个结果就是键key,对应一个内存地址,将数据存放进去。查找数据时,通过计算找到key对应的地址,直接取值。
    • R-tree:MyIsAM支持
  • 逻辑结构(创建视图);
    • 主键索引
    • 唯一索引
    • 普通索引(单值索引、单列索引)
    • 复合索引(多列索引)
    • 全文索引(MyIsAM支持、InnoDB不支持)

数据结构:

  • 线性结构:队列、栈、链表、数组
  • 树状结构:二叉树、二叉搜索树、红黑树、B树、B+树
  • 图状结构:有向图、无向图

二分查找法:先排序,从中间开始找,小的向左找,大的向右找,缩小范围,不断重复;二叉搜索树

全局查找:使用穷举法,一个个找一个个试;

也就是说,这一个表的这一列叫name我自己知道,但是数据库也知道,他也知道在哪个表,但是会再次全表搜索,我加了这个索引以后,数据库就可以根据我的这个name名字快速找到,不在查看其它内容吗
是的,你的理解基本正确,更准确的表述是:
当你在 employees 表的 last_name 列上创建索引后:
原本没有索引时,数据库会对 employees 表执行全表扫描(逐行检查每一条记录的 last_name 是否符合查询条件);
有了索引后,数据库会直接通过索引结构定位到所有 last_name 匹配的记录位置,只读取这些符合条件的行,无需再查看表中其他无关的记录,从而避免了全表扫描,大幅提升查询效率。
简单说,索引就像给这一列的数据做了一个 “目录”,数据库通过目录直接找到目标内容,不用逐行翻查整个表了。
#主键索引:就像每个人的身份证号,唯一对应一个人,用它查信息能直接定位到 “某一个人的完整信息”(比如通过employee_id=1001查某个员工的所有数据),效率最高,且确保不会重复。ps:索引就是身份证号
ALTER TABLE employees ADD PRIMARY KEY (employee_id);
唯一
#单值索引:就像给 “姓名”“部门” 这类单列做了目录,方便按 “类别” 批量查找(比如查所有叫 “Smith” 的人、所有属于 “销售部” 的人),不要求唯一,适合频繁按这一列筛选的场景。ps:给列作索引
CREATE INDEX idx_name ON employees (last_name);
一类
#唯一索引:类似 “手机号”,既要求不重复(防止多个人用同一个手机号),又能快速通过手机号找到对应的人。
CREATE UNIQUE INDEX idx_email ON users (email);
唯一
#复合索引:就像 “姓名 + 部门” 的组合目录,适合同时按这两个条件查(比如 “找销售部所有叫 Smith 的人”),比单独查更高效,但要注意查询时尽量从第一个条件开始用。
CREATE INDEX idx_name_age ON employees (last_name, age);
合并同类
#索引的核心功能确实是加速查询,但某些类型的索引(如唯一索引、全局唯一索引)同时具备约束数据唯一性的作用,这是 “查询优化” 之外的附加功能。
CREATE FULLTEXT INDEX idx_description ON articles (description);
#空间索引:就像城市地图上的 “区域标注”,比如在地图上把商圈、住宅区、公园等区域用不同颜色标注出来。当你想找 “某公园 300 米内的咖啡馆” 时,不用逐个查看全城店铺,直接通过标注的区域快速定位范围内的目标,专门优化地理位置、区域范围类的查询(比如经纬度、多边形区域相关的搜索)。
也就是说处理带经纬度的数据呗,给他们上了空间索引后,会给他们按区块划分,像二叉树一样向下分级
范围
CREATE SPATIAL INDEX idx_location ON places (location);
#哈希索引:就像字典的 “首字母目录”,但更直接 —— 给每个关键词计算一个唯一的 “哈希码”,比如 “apple” 对应 “123”,“banana” 对应 “456”。查询时直接通过哈希码定位,不用逐行比对,适合 “精准匹配” 场景(比如按身份证号查信息),但不适合范围查询(比如 “找年龄在 20-30 岁之间的人”),因为哈希码的顺序和原数据无关。
哈希可以选中任意能被转换为e的内容,转换为哈希值然后存储在自己的库里,和位图相反
CREATE INDEX idx_name_hash USING HASH ON employees (last_name);
当你执行查询 WHERE last_name = 'Smith' 时:
数据库会先对查询条件中的 "Smith" 计算哈希值(比如得到 1a3b5c)。
直接到哈希表中查找 1a3b5c 对应的地址,瞬间定位到数据行,不需要像全表扫描那样逐行比对,效率极高。
精确身份证,手机号
#位图索引:就像学生名单上的 “特征标记”,比如用不同颜色的圆点标记 “男生 / 女生”“近视 / 不近视”—— 每个特征对应一列标记,1 表示有该特征,0 表示没有。当要查 “所有近视的男生” 时,直接把 “男生” 和 “近视” 两列的标记做叠加,瞬间找出同时满足两个特征的人,适合数据重复值多的列(比如性别、职业类型),能快速做组合条件筛选。

SHOW INDEX FROM table_name;
位图索引其实就是多个列标记,然后选择都有标记的对吗
你的理解很接近核心逻辑!位图索引(Bitmap Index)确实是通过对列值进行 “标记”,并通过标记的组合快速定位符合条件的记录,尤其适合列值重复度高的场景(比如性别、部门、状态等枚举类字段)。
比如要筛选 “叫张三的男人”,如果对 “性别” 列建了位图索引:
位图索引会先快速定位所有 “性别 = 男” 的记录(通过男性的标记向量,直接找到所有标记为 1 的行);
再在这些男性记录中筛选 “姓名 = 张三” 的人。
#全文索引的核心是用 “关键词→行 / 文档” 的映射关系标记 “哪些行包含某个词”:
先对文本内容分词(拆成关键词),再为每个关键词记录包含它的行 ID 列表(或文档 ID)。例如,关键词 “数据库” 的标记是 [行 1, 行 5, 行 8],表示这几行文本包含 “数据库”。通过这种映射,能快速定位包含特定关键词的文本。

我们可以把数据库里的 “索引”,想象成图书的 “目录”,通过目录能快速找到想要的章节,而索引能让数据库快速找到对应的数据,下面来逐个解析这些索引:

  1. 主键索引

就像每本书都有唯一的书号,能精准定位这本书。在数据库表中,主键索引用于唯一标识每一条记录。

  • 唯一性:表中每条记录的主键值都不一样,比如学生表用学号做主键,每个学生学号唯一。
  • 非空性:主键对应的字段不能没有值,学号必须得有,不能空着。
  • 自动索引:当你给表定义主键时,数据库会自动为这个主键字段创建索引,方便快速查找。
  • 优化查询、数据完整性:有了主键索引,查询数据时能更快找到目标记录;同时保证数据不会出现重复、混乱的情况,维护数据的准确性。
  1. 单值索引

好比图书目录里,一个目录项只对应书中一个章节(一列数据)。一个单值索引只针对表中的单个列创建。
比如学生表有 “姓名” 列,给 “姓名” 列建单值索引,一个表可以有多个这样的单值索引,像还能给 “年龄” 列也建单值索引。

  1. 唯一索引

类似图书里的 “限量版标记”,要求索引列的值必须唯一,但可以有空值。
比如学生表的 “身份证号” 列,建唯一索引,每个学生身份证号肯定唯一,但如果有学生还没录入身份证号,该字段可以为空。

  1. 复合索引

就像图书目录里,一个目录项对应多个相关章节(多列数据)。复合索引是基于表中多个列创建的索引。
比如学生表有 “年级” 和 “班级” 列,建复合索引,当查询同时涉及 “年级” 和 “班级” 的条件时,复合索引能比单值索引更快找到数据,提升多列查询的效率

锁:解决并发事务中的问题,例如:幻读、不可重复读、脏读。

“占位”的操作。

锁的分类:

  • 颗粒度(从大到小)
    • 全局锁:锁整个库,组织写操作。
    • 表级锁:锁一个表
    • 行级锁:锁某个记录或某个范围
  • 属性
    • 共享锁(S):读锁,其他用户和事务只能查询,不能修改。
    • 排他锁(X):写锁,其他用户和事务不能进行任何操作
  • 状态
    • 意向共享锁(IS):表示某个事务即将加共享锁的意图。
    • 意向排他锁(IX):表示某个事务即将加排他锁的意图。
  • 模式
    • 乐观锁:在读多的场景,事务冲突概率低,不加锁,在操作完成后校验。
    • 悲观锁:预计冲突的概率高,直接加锁,写操作比较多

SQL优化

1.插入数据时:

  • 批量插入

  • 手动控制事务

  • 主键按顺序插入,建议使用AUTO_INCREMENT.不建议使用UUID作为主键

  • 4.大批量导入数据时,建议客户端添加--local-infile选项,直接从文本导入数据

    load data local infile '/root/user1.csv' into table user1 fields 
    terminated by ',' lines terminated by '\n';
    

2.主键的优化

  • 1.尽量简短一些
    2.按顺序添加,AUTO_INCREMENT
    3.尽量不要使用 UUID 做主键或者是其他自然主键,如身份证号。
    4.业务操作时,避免对主键的修改。

3.order by 排序

  1. 数据库order by排序优化相关:

    • Using FileSort:全表扫描后在排序缓冲区(sortbuffer)完成排序,非通过索引直接返回结果的排序方式。

    • Using Index:利用索引列排序(索引默认有序),可给需排序列添加单列或联合索引。

      • 多列索引生效依赖 “最左前缀” 原则,需从第一列开始匹配。

      • 2.在使用索引排序时,不要用 “select * from …”,“*” 会导致索引失效,变为全文扫描。

日志

  • 两个日志(master 的 bin - log 和 slave 的 relay log)
  • 三个线程(master 的 dump 线程、slave 的 io 线程和 sql 线程)

1.master(主服务器)执行DDL或DML语句时,会记录bin-log

2.bin-log写入成功后,dump线程会通知slave(从服务器)节点

3.slave使用io线程读取master的bin-log日志,并写入relay log中

4.slave使用sql线程将relay log 中新添加的内容转换为SQL语句,并执行,从而实现从节点(slave)与主节点(master)的数据一致.

线程是进程中任务最小执行单元,一个进程中可以包含多个线程,执行相同或不同的功能,实现多线程并发执行。

线程

八、MySQL 主从集群

  • 主bin-log 从 relay -log
  • 主dump 从io,sql

作用:

  • 实时备份:主服务器实时备份数据到从服务器,主服务器中数据丢失时,可以重从服务中恢复数据.
  • 读写分离:主服务器主要负责写的操作(insert\update\delete),从服务器主要负责读(select)的操作.
  • 高可用集群:当主服务器突然下线,从服务器可以很快的接替它的功能
  • 负载均衡:将原本一台服务器处理的请求,分发给多台服务器去处理,适用于高并发场景,防止单台服务器负载过高崩溃.

MySQL主从复制步骤

STOP SLAVE IO_THREAD;

若重新连接日志,需要终止io线程

报错3081

STOP SLAVE FOR CHANNEL '';

报错1872

STOP SLAVE;

RESET SLAVE ALL; -- 注意:该命令会清除从库记录的主库信息,需重新配置

重新配置日志

1858密码强度不足


STOP SLAVE IO_THREAD;
STOP SLAVE FOR CHANNEL '';
STOP SLAVE;
RESET SLAVE ALL;
#1. 安装脚本18.0.20
bash mysql_install.sh

#2. 编辑主服编号,方便后续连接
vim /etc/my.cnf
#3. 在[mysqld]里插入下文
server-id=1
log-bin= /usr/local/mysql/data/mysql-bin
binlog_format=ROW  # ROW模式(MHA推荐)
gtid_mode=ON  # 开启GTID
enforce_gtid_consistency=ON  # 强制GTID一致性
log_slave_updates=ON  # 从库同步时记录binlog(用于级联复制)
skip_name_resolve=ON

# 4.编辑从服编号,方便后续连接
vi /etc/my.cnf
# 在[mysqld]里插入下文
server-id=3
log_bin=mysql-bin
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON
skip_name_resolve=ON
relay_log=relay-bin  # 开启中继日志
read_only=ON

#5.配置完同时重启
/etc/init.d/mysqld restart

#6.关闭两个的防火墙
#临时关闭(重启后恢复)
systemctl stop firewalld
#永久关闭(禁止开机启动)
systemctl disable firewalld

#7.主数据库创建用户slave并授权
# 在主数据库端(192.168.8.3)
# 登录mysql -uroot -p
# 创建用户
create user 'slave'@'%' identified with mysql_native_password by 'root123';
# 授权
grant replication slave on *.* to 'slave'@'%';
# 刷新权限
flush privileges;

#8.从数据库端验证主数据库slave用户是否可用
# 在从数据库端(192.168.8.4)验证主数据库slave用户是否可用
mysql -uslave -p -h192.168.8.5 -P3306

#9.配置主从节点信息
# 在主数据库端(192.168.8.3)
mysql -uroot -p
# 查询server_id是否可配置文件中一致
show variables like 'server_id';
# 若不一致,可设置临时ID(重启失效)
set global server_id = 100;
# 查询Master状态,并记录 File(对应下一步中的master_log_file)
# Position (对应下一步中的master_log_pos)的值
show master status;
# 注意:执行完此步骤后退出主数据库
# 防止再次操作导致 File 和 Position 的值发生变化
#10.在从数据库端设置同步
# 在从数据库端(192.168.8.4)
# 登录
mysql -uroot -p
# 查询server_id是否可配置文件中一致
show variables like 'server_id';
# 若不一致,可设置临时ID(重启失效)
set global server_id = 101;
# 设置主数据库参数(用上一步创建的slave用户及密码)
change master to 
master_host='192.168.8.3',
master_port=3306,
master_user='slave',
master_password='root123',
master_log_file='mysql-bin.000021',
master_log_pos=236;
# 开始同步
start slave;
# 查询Slave状态
show slave status\G;
# 查看是否配置成功
# 查看参数 Slave_IO_Running 和 Slave_SQL_Running 是否都为yes,则证明配置成功。若为no,则需要查看对应的 Last_IO_Error 或 Last_SQL_Error 的异常值
# 若出现错误,则停止同步,重置后再次启动
stop slave;
reset slave;
start slave;
# 可以在从服务器my.cnf中添加
slave_skip_errors = ALL
# 跳过错误,继续同步

#11.测试,在主服务器create一个库,从服务器查询到,则无问题

#易错点:
1不能克隆安装有mysql的虚拟机,
2.注意防火墙
3.下载可避开cs7yum --disablerepo=c7-media install后面加下载软件或者yum --disablerepo=c7-media [你的yum操作命令]
4.安装完mysql后,要重新加载source //etc/profile然后执行bash

解决步骤(必须严格执行):
从库停止所有复制线程并重置配置
登录从库 MySQL:
sql
STOP SLAVE FOR CHANNEL '';  -- 停止所有复制线程
RESET SLAVE ALL;  -- 彻底清除旧配置

使用正确密码(repl123)重新配置主从连接
注意 MASTER_PASSWORD 必须是 repl123(与手动登录成功的密码一致):
sql
CHANGE MASTER TO
  MASTER_HOST='192.168.8.3',  -- 直接用主库IP,避免hostname解析问题
  MASTER_USER='repl',
  MASTER_PASSWORD='repl123',  -- 这里必须用手动登录成功的密码
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION=1;

启动复制并检查状态
sql
START SLAVE;
SHOW SLAVE STATUS\G

关键原因总结:
你之前手动登录主库成功的密码是 repl123,但从库配置时误用了其他密码(Repl@123、repl@123),导致密码不匹配。只要确保 CHANGE MASTER TO 中的 MASTER_PASSWORD 与手动登录成功的密码(repl123)完全一致,问题即可解决。
执行后,Slave_IO_Running 应变为 Yes,Last_IO_Error 为空,主从同步正常启动

MySQL的读写分离

CentOS7安装proxysql(在主服操作)
#1. 配置官方yum源,或直接下载rpm包(下载地址:https://github.com/sysown/proxysql/releases)
cat > /etc/yum.repos.d/proxysql.repo << EOF
[proxysql]
name=ProxySQL YUM repository
baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.5.x/centos/\$releasever
gpgcheck=1
gpgkey=https://repo.proxysql.com/ProxySQL/proxysql-2.5.x/repo_pub_key
EOF
#.yum安装proxysql
yum makecache
yum install proxysql
上述不行则执行 yum --disablerepo=c7-media makecache
#启动proxysql服务并加入开机自启
systemctl start proxysql
systemctl enable proxysql
#3.使用mysql客户端,并使用以下admin凭据在本地端口(6032)上进行连接。默认账号密码admin:admin(主机操作进入proxysql)(在主服操作)
mysql -uadmin -padmin -h127.0.0.1 -P6032
#进入proxysql
show databases;
#查看

#4.添加一个ProxySQL账号,例如:添加一个root:root123的用户和密码(在主服操作)
select @@admin-admin_credentials;#查询当前
set admin-admin_credentials='admin:admin;root:root123';
#管理接口,加入用户密码
select @@admin-admin_credentials;  #查询是否正常
load admin variables to runtime;   # 使修改立即生效
save admin variables to disk;    # 使修改永久保存到磁盘

#5.在主节点的MySQL中创建监控用户(在mysql里不是proxysql里需要新开查哨)(在主服操作)
CREATE USER 'monitor'@'%' IDENTIFIED BY 'monitor';
GRANT USAGE, REPLICATION CLIENT ON *.* TO 'monitor'@'%';
#将监控用户加入到proxysql中
UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_username';
UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_password';
#6.将Master和slave节点添加到mysql_servers表中(在proxysql操作)
注意:是在proxysql中操作
#-- Master主节点
INSERT INTO mysql_servers(hostgroup_id,hostname,port,weight,comment) VALUES (1,'192.168.8.3',3306,1,'Write group');
#-- slave节点
INSERT INTO mysql_servers(hostgroup_id,hostname,port,weight,comment) VALUES (2,'192.168.8.4',3306,1,'Read group');
#-- 保存
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
#查看添加的mysql集群
SELECT * FROM mysql_servers\G;
#目的是把写权限给主,把读权限给从
#7.在MySQL主从节点上创建用户,赋予权限,并将其存储到代理服务器中。(在主服操作)
-- 在Master节点和slave节点上创建adm用户,设置为管理员权限。
CREATE USER 'adm'@'%' IDENTIFIED BY '123456';
GRANT ALL PRIVILEGES ON *.* TO 'adm'@'%';
-- 在Master节点和slave节点上创建用户read,并设置权限为只读。
CREATE USER 'read'@'%' IDENTIFIED BY '123456';
GRANT SELECT ON *.* TO 'read'@'%';
FLUSH PRIVILEGES;

#8.在proxysql上添加用户(在p操作)
-- 在proxysql上添加用户
INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('adm','123456',1);
INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('read','123456',2);
-- 保存
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
select hostgroup_id, hostname, port,status from runtime_mysql_servers;
#9.在proxysql上配置读写规则(在主服操作)
INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply) VALUES (1,1,'^SELECT.*FROM UPDATE$',1,1);
INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply) VALUES (2,1,'^SELECT',2,1);
INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply) VALUES (3,1,'^SHOW',2,1);
-- 保存规则
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
-- 查看规则
select rule_id,match_digest,destination_hostgroup,apply from mysql_query_rules order by rule_id;

#10..测试能否正常读取(在主服操作)
#一定要关掉所有防火墙
直接在ProxySQL所在服务器的Linux命令行执行下列命令
mysql -uread -p123456 -h 127.0.0.1 -P6033 -e "SELECT @@hostname,@@port"
# 在代理服务器上执行读操作
mysql -uread -p123456 -h 127.0.0.1 -P6033 -e "show databases;"
# 执行创建操作,测试效果
mysql -uadm -p123456 -h 127.0.0.1 -P6033 -e "create database test2;"
# 再次查询
mysql -uread -p123456 -h 127.0.0.1 -P6033 -e "show databases;"

# 可以看到proxysql将不同的请求分别发送给了不同的服务器处理,读取发送给slave节点,写入和删除发送给Master节点。
# 在proxysql服务器上执行
mysql -uadmin -padmin -h127.0.0.1 -P6032
select hostgroup,digest_text from stats_mysql_query_digest\G;
出现
*************************** 1. row ***************************
  hostgroup: 1
digest_text: create database test6
*************************** 2. row ***************************
  hostgroup: 2
digest_text: show databases
*************************** 3. row ***************************
即为正确
## ProxySQL保存配置:

-- 修改后重新加载服务并保存配置,防止重启服务器后配置丢失。
-- 重新加载并保存服务器设置
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
-- 重新加载并保存查询设置
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
-- 重新加载并保存用户设置
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
-- 重新加载并保存变量设置
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
### 主从分离的核心是把主服务器的查看权限丢给从服务器,从而缓解主服务器的压力,主服务器只是赋予从查看权限,它本身也是还可以查询的.

MySQLd集群

#1,需要准备三台机子,一台主服务器,一台从服务器,一台mycat搭建的目的是通过mycat可以更改主从服务器的内容,分担主服务器的压力,集中从服务器的性能
#2.找一对已经搭建好的主从服务器,通过主服务器,对mycat创建一个用户,并赋予权限,允许其连接(在主服操作)
# 常见出现 ERROR 1045 是因为 root 用户在 192.168.8.7 主机登录权限或密码错误。
附加:
#1.启动mycat方法(常见于2003报错)
[root@192 ~]# cd /usr/local/mycat/bin
[root@192 bin]# ./mycat status
Removed stale pid file: /usr/local/mycat/logs/mycat.pid
mycat2 is not running. 
#先cd进入,随后执行启动
./mycat restart

#2.默认密码为123456,经常习惯性输入root123密码,所以会报1045报错
#3. 常见出现 ERROR 1045 是因为 root 用户在 192.168.8.7 主机登录权限或密码错误。解决步骤:
登录 192.168.8.3 本地 MySQL(用有权限账号)。
执行 CREATE USER 'root'@'192.168.8.%' IDENTIFIED BY 'root123';(若用户已存在,可 ALTER USER 'root'@'192.168.8.7' IDENTIFIED BY 'root123';)。
执行 GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.8.%'; FLUSH PRIVILEGES; 赋予权限并刷新。
再用 mysql -h 192.168.8.3 -P 3306 -u root -p(回车后输入正确密码)登录。

1. 编辑 prototypeDs.datasource.json 配置文件
bash
# 在 conf 目录下执行,编辑 prototypeDs 数据源配置
vi datasources/prototypeDs.datasource.json
2. 修改密码字段
文件内容大致如下(重点关注 password 字段):
json
{
  "dbType": "mysql",
  "idleTimeout": 60000,
  "initSqls": [],
  "initSqlsGetConnection": true,
  "instanceType": "READ_WRITE",
  "maxCon": 1000,
  "maxConnectTimeout": 30000,
  "maxRetryCount": 5,
  "minCon": 1,
  "name": "prototypeDs",
  "password": "旧密码",  // 这里需要改为本地 MySQL 的正确密码
  "type": "JDBC",
  "url": "jdbc:mysql://localhost:3306/mysql?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true",
  "user": "root",
  "weight": 0
}
将 password 的值改为 本地 MySQL 的 root 用户实际密码(例如之前重置的 root123)。
3. 保存并重启 MyCat2
bash
# 保存文件后,回到 bin 目录重启服务
cd ../bin
./mycat restart

# 检查 8066 端口是否监听
ss -tln | grep 8066
4. 验证连接
若端口正常监听,尝试连接 MyCat2:
bash
mysql -uroot -p123456 -h127.0.0.1 -P8066
若连接成功,说明数据源密码已同步,问题解决;
若仍提示连接失败,检查 prototypeDs.datasource.json 中的 url 是否正确(是否指向本地 MySQL 的 3306 端口),以及本地 MySQL 是否正常运行。
总结
prototypeDs.datasource.json 是 MyCat2 连接底层数据库的关键配置,只需确保其中的 password 与本地 MySQL 的 root 密码一致,即可解决启动时的认证失败问题,进而使 8066 端口正常监听
修改 Mycat 自身用户密码:
打开 Mycat 的配置文件server.xml,通常位于 Mycat 安装目录的conf文件夹下。例如,若 Mycat 安装在/usr/local/mycat,则使用命令vim /usr/local/mycat/conf/server.xml打开该文件。
在文件中查找要修改密码的用户配置部分。一般用户配置类似如下内容:<user name="root"><property name="password">123456</property><property name="schemas">TESTDB</property></user>。
按i键进入插入模式,修改password标签内的密码值。例如,将密码修改为newpassword,修改后的内容为:<property name="password">newpassword</property>。
修改完成后,按Esc键退出插入模式,输入:wq并回车,保存修改并退出编辑器。
修改 Mycat 连接后端数据库的密码:
打开 Mycat 的配置文件schema.xml,同样位于 Mycat 安装目录的conf文件夹下,使用命令如vim /usr/local/mycat/conf/schema.xml打开该文件。
在文件中找到连接后端数据库的配置部分,例如:<writeHost host="hostM1" url="localhost:3306" user="root" password="123456789"></writeHost>。
按i键进入插入模式,修改password属性的值为新的数据库密码,修改完成后保存并退出文件
#3.主机里需要创一个用户,给予其权限,也可以不创用我们的root,然后主从链接,一般连不上的原因就是从机没用正确输入主机的启用日志和日志位置,或者有重复文件,需要先删除


#4.正式操作,给mycat机器重置配置,开始搭配内容(在mycat操作)
先进入mysql -uroot -p123456 -h127.0.0.1 -P8066
执行重置  /*+ mycat:resetConfig{} */;
# 插入数据
 /*+ mycat:createDataSource
{
    "dbType": "mysql",
    "idleTimeout": 60000,
    "initSqls": [],
    "initSqlsGetConnection": true,
    "instanceType": "READ_WRITE",
    "maxCon": 1000,
    "maxConnectTimeout": 3000,
    "maxRetryCount": 5,
    "minCon": 1,
    "name": "m1",
    "password": "root123",
    "type": "JDBC",
    "url": "jdbc:mysql://192.168.8.3:3306?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8",
    "user": "root",
    "weight": 0
}
*/;

# 更多操作添加读的数据源

/*+ mycat:createDataSource
{
    "dbType": "mysql",
    "idleTimeout": 60000,
    "initSqls": [],
    "initSqlsGetConnection": true,
    "instanceType": "READ",
    "maxCon": 1000,
    "maxConnectTimeout": 3000,
    "maxRetryCount": 5,
    "minCon": 1,
    "name": "m1s1",
    "password": "root123",
    "type": "JDBC",
    "url": "jdbc:mysql://192.168.8.5:3306?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8",
    "user": "root",
    "weight": 0
}
*/;
# 其中第一个是添加主服务器的ip,给与大额权限,第二个是从服务器,读取权限
# 5查看是否成功,成功后会多m1,n1的内容
/*+ mycat:showDataSources{} */\G;
# 6.完成后可以建立集群,从而统一调用

/*! mycat:createCluster{
  "clusterType":"MASTER_SLAVE",
  "heartbeat":{
    "heartbeatTimeout":1000,
    "maxRetry":3,
    "minSwitchTimeInterval":300,
    "slaveThreshold":0
  },
  "masters":[
    "m1"
  ],
  "maxCon":2000,
  "name":"prototype",
  "readBalanceType":"BALANCE_ALL",
  "replicas":[
    "m1s1"
  ],
  "switchType":"SWITCH"
} */
# 7.查询是否成功,成功后会显示
/*! mycat:showClusters{} */\G;
# true则成功,false则失败

# 8创建逻辑库(在mycat执行)
CREATE DATABASE db1 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
#9修改逻辑库中的数据,生成管理权限
vim /usr/local/mycat/conf/schemas/db1.schema.json
## 在里面添加集群的名称,作用是让该集群生成并管理这个库的物理库
"targetName":"prototype",
# 10 测试读写分离是否成功(在MyCAT里面测试)
# 进入 MyCAT 安装目录(示例路径)
cd /usr/local/mycat 
# 重启
./bin/mycat restart
#在MyCAT里面创建一个sys_user表:用于测试
CREATE TABLE SYS_USER(  ID BIGINT PRIMARY KEY,  USERNAME VARCHAR(200) NOT NULL,  ADDRESS  VARCHAR(500));
# 在MyCAT里面向sys_user表添加一条数据:
INSERT INTO SYS_USER(ID,USERNAME,ADDRESS) VALUES(1,"XIAOMING","WUHAN");
#测试主库从库修改对mycat的影响,先修改主库在修改从库,然后正常的时候mycat就会显示两个不同的值,并且创建同步
#添加数据
UPDATE sys_user 
SET address = 'wuhan-m1s1'
WHERE id = 1;
/*+ mycat:refreshMetadata{} */;
刷新结构

MySQL分库分表

3#1. 配置MyCAT数据源
#通过上面的配置,我们准备了两组主从,分别为:
#1)主服务器dw0 从服务器dr0
#2)主服务器dw1 从服务器dr1
#接下来,我们要在MyCAT里面配置这四个数据源。
都在mycat操作
#-- 添加dw0数据源(添加主1)
/*+ mycat:createDataSource
{ "name":"dw0",
  "password":"root123",
  "url":"jdbc:mysql://192.168.8.3:3306?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8", 
  "user":"root",}
*/;

#-- 添加dr0数据源(主1从1)
/*+ mycat:createDataSource
{ "name":"dr0",
  "password":"root123",
  "url":"jdbc:mysql://192.168.8.4:3306?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8", 
  "user":"root",}
*/;

#-- 添加dw1数据源(主2)
/*+ mycat:createDataSource
{ "name":"dw1",
  "password":"root123",
  "url":"jdbc:mysql://192.168.8.5:3306?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8",
  "user":"root",}
*/;

#-- 添加dr1数据源(主2从2)
/*+ mycat:createDataSource
{ "name":"dr1",
  "password":"root123",
  "url":"jdbc:mysql://192.168.8.6:3306?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8",
  "user":"root",}
*/;
# 查看数据源是否成功
/*+ mycat:showDataSources{} */\G;
#随后可在cd /usr/local/mycat/conf/datasources里查看是否创建成功
#2.创两组主从集群配置
#注意:自动分片默认要求集群名字以c为前缀,数字为后缀:
#尽力创c的节点,
#一般情况下我们使用默认的就可以了。
/*! mycat:createCluster{ "name":"c0", "masters":[  "dw0" ], "replicas":[  "dr0" ]} */;
/*! mycat:createCluster{ "name":"c1", "masters":[  "dw1" ], "replicas":[  "dr1" ]} */;
# 查看集群是否成功
/*+ mycat:showClusters{} */\G;
#随后可在cd /usr/local/mycat/conf/clusters里查看是否创建成功
# 3.全局表配置
#同时创建名为db1的数据库
CREATE DATABASE db1 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
#插入db1里面的表
use db1;

CREATE TABLE `sys_dict` ( `id` bigint NOT NULL AUTO_INCREMENT,
                        `dict_type` int ,
                        `dict_name` varchar(100) DEFAULT NULL,
                        `dict_value` int , PRIMARY KEY (`id`)
                        ) ENGINE=InnoDB
                        DEFAULT CHARSET=utf8mb4
                        BROADCAST;
                        
#查看结果随后可在cd /usr/local/mycat/conf/schemas里
# cat db1.schema.json 查看是否创建成功,随后登录查看Navicat Premium 17中是否同时建库(在表的上面)
#插入数据查看结果10.4.4 添加数据查看结果
INSERT INTO sys_dict(dict_type,dict_name,dict_value) VALUES(1,"男",1);
INSERT INTO sys_dict(dict_type,dict_name,dict_value) VALUES(1,"女",0);
# 所有的库中都有的数据
10.4.5 查询数据查看结果
select * from sys_dict;
# 4创建表
CREATE TABLE orders(  ID BIGINT NOT NULL AUTO_INCREMENT,
               ORDER_TYPE INT,  CUSTOMER_ID INT,
               AMOUNT DECIMAL(10,2),  PRIMARY KEY(ID)
               ) ENGINE=INNODB  DEFAULT CHARSET=utf8mb4
               dbpartition BY mod_hash(CUSTOMER_ID)
               dbpartitions 2
               tbpartition By mod_hash(CUSTOMER_ID)
               tbpartitions 1;
#查看结果随后可在cd /usr/local/mycat/conf/schemas里
# cat db1.schema.json 查看是否创建成功(在大概中间为位置)     #插入数据   
INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(1,101,100,100101);
INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(2,101,100,100101);
INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(3,101,100,100101);
INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(4,102,101,101102);
INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(5,102,101,101102);
INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(6,102,101,101102);
# 查询Navicat Premium 17是否每个库都新增,并且不在一个库里
#下属同理
# 创建表
CREATE TABLE orders_detail( id BIGINT AUTO_INCREMENT,
                    detail VARCHAR(2000),
                    order_id BIGINT, PRIMARY KEY(ID)
                    ) ENGINE=INNODB  DEFAULT CHARSET=utf8mb4
                    dbpartition BY mod_hash(order_id)
                    tbpartition By mod_hash(order_id)
                    tbpartitions 1
                    dbpartitions 2;
  #查看结果随后可在cd /usr/local/mycat/conf/schemas里
# cat db1.schema.json 查看是否创建成功(在大概最后位置)          #添加数据
INSERT INTO orders_detail VALUES(1,"详情1",1);
INSERT INTO orders_detail VALUES(2,"详情2",2);
INSERT INTO orders_detail VALUES(3,"详情3",3);
INSERT INTO orders_detail VALUES(4,"详情4",4);
INSERT INTO orders_detail VALUES(5,"详情5",5);
INSERT INTO orders_detail VALUES(6,"详情6",6); 
 查询后台物理库
 MyCAT中关联查询
select * from orders o inner join orders_detail od on(o.id=od.order_id)
#over
从你的操作来看,核心矛盾是:MyCat 元数据显示 sys_dict 表存在(show tables 和 DESCRIBE 正常),但实际插入数据时提示表不存在,同时建表时仍有 Access denied 权限错误。这说明 MyCat 元数据与底层物理库状态不一致,底层物理库中可能并未真正创建 sys_dict 表(因权限问题),而 MyCat 缓存了表结构信息。
根本原因:
底层物理库权限不足:c0 和 c1 集群包含的数据源(dw0/dr0/dw1/dr1)对应的 MySQL 中,root@192.168.8.% 用户仍未获得 db1 数据库的操作权限,导致建表命令在底层执行失败。
MyCat 元数据与物理库不同步:虽然之前的建表操作因权限失败,但 MyCat 可能缓存了表结构元数据,导致 show tables 和 DESCRIBE 能看到表,但实际物理库中无此表,插入时自然失败。
解决步骤(按顺序执行):
1. 彻底解决底层数据源的权限问题(关键!)
db1 关联了 c0 和 c1 集群,需在以下所有数据源对应的 MySQL 中执行授权:
集群	数据源	对应物理机 IP	操作
c0	dw0	192.168.8.3	授权 + 创建物理库
c0	dr0	192.168.8.4	授权 + 创建物理库
c1	dw1	192.168.8.5	授权 + 创建物理库
c1	dr1	192.168.8.6	授权 + 创建物理库
以 dw0(192.168.8.3)为例,执行以下命令:
bash
# 登录 192.168.8.3 的 MySQL(物理机直接登录或远程登录)
mysql -uroot -proot123 -h192.168.8.3 -P3306
sql
-- 1. 确保 db1 物理库存在(若不存在则创建)
CREATE DATABASE IF NOT EXISTS db1 DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;

-- 2. 授予 root 用户对 db1 的所有权限(从 192.168.8.% 网段访问)
GRANT ALL PRIVILEGES ON db1.* TO 'root'@'192.168.8.%' WITH GRANT OPTION;

-- 3. 刷新权限
FLUSH PRIVILEGES;

-- 4. 验证权限(应返回 db1.* 的权限记录)
SELECT user, host, db FROM mysql.db WHERE db = 'db1' AND user = 'root';
对 dr0(192.168.8.4)、dw1(192.168.8.5)、dr1(192.168.8.6)重复以上步骤,确保所有关联的物理库都授权成功。
2. 删除 MyCat 中缓存的无效表结构
由于 MyCat 缓存了错误的表元数据,需先删除表再重建:
sql
-- 切换到 db1
use db1;

-- 删除 MyCat 中的 sys_dict 表(即使物理库中不存在,也需清理元数据)
DROP TABLE IF EXISTS sys_dict;
3. 重新创建 sys_dict 表(确保底层执行成功)
sql
use db1;

-- 创建表(若需在 c0 和 c1 所有节点同步,添加 BROADCAST)
CREATE TABLE `sys_dict` ( 
  `id` bigint NOT NULL AUTO_INCREMENT,
  `dict_type` int,
  `dict_name` varchar(100) DEFAULT NULL,
  `dict_value` int, 
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 BROADCAST;
若创建成功,无错误提示;
若仍提示 Access denied,说明步骤 1 中某数据源的权限未配置正确,重新检查对应物理机的授权。
4. 验证物理库中表是否实际存在
登录 c0 和 c1 集群的任意物理库(如 dw0:192.168.8.3),确认表已创建:
bash
mysql -uroot -proot123 -h192.168.8.3 -P3306 db1
sql
-- 查看表是否存在
show tables;  -- 应显示 sys_dict

-- 查看表结构
DESCRIBE sys_dict;
5. 刷新 MyCat 元数据并测试插入
sql
-- 刷新 db1 的元数据,确保与物理库同步
/*+ mycat:refreshMetadata{"schemaName":"db1"} */;

-- 插入数据
INSERT INTO sys_dict(dict_type,dict_name,dict_value) VALUES(1,"男",1);
INSERT INTO sys_dict(dict_type,dict_name,dict_value) VALUES(1,"女",0);

-- 查询验证
SELECT * FROM sys_dict;
关键说明:
MyCat 的元数据(show tables 等)仅反映缓存状态,实际操作以底层物理库为准。权限不足会导致物理库建表失败,即使 MyCat 显示表存在,插入也会失败。
BROADCAST 关键字确保表在 c0 和 c1 集群的所有数据源中同步创建,适合字典表等需要全节点一致的数据。
按照以上步骤,彻底解决底层权限问题后,表会真正创建在物理库中,插入操作即可成功。

MySQL高可用

高可用的 VIP 是为 MySQL 等服务集群提供的固定虚拟网络 IP,通常由 Keepalived 等工具自动管理,主节点故障时会自动漂移到新主节点,确保应用无需改连接地址即可持续访问服务,无需手动频繁操作。

#1.准备四台机器,一台下载高可用master,一台主,两台从
四台都需要操作
# 关闭防火墙
systemctl stop firewalld && systemctl disable firewalld
# 关闭SELinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

# 配置hosts(所有节点一致)
cat >> /etc/hosts << EOF
192.168.8.3 mha-node1
192.168.8.4 mha-node2
192.168.8.8 mha-node3
192.168.8.7 mha-manager
EOF
# 配置SSH免密登录(manager节点需免密登录所有数据库节点,数据库节点间也需互信)所有节点执行
ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa
for host in mha-node1 mha-node2 mha-node3; do
  ssh-copy-id -i ~/.ssh/id_rsa.pub $host
done
#2.搭配环境
一主两从下载mysql环境
编辑vi内容,这步重点,尽量一点不要少也不要多,直接复制
主. 配置MySQL(主从差异化配置)
Master(mha-node1)配置
vim  /etc/my.cnf
[mysqld]
server-id=11  # 唯一ID
log_bin=mysql-bin  # 开启binlog
binlog_format=ROW  # ROW模式(MHA推荐)
gtid_mode=ON  # 开启GTID
enforce_gtid_consistency=ON  # 强制GTID一致性
log_slave_updates=ON  # 从库同步时记录binlog(用于级联复制)
skip_name_resolve=ON  # 跳过域名解析

systemctl restart mysqld 重启

从配置Slave(mha-node2/mha-node3)配置
# mha-node2(server-id=12)
vim  /etc/my.cnf
[mysqld]
server-id=12  # 唯一ID(mha-node3设为13)
log_bin=mysql-bin
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON
skip_name_resolve=ON
relay_log=relay-bin  # 开启中继日志
read_only=ON  # 从库只读(可选)

systemctl restart mysqld 重启
# 3.搭建主从复制(基于GTID)
在Master(mha-node1)也就是主服创建复制用户
CREATE USER 'repl'@'192.168.8.%' IDENTIFIED WITH mysql_native_password BY 'Repl@123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.8.%';
FLUSH PRIVILEGES;
# 在从设置连接
-- 登录Slave的MySQL
CHANGE MASTER TO
  MASTER_HOST='mha-node1',
  MASTER_USER='repl',
  MASTER_PASSWORD='Repl@123',
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION=1;  # 基于GTID自动定位

-- 启动复制
START SLAVE;

-- 检查复制状态(确保Slave_IO_Running和Slave_SQL_Running均为Yes)
SHOW SLAVE STATUS\G;
# 4.挂载光盘后下载东西配置环境,四个机器都设置
vim /etc/yum.repos.d/CentOS-Media.repo
#在中间追加
file:///hao
#然后cd / 进入/
mkdir hao
#mount /dev/sr0  /hao
#随后执行下载
yum install -y wget
# 配置网络Yum源
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# 配置Yum扩展源
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
# 安装Perl依赖(MHA基于Perl开发)
yum install -y perl-DBD-MySQL perl-CPAN perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker
yum install -y perl-Email-Sender perl-Email-Valid perl-Mail-Sender

#下载MHA源码包
# 在教室可以使用局域网下载
# 管理节点下载(只在manage)
wget http://192.168.56.200/Software/mha4mysql-manager-0.58.tar.gz
# 所有节点下载(四个机器,包括manage)
wget http://192.168.56.200/Software/mha4mysql-node-0.58.tar.gz
#安装
tar -zxvf mha4mysql-node-0.58.tar.gz
cd mha4mysql-node-0.58
perl Makefile.PL
make && make install
#manage再次安装
tar -zxvf mha4mysql-manager-0.58.tar.gz
cd mha4mysql-manager-0.58
perl Makefile.PL
make && make install
# manage创建MHA工作目录
mkdir -p /etc/mha/mha_cluster /var/log/mha/mha_cluster
#在manage配置环境
cat > /etc/mha/mha_cluster.cnf << EOF
[server default]
# MHA管理用户(需在所有MySQL节点创建)
user=mha_user
password=Mha@123
# SSH登录用户
ssh_user=root
# MySQL复制用户
repl_user=repl
repl_password=Repl@123
# 健康检查间隔(秒)
ping_interval=1
# master的binlog目录
master_binlog_dir=/usr/local/mysql/data
# 远程节点临时目录
remote_workdir=/tmp
# 二次检查节点
secondary_check_script=masterha_secondary_check -s mha-node2 -s mha-node3
# manager工作目录
manager_workdir=/var/log/mha/mha_cluster
# manager日志
manager_log=/var/log/mha/mha_cluster/manager.log

[server1]
hostname=mha-node1
port=3306
# 不优先作为候选主库
candidate_master=0

[server2]
hostname=mha-node2
port=3306
# 优先作为候选主库(数据最新时)
candidate_master=1
# 忽略复制延迟,强制作为候选
check_repl_delay=0

[server3]
hostname=mha-node3
port=3306
candidate_master=0
EOF
#5在所有地方设置互通账号
CREATE USER 'mha_user'@'192.168.8.%' IDENTIFIED WITH mysql_native_password BY 'Mha@123';
GRANT ALL PRIVILEGES ON *.* TO 'mha_user'@'192.168.8.%';
FLUSH PRIVILEGES;
#注:上述ip根据个人电脑修改
#6,完成后验证
1. 检查SSH连接(manager节点)
masterha_check_ssh --conf=/etc/mha/mha_cluster.cnf
# 输出"All SSH connection tests passed successfully."即为正常
2. 检查主从复制(manager节点)
masterha_check_repl --conf=/etc/mha/mha_cluster.cnf
# 输出"MySQL Replication Health is OK."即为正常
#7.尝试启动
# 前台启动(测试用,日志实时输出)
masterha_manager --conf=/etc/mha/mha_cluster.cnf
(上述操作会在前台一直显示最新日志,需要ctrl+c退出)
# 后台启动(生产用)
nohup masterha_manager --conf=/etc/mha/mha_cluster.cnf > /var/log/mha/mha_cluster/nohup.log 2>&1 &
(常用,后台默认运行)
# 检查MHA状态
masterha_check_status --conf=/etc/mha/mha_cluster.cnf
# 输出"mha_cluster (pid: xxxx) is running(0:PING_OK)"即为正常运行,后面会标着主机name,没有也没事
#8干掉主机,让从机继位
六、测试故障切换
. 模拟Master故障(在mha-node1执行)
systemctl stop mysqld  # 停止主库服务
. 观察故障切换(manager节点日志)
tail -f /var/log/mha/mha_cluster/manager.log
# 正常情况下,日志会显示:
# - 检测到master故障
# - 提升mha-node2为新master
# - 其他slave(mha-node3)指向新master
. 验证切换结果
# 在新master(mha-node2)查看状态
mysql -uroot -p -e "SELECT @@server_id, @@read_only;"
# 应显示server_id=12,read_only=OFF

# 在mha-node3查看复制状态
mysql -uroot -p -e "SHOW SLAVE STATUS\G"
# 应显示Master_Host为mha-node2,且复制正常
#9.恢复
重启主机后设置为新主机的从即可
#10最后一步重启manage
nohup masterha_manager --conf=/etc/mha/mha_cluster.cnf > /var/log/mha/mha_cluster/nohup.log 2>&1 &

manage常见报错

1.   vim里面追加内容,或者使用以前集群的数据的话容易冲突,很容易崩,建议用新的,或者删掉集群追加内容
2   主从复制经常连不上,需要检查授权用户的密码,我的电脑自动给三个电脑了三个密码,后来用重置密码统一后修复
常见于
masterha_check_repl --conf=/etc/mha/mha_cluster.cnf
执行后报错
修改密码代码:
ALTER USER 'repl'@'192.168.8.%' IDENTIFIED WITH mysql_native_password BY 'Repl@123';
查询叫repl名字的代码
SELECT user, host, authentication_string FROM mysql.user WHERE user = 'repl';
3   杀不掉主服的mysql,使用线性删除也不行,直接reboot他,但因为删除一次没成功,manage可能报错,需要刷新manage状态,不然它会显示主机连续崩溃两次是错误情况,不处理,也就是不自动切主机,因 “短时间内多次故障转移保护机制” 而失败。解决需手动删除标记文件后重新执行故障转移。
查看是否杀死进程: ps -ef | grep mysqld | grep -v grep
重置manage代码
rm -f /var/log/mha/mha_cluster/mha_cluster.failover.complete
重新启动 MHA 管理器,触发故障转移:
masterha_manager --conf=/etc/mha/mha_cluster.cnf
#重启mysql 的代码是/etc/init.d/mysqld restart
4. 查看所有用户
masterha_check_repl --conf=/etc/mha/mha_cluster.cnf

MySAL

搭建主从服务器

# 1.服务器的准备

服务器IP           角色        主机名
192.168.25.22   Master1(主)  zhu_fwq
192.168.25.23   Slave1(从)   con_fwq
--------------------------------------------------------
#2.给两台服务器都安装相同版本的MySQL数据库(mysql8.0.20)

#下载MySQL安装脚本
wget 192.168.56.200/Software/mysql_install.sh

# 执行MySQL安装脚本
bash mysql_install.sh

#安装好后重新加载
source //etc/profile
bash
-------------------------------------------------------
#3.修改主服务器的配置文件 /etc/my.cnf
vim /etc/my.cnf

[mysqld]
... # 省略
# 主从复制-主机配置
# 主服务器唯一ID
server-id=1
# 启用二进制日志
log-bin=mysql-bin
# 设置不要复制的数据库(可设置多个)
binlog-ignore-db=sys
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
binlog-ignore-db=performance_schema
# 设置需要复制的数据库(可设置多个)
# binlog-do-db=test
# 设置logbin格式
binlog_format=ROW

#STATEMENT格式记录执行的SQL语句,而不是记录实际数据行的更改。
#ROW格式记录了对数据行的更改。
#MIXED格式则是根据操作的类型(语句或行)来灵活选择。
--------------------------------------------------------
#4.修改从服务器的配置文件 /etc/my.cnf
vi /etc/my.cnf

[mysqld]
...
# 在之前配置下方编写
# 主从复制-从机配置
# 从服务器唯一ID
server-id=2
# 启用中继日志
relay-log=mysql-relay
--------------------------------------------------------
#5.分别重启两台服务器上的MySQL
/etc/init.d/mysqld restart
--------------------------------------------------------
#6.关闭主从数据库服务器防火墙或开放3306端口

# 查看防火墙状态
systemctl status firewalld
# 关闭防火墙
systemctl stop firewalld
--------------------------------------------------------
#7.主数据库创建用户slave 并授权
# 在主数据库端(192.168.25.22)

# 登录mysql -uroot -p
# 创建用户
create user 'slave'@'%' identified with mysql_native_password by 'root123';

# 授权
grant replication slave on *.* to 'slave'@'%';

# 刷新权限
flush privileges;
--------------------------------------------------------
#8.从数据库端验证主数据库slave用户是否可用
# 在从数据库端(192.168.25.23)

# 验证主数据库slave用户是否可用
mysql -uslave -p -h192.168.8.100 -P3306
#验证成功后退出
--------------------------------------------------------
#9.配置主从节点信息
# 在主数据库端(192.168.25.22)
# 查询服务ID及Master状态

# 登录
mysql -uroot -p

# 查询server_id是否可配置文件中一致
show variables like 'server_id';
# 若不一致,可设置临时ID(重启失效)
set global server_id = 100;

# 查询Master状态,并记录 File(对应下一步中的master_log_file)
# Position (对应下一步中的master_log_pos)的值
show master status\G;
#输出
             File: mysql-bin.000001
         Position: 828
     Binlog_Do_DB: 
 Binlog_Ignore_DB: sys,mysql,information_schema,performance_schema
Executed_Gtid_Set: 
# 注意:执行完此步骤后退出主数据库
# 防止再次操作导致 File 和 Position 的值发生变化
--------------------------------------------------------
#10.在从数据库端设置同步
# 在从数据库端(192.168.25.23)

# 登录
mysql -uroot -p
# 查询server_id是否可配置文件中一致
show variables like 'server_id';
# 若不一致,可设置临时ID(重启失效)
set global server_id = 101;

# 设置主数据库参数(用上一步创建的slave用户及密码)
change master to 
master_host='192.168.8.100',
master_port=3306,
master_user='slave',
master_password='root123',
master_log_file='mysql-bin.000001',
master_log_pos=828;

# 开始同步
start slave;

# 查询Slave状态
show slave status\G;
# 查看是否配置成功
# 查看参数 Slave_IO_Running 和 Slave_SQL_Running 是否都为yes,则证明配置成功。若为no,则需要查看对应的 Last_IO_Error 或 Last_SQL_Error 的异常值

# 若出现错误,则停止同步,重置后再次启动
#停止
stop slave;
#重置
reset slave;
#启动
start slave;
--------------------------------------------------------
#11.测试主从复制,主服务上执行
# 在主数据库端(192.168.25.22)
mysql -uroot -p
# 创建test库,t1表,添加测试数据
create database test;
use test;
create table t1(id int,name varchar(30));
insert into t1(id,name) values(1,"aaa");
--------------------------------------------------------
#12.测试主从复制,从服务器上执行
# 在从数据库端(192.168.25.23)
mysql -uroot -p
# 查看是否同步数据
show databases;
use test;
show tables;
select * from t1;

如果主从不同步,怎么解决

从不同的原因分析:

  1. 问题:主服务器二进制日志异常

    解决办法:需要检查主库的二进制日志是否正常。可以通过查看主库的错误日志、binlog文件的状态以及复制进程的状态来判断。如果发现异常,可以尝试重启主库的复制进程或者重新生成二进制日志。

  2. 问题:主从库的配置不一致也是主从不同步的一个常见原因。比如主库的字符集设置为utf8,而从库的字符集设置为latin1,就会导致数据在复制过程中出现乱码或者丢失的情况。

    解决办法:如果主从库的配置不一致,可以通过修改从库的配置文件来保持一致。比如,将从库的字符集设置与主库一致,确保数据在复制过程中不会出现乱码或者丢失。

  3. 问题:初始数据不一至时,主服务器上修改了从服务器上没有的内容后,导致主从不同步

    解决办法:直接忽略报错:在从服务器上修改配置文件,添加 slave_skip_errors=ALL 【跳过所有报错】,然后重启MySQL服务 ,在查看状态

集群

使用多台服务器实现相同的功能,通过网络进行连接。
分类:

  • 负载均衡集群
  • 高可用集群(主备集群)
  • 读写分离集群

分布式

  • 单体架构:所有应用\功能\运算\存储等都在一台服务中.
    • 开发,简单测试,个人网站(应用),小公司.
    • 搭建简单,成本低
    • 抗并发能力低,没有备份
  • 分布式架构:将服务,应用,运算,存储"拆分"到不同服务器上实现.
    • 适合复杂的服务,应用.
    • 横向扩展(增加服务器(节点)数量,来提升整体的性能.)
    • 分布式存储服务器:网络版的RAID10
    • 分布式缓存,分布式运算

九 MySQL读写分离

  • 中间件:在客户端与服务端之间的服务,用于实现一些特定的功能,安全认证中间件,读写分离中间件,反向代理,等功能.

十.MySQL分库分表与MyCAT

分库分表

分库:拆分数据库,当单台数据库服务存储容量不足时,或者并发量过高,单机资源不足.

分表:拆分数据表,当单表数据量过大时,索引(B+树)查询效率会变低,2千万数据左右.

方法:

垂直分库:将原本一个库中的表分到不同的库

垂直分表:将原来的表,按字段拆分成多个表.

水平分库:按照数据内容拆分,例如按年月拆分数据,数据范围拆分,模运算

水平分表:也是按照内容拆分表

使用MyCAT分布式集群中间件,可以实现分库,分表,读写分离,负载均衡,故障(屏蔽)转移.

MyCAT支持MySAL网络协议,可以使用mysql的客户端进行操作.

使用java语言开发,安装java运行环境(jdk)

  • ini:xx.ini/xx.conf/xx.cnf/xx.repo
[mysqld]
base_dir = /usrl/local/mysql
date_dir = /usr/local/mysql/data
...
  • xml:标签语言,java 项目、大数据、
- <user>
  <id>1001</id>
  <name>John Doe</name>
  <age>30</age>


  • JSON:JavaScript 对象表示法。API 接口数据交换、配置文件、存储简单结构化数据等。
    • Apache,TomCat
{
"user": {
"id": 1001,
"name": "John Doe",
"age": 30,
"hobbies": ["reading", "sports"]
}
}
  • yaml:采用缩进表示层级关系,语法简洁,可读性强,支持复杂数据结构,如列表、字典等。
    • Docker,K8S
user:
  id: 1001
  name: John Doe
  age: 30
  hobbies:
    - reading
    - sports

概念

数据源:MyCAT用于连接后端的MySQL数据库

  • 用户名,密码,IP

MyCAT集群设置:对后端MySAL进行组合设置,例如主,从,只读,读写,分库,分表

  • clusters:设置集群
mycat 注释指令:
清空所有配置
/*+ mycat:resetConfig{} */;
创建mycat用户
/*+ mycat:createUser{
"username":"user",
"password":"1",
"ip":"127.0.0.1",
"transactionType":"xa"}
*/

附加内容

# 查看插入后的名单(名单名为user)
SELECT * FROM user;
 
# 这条语句的完整含义是:向 user 表中插入一行数据,其中 id 为 1、name 为 “武大郎”、gender 为 “男”、password 为 “123321”、phone 为空值。
INSERT INTO user(id,name,gender,password,phone) 
VALUE(1,'武大郎','男','123321',NULL);


## 查看数据  DQL(数据查询语言)
select * from user; -- 查看所有数据
select name,gender from user;
#注意:user为我自己的表格名,name和gender为表格的选项,名字和性别。其他不改结尾要有;两个字段中间要有逗号
执行前要先选择数据库,我的为USE test; (
#use为固定,test为我的数据库名


#修改语句,修改语句必须要加where条件,否则会更新所有行的数据。
update user set phone='1999' where id=1;
修改 user表中 id 为 1 的那一行数据,将其 phone字段的值更新为 '1999'。
## 删除数据必须要加where条件,否则会删除所有行的数据。
delete from user where id=6;
从 user 表中删除 id 为 6 的那一行数据。
#检查是否开启安全模式
show variables like 'sql_safe_updates';

#开启安全模式
set sql_safe_updates = 1;
#关闭安全模式
set sql_safe_updates = 0;

# 自动启动安全模式
vim /etc/my.cnf
# 在[mysqld]下配置一个
init-file=/usr/local/mysql/init-file.sql

vim /usr/local/mysql/init-file.sql
# 在sql脚本文件中添加下列语句
set global sql_safe_updates=1;

# 重启MySQL服务
systemctl restart mysqld

# 开启安全模式后的限制有哪些
1. update语句必须满足如下条件之一才能执行成功
1)使用where子句,并且where子句中列必须为索引列
2)使用limit
3)同时使用where子句和limit(此时where子句中列可以不是索引列)

2. delete语句必须满足如下条件之一才能执行成功
1)使用where子句,并且where子句中列必须为索引列
2)同时使用where子句和limit(此时where子句中列可以不是索引列)

#例子
LIMIT作用
-- 只返回前 5 条数据
SELECT * FROM user LIMIT 5;

-- 从第 3 条开始(偏移 2),返回 5 条(常用于分页)
SELECT * FROM user LIMIT 2, 5; 偏移2,一共返回五条


UPDATE user SET id=2 WHERE name='潘金莲'LIMIT 1;
# 把潘金莲那行的id改成2,最多只更新一行其他不变,更新最先检测到的

了解:聚合函数,分组查询,升序、降序,分页查询,子查询

下面为你详细介绍 SQL 中聚合函数、分组查询、排序(升序、降序)、分页查询和子查询的相关知识:

1. 聚合函数

聚合函数用于对一组数据进行计算并返回单个结果值,常用于统计分析。

常见的聚合函数:

  • count`:计算记录的数量

    -- 计算表中所有记录数
    SELECT COUNT(*) FROM students;
    -- 计算指定列非NULL值的数量
    SELECT COUNT(age) FROM students;
    
  • SUM():计算数值列的总和

    萨姆

    -- 计算所有学生的总分
    SELECT SUM(score) FROM exam_results;
    
  • AVG():计算数值列的平均值

    安格

    -- 计算学生的平均年龄
    SELECT AVG(age) FROM students;
    
  • MAX():获取指定列的最大值

    -- 获取最高分数
    SELECT MAX(score) FROM exam_results;
    
  • MIN():获取指定列的最小值

    -- 获取最低分数
    SELECT MIN(score) FROM exam_results;
    

2. 分组查询

分组查询使用GROUP BY子句,将表中的数据按照指定列的值进行分组,然后对每个分组应用聚合函数。

基本语法:

SELECT 列1, 聚合函数(列2)
FROM 表名
GROUP BY 列1;

示例:

-- 按班级分组,计算每个班级的学生人数和平均年龄
SELECT class, COUNT(*), AVG(age)
FROM students
GROUP BY class;

-- 结合HAVING筛选分组结果(HAVING用于筛选分组,WHERE用于筛选行)
-- 筛选出学生人数大于30的班级
SELECT class, 
COUNT(*) AS student_count
FROM students
GROUP BY class
HAVING COUNT(*) > 30;

-- 筛选出学生人数大于30的班级
SELECT 
    class_name AS 班级,#起名班级
    COUNT(*) AS 学生人数  #起名学生人数
FROM class_students  #总表名
GROUP BY class_name   #人数列名
HAVING COUNT(*) > 30;

    SELECT
含义:"选择",用于指定要查询并返回的列或计算结果。
class_name
含义:表中的 "班级名称" 字段,代表要查询的具体列。
AS 班级
AS:"作为",用于给查询结果的列起别名
班级:为class_name字段起的别名,使结果更易读
COUNT(*)
COUNT:聚合函数,"计数"
(*):表示统计所有行(记录)的数量,不忽略 NULL 值
AS 学生人数
为COUNT(*)的计算结果起别名 "学生人数"
FROM class_students
FROM:"从... 中",指定查询的数据来源表
class_students:具体的表名,即要查询的表
GROUP BY class_name
GROUP BY:"按... 分组",用于将数据按指定列的值分组
class_name:按 "班级名称" 进行分组,相同班级的记录会被归为一组
HAVING COUNT(*) > 30
HAVING:"具有",用于筛选分组后的结果(与WHERE不同,WHERE筛选原始数据)
COUNT(*) > 30:筛选条件,只保留 "学生人数大于 30" 的分组(班级)

-- 统计每个班级的人数并按人数排序(从多到少)
SELECT 
    class_name AS '班级',#class是列,比如name,id列,这里表示按班级分组,一样的为一组
    COUNT(*) AS '人数'  #统计每个分组(班级)的学生总数,并命名为 "人数"
FROM class_students #这个是表名
GROUP BY class_name #还是列
ORDER BY 人数 DESC; #ORDER BY 人数 DESC:将结果按人数从多到少排序,方便直观对比
    

3. 排序(升序、降序)

使用ORDER BY子句对查询结果进行排序,默认是升序。

  • 升序(ASC):从小到大排序(可省略不写)
  • 降序(DESC):从大到小排序

示例:

-- 按年龄升序排列学生( youngest to oldest)
SELECT student_name, score FROM class_students ORDER BY score ASC;
选择,name和score两列,然后根据score进行asc,选用class_students表
-- 按分数降序排列考试结果( highest to lowest)
SELECT student_name, score FROM class_students ORDER BY score DESC;

-- 多列排序:先按班级升序,再按年龄降序
SELECT student_name, class_name, age FROM class_students ORDER BY class_name ASC, age DESC;
选择student_name, class_name, age 三列,选择class_students 表,然后class_name 升序ASC, age 降序DESC;

4. 分页查询

分页查询用于限制返回结果的数量,通常用于在网页上分页显示数据。不同数据库语法略有差异:

  • MySQL 使用LIMIT

    -- 从第0条记录开始,获取10条记录(第一页)
    SELECT * FROM class_students LIMIT 0, 10;
                                 厘米特
    前面的数字是多少就是跳过多少行
    -- 从第10条记录开始,获取10条记录(第二页)
    SELECT * FROM class_students LIMIT 10, 10;
    

5. 子查询

子查询是嵌套在其他 SQL 语句中的查询,也称为内部查询,而包含子查询的查询称为外部查询。

子查询可以用于SELECTFROMWHERE等子句中。

  • 在 WHERE 子句中使用子查询:

    -- 查找分数高于平均分的学生
    SELECT class_name, score
    FROM class_students
    WHERE score > (SELECT AVG(score) FROM class_students);
    
  • 在 FROM 子句中使用子查询(作为临时表):

    -- 查找每个班级分数最高的学生信息
    SELECT s.name, s.class, s.score
    FROM exam_results s
    INNER JOIN (
        SELECT class, MAX(score) AS max_score
        FROM exam_results
        GROUP BY class
    ) AS sub ON s.class = sub.class AND s.score = sub.max_score;
    
    SELECT class_name, score, student_name
    FROM class_students s
    WHERE score = (
        SELECT MAX(score)
        FROM class_students
        WHERE class_name = s.class_name
    );
    
    
  • 在 SELECT 子句中使用子查询:

    -- 查询每个学生的姓名及其所在班级的平均年龄
    SELECT class_name, 
           (SELECT AVG(age) FROM class_students s2 WHERE s2.class = s1.class) AS class_avg_age
    FROM class_students s1;
    
    -- 修正字段名并优化:查询每个学生的姓名及其所在班级的平均年龄
    SELECT 
        student_name,  -- 学生姓名
        class_name,    -- 班级名称
        -- 子查询:计算当前学生所在班级的平均年龄
        (SELECT AVG(age) 
         FROM class_students s2 
         WHERE s2.class_name = s1.class_name  -- 关联条件:同一个班级
        ) AS class_avg_age  -- 别名:班级平均年龄
    FROM class_students s1;  -- 主表别名s1
        
    

这些是 SQL 查询中非常基础且常用的操作,掌握它们可以帮助你完成大部分数据查询和分析任务。在实际应用中,这些操作经常会结合使用,以实现更复杂的查询需求。

多表连接查询是 SQL 中用于从多个相关表中获取数据的核心操作,通过表之间的关联字段(通常是主键和外键)将数据连接起来。常见的连接类型及用法如下:

1. 内连接(INNER JOIN)

从三个表中分别提取需要的数据,并通过关联条件组合起来

作用:只返回两个表中匹配关联条件的记录(交集)。
语法

SELECT 表1.字段, 表2.字段
FROM 表1
INNER JOIN 表2 
ON 表1.关联字段 = 表2.关联字段;

示例:查询学生及其所在班级的信息(学生表 students 和班级表 classes 通过 class_id 关联):

SELECT students.name, classes.class_name
FROM students
INNER JOIN classes 
ON students.class_id = classes.id;

2. 左连接(LEFT JOIN / LEFT OUTER JOIN)

  • 左侧表(LEFT JOIN 左边的表)的所有记录都会被保留,无论是否能在右侧表中找到匹配的数据。
  • 右侧表如果没有匹配的记录,对应的字段值就会用 NULL 填充。

作用:返回左表(FROM 后的表)所有记录,以及右表中匹配关联条件的记录;右表无匹配时显示 NULL
语法

SELECT 表1.字段, 表2.字段
FROM 表1
LEFT JOIN 表2 
ON 表1.关联字段 = 表2.关联字段;

示例:查询所有学生(包括未分配班级的)及其班级信息:

SELECT students.name, classes.class_name
FROM students
LEFT JOIN classes 
ON students.class_id = classes.id;

3. 右连接(RIGHT JOIN / RIGHT OUTER JOIN)

作用:与左连接相反,返回右表所有记录,以及左表中匹配关联条件的记录;左表无匹配时显示 NULL
语法

SELECT 表1.字段, 表2.字段
FROM 表1
RIGHT JOIN 表2 
ON 表1.关联字段 = 表2.关联字段;

示例:查询所有班级(包括没有学生的)及班级中的学生:

SELECT classes.class_name, students.name
FROM students
RIGHT JOIN classes 
ON students.class_id = classes.id;

4. 全连接(FULL JOIN / FULL OUTER JOIN)

全连接(FULL JOIN 或 FULL OUTER JOIN) 的逻辑是:
左右两侧表的所有记录都会被保留,无论是否能在对方表中找到匹配的数据。

作用:返回左表和右表的所有记录,匹配的记录合并,不匹配的部分显示 NULL
注意:MySQL 不直接支持 FULL JOIN,可通过 UNION 组合左连接和右连接实现。
语法(支持的数据库如 SQL Server)

SELECT 表1.字段, 表2.字段
FROM 表1
FULL JOIN 表2 
ON 表1.关联字段 = 表2.关联字段;

5. 交叉连接(CROSS JOIN)

交叉连接(CROSS JOIN) 是 SQL 中一种特殊的连接方式,它的核心逻辑是:将左表的每一行与右表的每一行进行组合,生成两表所有可能的 “行对”,即数学中的 “笛卡尔积”(Cartesian product)。


特点与逻辑

  • 不需要指定连接条件(ON 子句),因为它会强制匹配所有行。
  • 结果集的行数 = 左表行数 × 右表行数。
  • 无论两表是否有关联,都会生成所有可能的组合。

示例

作用:返回两个表的笛卡尔积(左表每条记录与右表所有记录组合),慎用(数据量可能极大)。
语法

SELECT 表1.字段, 表2.字段
FROM 表1
CROSS JOIN 表2;

关键注意事项:

  • 关联条件:必须通过 ON 指定连接条件(避免笛卡尔积),多表连接时可连续使用 JOIN
  • 表别名:使用 AS 简化表名,例如 students AS s 可简写为 s
  • 优先级JOIN 优先级高于 WHERE,建议先连接再过滤(用 WHEREON 补充条件)。

通过多表连接,可以灵活组合不同表的数据,满足复杂查询需求(如 “查询某课程的学生成绩及对应教师信息” 等)。

这段内容是 MySQL 数据库的查询语句及执行结果,以下是拆解解析:

1. SQL 查询语句

SELECT u2.username, u2.city
FROM users u1
JOIN users u2 ON u1.city = u2.city
WHERE u1.username = '张三' AND u2.username != '张三';
  • 作用:从 users 表中,查询与 “张三”同城市,但不是张三本人的用户信息(姓名、城市)。

  • 语法拆解

    • SELECT u2.username, u2.city:指定要查询的字段(u2 表的 usernamecity)。
    • FROM users u1:从 users 表取数据,给表起别名 u1(方便后续关联)。
    • JOIN users u2 ON u1.city = u2.city自连接(同一张表 users 自己关联自己),条件是 u1u2city 字段值相同(即 “同城市”)。
    • WHERE u1.username = '张三' AND u2.username != '张三':筛选条件,u1 是 “张三”,且 u2 不是 “张三”(避免查自己)。

2. 执行结果

+----------+--------+
| username | city   |
+----------+--------+
| 赵六     | 北京   |
+----------+--------+
1 row in set (0.00 sec)
  • 含义

    :查询结果返回 1 条数据,说明:

    • 表中 “张三” 所在城市是 北京
    • 同在北京、且不是 “张三” 的用户是 赵六

在 MySQL 中,除了DATE(日期类型)、INT(整数类型)外,还有很多其他数据类型,以下是常见的数据类型及其说明:

表格标题选择的数值类型

  • TINYINT:极小整数类型,占用 1 个字节存储空间。有符号的范围是 -128 到 127,无符号的范围是 0 到 255。常用于存储取值范围较小的整数,比如年龄等级(1 - 5 级)等。
  • SMALLINT:小整数类型,占用 2 个字节。有符号范围是 -32768 到 32767,无符号范围是 0 到 65535。可用于存储人数、简单计数等。
  • MEDIUMINT:中等大小整数类型,占用 3 个字节。有符号范围是 -8388608 到 8388607,无符号范围是 0 到 16777215 。
  • BIGINT:大整数类型,占用 8 个字节,有符号范围非常大,适用于存储极大的数值,像自增 ID 在预计数据量特别大时可以使用此类型。
  • FLOAT:单精度浮点数类型,占用 4 个字节,用于存储带有小数部分的数值,但存在一定精度损失,如存储3.1415926可能会有细微偏差。
  • DOUBLE:双精度浮点数类型,占用 8 个字节,精度比FLOAT更高,但同样存在精度问题,适用于对精度要求不是极高的科学计算、价格计算等场景。
  • DECIMAL:定点数类型,能精确存储小数,占用字节数根据精度设置而定。常用于存储对精度要求极高的财务数据,如金额等,可指定精度和小数位数,如DECIMAL(10, 2)表示总位数为 10 位,小数部分占 2 位。

日期和时间类型

  • TIME:时间类型,用于存储一天内的时间,格式为HH:MM:SS(时:分: 秒),也可以只存储部分,如HH:MM
  • YEAR:年份类型,占用 1 个字节,可存储范围是 1901 - 2155。
  • DATETIME:日期时间类型,占用 8 个字节,能存储从 1000 - 01 - 01 00:00:00 到 9999 - 12 - 31 23:59:59 的日期和时间信息。
  • TIMESTAMP:时间戳类型,占用 4 个字节,存储范围是1970 - 01 - 01 00:00:01 UTC2038 - 01 - 19 03:14:07 UTC ,会自动根据时区进行调整,常用来记录数据的创建或更新时间。

字符串类型

  • CHAR:固定长度字符串类型,定义时需指定长度,如CHAR(10),无论实际存储的字符串是否达到指定长度,都会占用固定字节数。适合存储长度固定的字符串,如身份证号后 4 位校验码(固定 4 位)等。
  • VARCHAR:可变长度字符串类型,同样要指定最大长度,如VARCHAR(50),实际占用空间为字符串长度加上 1 - 2 个字节的长度标识,更节省存储空间,适用于存储长度不确定的字符串,比如姓名、地址等。
  • TEXT:文本类型,用于存储大量文本数据,如文章内容、备注信息等。根据存储数据量大小,又分为TINYTEXT(最大 255 字节)、TEXT(最大 65535 字节 )、MEDIUMTEXT(最大 16777215 字节 )、LONGTEXT(最大 4294967295 字节 ) 。
  • BINARYVARBINARY:分别是固定长度和可变长度的二进制字符串类型,用于存储二进制数据,如图片、音频等文件的二进制内容(实际应用中更多使用专门的文件存储方式,但理论上可存 )。

其他类型

  • ENUM:枚举类型,定义时需列出所有可能的值,如ENUM('男', '女'),只能从列出的值中选择一个进行存储,节省存储空间,常用于存储取值固定的字段,如性别、订单状态等。
  • SET:集合类型,与ENUM类似,但可以同时存储多个值,如SET('苹果', '香蕉', '橙子'),可以存储一个或多个水果名称 。

NOSQL

# 先停止 Redis
./redis-cli shutdown
# 用配置文件重新启动
./redis-server ../etc/redis.conf
del      删除
get      查看关联
select   切换库
ping     检测联通
set      设置关联声明某个词是某个意思
exists key 检测key在不在,在返回1
expire key 30  给key设置30秒的生存空间
pexpire key 10000   给key设置100毫秒的生存空间

什么是nosql?

NOSQL(Not Only SQL):非关系型数据库;

包括:

  • Redis:基于内存的KV结构的数据
  • MongoDB:文档型数据库,擅长存储JSON(BSON)数据;
  • HBase:列存储数据库,大数据存储;

特点:

  • 存储半结构化,非结构化数据;
  • 海量存储;(通过分布式)
  • 高并发场景;

redis

Redis(Remote Dictionary Server)远程字典服务.

内存型数据库:数据存储到内存中的,读写速度快(GB/s);

支持高并发,查询11万/秒,写入8万/秒.

支持持久化(将数据定期存储到磁盘中);

常用于缓存,热点数据,临时数据;通过加缓存,可以提高并发,减少成本.

Redis常用数据类型

  • 字符串
  • hash
  • 集合
  • 有序集合
  • 列表

你准确列出了 Redis 最核心、最常用的 5 种基础数据类型。在实际开发中,这几种类型覆盖了绝大多数缓存、计数、排序等场景,下面为你详细拆解每种类型的 核心特性、底层结构(简化)、典型使用场景,帮你更深入理解其设计逻辑和应用价值:


1. 字符串(String)

Redis 中最基础、最灵活的数据类型,value 不仅是 “字符串”,还支持整数、浮点数(本质是二进制安全的字节流,最大容量 512MB)。

核心特性

  • 单键单值,支持直接赋值、修改、拼接、截取等操作;
  • 对整数 / 浮点数支持原子性自增(INCR)、自减(DECR)、增减指定值(INCRBY/DECRBY);
  • 支持 SETNX(仅当键不存在时赋值,常用于分布式锁)、SETEX(赋值时指定过期时间,常用于临时缓存)。

典型场景

  • 缓存单个值:如用户信息(JSON 字符串)、商品详情、接口返回结果;
  • 计数器:文章阅读量、视频播放量、接口调用次数(依赖 INCR 原子性,避免并发问题);
  • 分布式锁基础:用 SETNX key value EX 10 NX 实现简单分布式锁(避免重复执行任务);
  • 临时标识:验证码(如短信验证码,SETEX 设置 5 分钟过期)、登录 token 临时存储。

2. 哈希(Hash)

类似 Java 中的 HashMap键(key)对应一个 “哈希表”,哈希表内包含多个 “字段(field)- 值(value)” 对,适合存储 “结构化数据”。

核心特性

  • 可直接操作哈希表中的单个字段(如新增 HSET、查询 HGET、删除 HDEL),无需修改整个哈希表;
  • 支持批量操作(HMSET 批量设字段、HMGET 批量查字段、HGETALL 查所有字段和值);
  • 支持判断字段是否存在(HEXISTS)、统计字段数量(HLEN)。

典型场景

  • 存储结构化对象:如用户信息(user:1001 为 key,name/age/phone 为 field,对应值为具体内容),相比 String 存储 JSON,Hash 可单独更新某个字段(如只改 age,无需重新存储整个用户 JSON);
  • 购物车:用户 ID 为 key,商品 ID 为 field,商品数量为 value(HINCRBY 可原子性修改数量,HDEL 移除商品)。

3. 列表(List)

有序、可重复的元素集合,底层基于 “双向链表”(小数据量)或 “压缩列表”(大数据量)实现,支持从两端操作元素,性能高效。

核心特性

  • 两端操作:从左侧插入(LPUSH)、左侧弹出(LPOP)、右侧插入(RPUSH)、右侧弹出(RPOP),时间复杂度均为 O (1);
  • 支持按索引查询 / 修改元素(LINDEX/LSET)、按范围获取元素(LRANGE,如获取前 10 个元素);
  • 支持 “阻塞弹出”(BLPOP/BRPOP,当列表为空时,客户端会阻塞等待,直到有元素插入,常用于消息队列)。

典型场景

  • 消息队列(简单版):生产者用 RPUSH 往列表尾部塞消息,消费者用 BLPOP 从头部取消息,避免轮询开销;
  • 排行榜(最新列表):如 “最新文章列表”,新文章用 LPUSH 插入头部,LRANGE 0 9 获取最新 10 篇;
  • 历史记录:如用户最近浏览的商品、最近操作日志,用 LPUSH 新增,LTRIM 限制列表长度(避免内存膨胀)。

4. 集合(Set)

无序、不可重复的元素集合,底层基于 “哈希表” 实现,支持高效的 “交集、并集、差集” 运算。

核心特性

  • 元素唯一:插入重复元素会自动去重(SADD 命令返回 0 表示元素已存在);
  • 集合运算:交集(SINTER,如两个用户的共同好友)、并集(SUNION,如合并两个标签的内容)、差集(SDIFF,如用户 A 有但用户 B 没有的好友);
  • 支持随机操作:随机取 N 个元素(SRANDMEMBER)、随机删除 1 个元素(SPOP,常用于 “抽奖” 场景)。

典型场景

  • 去重场景:如用户标签(一个用户的 “喜欢” 标签不重复,SADD 自动去重)、UV 统计(存储访问用户 ID,SCARD 统计数量);
  • 关系计算:如社交场景的 “共同好友”(SINTER user:A:friends user:B:friends)、“推荐好友”(SDIFF user:B:friends user:A:friends 得到 A 可能认识的人);
  • 随机场景:如抽奖(SPOP 随机抽 1 个中奖用户)、随机推荐(如随机推荐 3 个热门商品,SRANDMEMBER goods:hot 3)。

5. 有序集合(Sorted Set / ZSet)

在 “集合(Set)” 的基础上,为每个元素增加了一个 “分数(score)”,元素按分数从小到大自动排序,底层基于 “跳表”(Skip List)实现,兼顾排序和查询性能。

核心特性

  • 有序且唯一:元素不可重复,但分数可重复;排序依据分数,分数相同则按元素字典序排序;
  • 分数操作:新增元素时指定分数(ZADD)、修改元素分数(ZINCRBY,如给用户积分加 10);
  • 范围查询:按分数范围获取元素(ZRANGEBYSCORE,如获取积分 100-200 的用户)、按排名范围获取元素(ZRANGE,如获取排名前 10 的用户);
  • 排名查询:获取元素的排名(ZRANK,从 0 开始)、获取元素的分数(ZSCORE)。

典型场景

  • 排行榜(有序):如游戏战力榜(ZADD rank:game 5000 user:101ZRANGE rank:game 0 9 WITHSCORES 显示前 10 战力及分数)、商品销量榜;
  • 带权重的消息队列:如优先级任务(分数为优先级,ZRANGEBYSCORE task:queue 10 10 获取最高优先级任务);
  • 范围统计:如用户积分等级(ZRANGEBYSCORE user:score 0 99 为青铜用户,100 199 为白银用户)。

补充:各类型核心区别与选择建议

数据类型 核心特点 关键操作 适合场景
String 单键单值,灵活 SET/GET、INCR、SETEX 缓存单个值、计数器、分布式锁
Hash 单键多字段,结构化 HSET/HGET、HMGET、HGETALL 存储对象、购物车
List 有序可重复,两端操作快 LPUSH/RPOP、BLPOP、LRANGE 消息队列、最新列表、历史记录
Set 无序不可重复,支持集合运算 SADD、SINTER、SPOP、SCARD 去重、关系计算、随机场景
ZSet 有序不可重复,带分数 ZADD、ZRANGE、ZINCRBY、ZSCORE 排行榜、范围统计、权重队列

掌握这 5 种类型的特性和场景,就能应对 Redis 80% 以上的日常开发需求;若有更复杂的场景(如地理信息、位图等),可进一步学习 Redis 的扩展数据类型(GeoHash、BitMap、HyperLogLog 等)。

缓存失败问题

  • 缓存击穿:一个热点的key失效,直接访问到数据库,导致数据访问量激增.

    • 加锁,从数据库中读取数据写入缓存后,返回给用户;
    • 通过异步的方式不断的刷新过期时间;
  • 缓存穿透:

  • 大量用户访问不存在的数据,导致请求直接访问数据库,占用数据库大量的资源;
    缓存空值 / 默认值
    布隆过滤器做一层过滤

  • 缓存雪崩:最严重的缓存问题,缓存自身崩溃或者有大量的key都过期,后端数据库压力剧增,或直接崩溃.

    • 缓存增加备份,高可用;
    • 缓存集群;
    • 过期时间设置均匀一些;
    • 多级缓存;

Redis基础配置

Redis基础命令

Redis数据类型

redis数据持久化

数据持久化:将内存中的数据保存到磁盘中.

作用:让redis服务重启后可以恢复之前的数据.

  • Redis数据持久化的方式:
    • RDB(快照):将内存中redis缓存的所有数据,都以二进制字符串的方式保存为一个.rdb文件.特点:占用存储少,当恢复所有数据时速度快.不建议频繁拍快照.每次重启自动加载快照.
    • AOF(追加日志):将每次增,删,改的操作添加到.aof日志中.默认明文存储(可压缩),占据更大的存储空间.保存数据时,运行资源占用少.追加日志可以实时添加.

redis集群

  • redis主从模式:一主一从或一主多从,自带读写分离,负载均衡.
  • redis哨兵模式:高可用,主服务器宕机,从服务变为主服务器.
  • redis集群模式(分片):将数据拆分存储到多个Redis主从集群中.从而实现高扩展;

Redis主从模式

原理:第一次同步时,使用RDB(快照),在同步时,主服务器产生的数据,会记录偏移量,在同步完成后,进行偏移量的同步.

之后同步的数据是通过AOF日志方式同步的.

  • 当 slave 启动后,主动向 master 发送 SYNC(同步)命令;
  • master 接受到 SYNC 命令后在后台保存快照(RDB 持久化)和缓存保存快照这段时间的命令;
  • 然后将保存的快照文件和缓存的命令发送给 slave;
  • slave 收到快照文件和命令后加载快照文件和缓存的执行命令。
  • 复制初始化后,master 每次收到的写命令都会同步发送给 slave,保证主从数据一致性。

缺点:只有主服务器能写入数据,从服务器只能读,主服务器一旦宕机,导致无法写入数据.

 # 只需要在从节点添加配置
 vim /etc/redis/redis.conf
 # 最后一行添加
replicaof 192.168.8.3 6379
分别启动三台主机的redis服务器端服务
./bin/redis-server ./etc/redis.conf
 ps -ef|grep redis
 或
 # 启动命令(同样配置文件路径同上)
/usr/local/redis/bin/redis-server /etc/redis/redis.conf

# 直接指定完整路径执行客户端
/usr/local/redis/bin/redis-cli
或
./bin/redis-cli
127.0.0.1:6379> ping
# 若返回 "PONG",则服务完全正常
info replication 
#会显示主从信息
ps -ef | grep redis  
查看线程,有时候无法重启,就查询出来kill停止他,在执行重启
# 1. 进入 Redis 可执行文件目录(必须先执行这步!)
cd /usr/local/redis/bin

# 2. 用 redis-sentinel 软链接启动(指定配置文件,二选一)
# 若用 /etc/redis/sentinel.conf 配置:
./redis-sentinel /etc/redis/sentinel.conf

# 或用 /usr/local/redis/etc/sentinel.conf 配置:
./redis-sentinel /usr/local/redis/etc/sentinel.conf

# 3. 若软链接有问题,用 redis-server --sentinel 启动(效果完全相同)
# 示例:
./redis-server /etc/redis/sentinel.conf --sentinel
scp /usr/local/redis/sentinel.conf 192.168.8.3:/usr/local/redis/
 scp /usr/local/redis/sentinel.conf 192.168.8.4:/usr/local/redis/

哨兵模式

  • 1.监控所有redis服务器,重点监控主服务器,1秒ping一次主.

  • 2.主服务器宕机主观下线,十秒后未回复,客观下线,选举新的主服务器,根据条件(数据完整性,服务器性能);

  • 3.通知其他从服务器,主从变更,让其他从服务器连接新的主服务.

  • scp /usr/local/redis/sentinel.conf 192.168.8.3:/usr/local/redis/
     scp /usr/local/redis/sentinel.conf 192.168.8.4:/usr/local/redis/
    
cp  /usr/local/src/redis-6.2.14/sentinel.conf  /usr/local/redis/etc/sentinel.conf
# 复制备份
 cd  /usr/local/redis/etc/
 #进入文档
vim sentinel.conf
#修改配置
sentinel monitor mymaster 192.168.8.3 6379 1
#重启
 ./bin/redis-sentinel ./etc/sentinel.conf
#杀死从机进程,30秒后观察哨兵日志
 ps -ef|grep redis
 kill -s 9 22163  (通过上述代码查询到进程)
#启动1从机,观察哨兵日志
 ./bin/redis-server ./etc/redis.conf
 #重启
#杀死主机进程,30秒后观察哨兵日志
 ps -ef|grep redis(查看主机线程)
 kill -s 9 14988(杀死主机线程)
#启动主机,观察哨兵日志
 ./bin/redis-server ./etc/redis.conf
 #您可以使用以下命令测试哨兵连接。
redis-cli -p 26379 sentinel masters

多哨兵模式:

  • 哨兵监控主从的同时,也监控其他哨兵.

  • 当主宕机,哨兵中选出一个哨兵,这个哨兵再从其他从服务器中选出新的主.

  • 
    
#1把哨兵文件复制出来,新弄三个哨兵
cd  /usr/local/redis/etc/
 cp sentinel.conf sentinel-1.conf
 cp sentinel.conf sentinel-2.conf
 cp sentinel.conf sentinel-3.conf
 #修改上面新增的配置文件
  vim sentinel-1.conf
  
protected-mode no
port 27001
daemonize yes
pidfile "/var/run/redis-sentinel-27001.pid"
logfile "/usr/local/redis/log/27001.log"
sentinel monitor mymaster 192.168.8.3 6379 2
  #启动哨兵
 ./bin/redis-sentinel ./etc/sentinel-1.conf
 ./bin/redis-sentinel ./etc/sentinel-2.conf
./bin/redis-sentinel ./etc/sentinel-3.conf
# 格式:/usr/local/redis/bin/redis-sentinel + 配置文件的绝对路径
/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel-1.conf
#同时创三个哨兵并同时启动
#kill杀死从机,主机进行测试
 ps -ef|grep redis 查询redis线程
 kill -s 9 1111    杀死线程代码,数字自定义
 

Cluster模式

Redis集群模式

哈希槽:默认 Redis 官方在 Redis 集群模式中内置了 16384 个槽。
1 % 16384 = 1
重定向:在Redis集群任意节点查询或存储修改数据时,通过哈希

  • .find / -name redis.conf查找叫redis.conf文件的位置

cd /usr/local/redis/ redis-cluster/ 进入编辑目录

#1.创建文件位置存放数据
cd /usr/local/redis
 mkdir redis-cluster
cd redis-cluster/
 mkdir 7001
 mkdir 7002
 mkdir 7003
 mkdir 7004
 mkdir 7005
mkdir 7006
# 2.复制配置文件(按照上文cd路径走,不要推出)  
cp /etc/redis/redis.conf  ./7001/redis.conf
cp /etc/redis/redis.conf  ./7002/redis.conf
cp /etc/redis/redis.conf  ./7003/redis.conf
cp /etc/redis/redis.conf  ./7004/redis.conf
cp /etc/redis/redis.conf  ./7005/redis.conf
cp /etc/redis/redis.conf  ./7006/redis.conf
#3.下载yum相关
yum install ruby
yum install rubygems
gem install redis  
#4.编辑7001-7006的
vim ./redis-cluster/7001/redis.conf

bind 192.168.1.171      (第一行内容)
port 7001               (大概第三行内容)
daemonize yes           (大概第六行内容)
pidfile "/usr/local/redis/redis-cluster/7001/redis.pid"
(大概第八行)
logfile "/usr/local/redis/logs/redis-7001.log"
(大概第十行)
dir "/usr/local/redis/redis-cluster/7001/"
(大概第20行)
appendonly yes          (大概第39行)
cluster-enabled yes 
cluster-config-file nodes7001.conf
cluster-node-timeout 5000  #redis  (上述三行末尾添加)
#一共5个7001
#再执行复制7001到7002,3,4,5,6,
cp ./redis-cluster/7001/redis.conf ./redis-cluster/7002/redis.conf
#然后编辑
vim ./redis-cluster/7002/redis.conf
#命令行执行
:%s/7001/7002/g
#5.启动resis的1-6
 ./bin/redis-server ./redis-cluster/7001/redis.conf
 ./bin/redis-server ./redis-cluster/7002/redis.conf
 ./bin/redis-server ./redis-cluster/7003/redis.conf
 ./bin/redis-server ./redis-cluster/7004/redis.conf
 ./bin/redis-server ./redis-cluster/7005/redis.conf
 ./bin/redis-server ./redis-cluster/7006/redis.conf
# 6.创建集群
./bin/redis-cli --cluster create 192.168.8.3:7001 192.168.8.3:7002 192.168.8.3:7003 192.168.8.3:7004 192.168.8.3:7005 192.168.8.3:7006 --cluster-replicas 1
#7核验是否成功
[root@mha-node1 redis]# ./bin/redis-cli -c -h 192.168.8.3 -p 7001
192.168.8.3:7001> info cluster
#8.扩展内容
 cluster keyslot a
 #查询a文件的哈希值,可以判断在哪个库
  cluster nodes 
  #查看集群中的节点是否正常,可以试着停掉7003,kill掉他,再次查看会显示7003关闭,主节点被转移为7003的从节点7006,重启7003后显示7003自动成为7006从节点
  # 9.新增从节点的方法
  [root@zuolaoshi redis]# cd redis-cluster/
[root@zuolaoshi redis-cluster]# ls
7001  7002  7003  7004  7005  7006
[root@zuolaoshi redis-cluster]# mkdir 7007
[root@zuolaoshi redis-cluster]# cp ./7006/redis.conf ./7007/redis.conf
[root@zuolaoshi redis-cluster]# cd ..
[root@zuolaoshi redis]# vim ./redis-cluster/7007/redis.conf
#进入后替换7006为7007
[root@zuolaoshi redis]# ./bin/redis-server ./redis-cluster/7007/redis.conf
#启动7007
  [root@zuolaoshi redis]# ./bin/redis-cli --cluster add-node 192.168.8.3:7007 192.168.8.3:7004 --cluster-slave
  #将7插入成为6的从机,但是Redis Cluster 自动分配从节点的机制 —— 即使你指定了目标节点(7004),Cluster 也会优先根据「主节点的从节点数量均衡」原则重新分配,而非强制绑定你指定的目标节点。
  # 10删除节点
  [root@zuolaoshi redis]# ./bin/redis-cli --cluster del-node 192.168.8.3:7007 13870f882f16c028400be7f8d0f360d85faee740
  #后面加的是7007的唯一id通过cluster nodes 命令获取
 # 11.添加节点为主节点
 ./bin/redis-cli --cluster add-node 192.168.8.3:7007 192.168.8.3:7006
 #添加后他会默认是没有从的主节点需要分配
 [root@zuolaoshi redis]# ./bin/redis-cli --cluster reshard 192.168.8.3:7007
 后续会弹出6个需要输入的内容
 1.分配给7007的哈希数
 2.7007的id
 3-5.主1-主3的id
 6.done  #表示输入完毕
 随后输入yes进入执行
cd /tmp
# 从华为云镜像下载 Ruby 2.7.8 源码包
wget https://mirrors.huaweicloud.com/ruby/ruby/2.7/ruby-2.7.8.tar.gz
步骤 4:继续解压和编译安装
# 解压源码包(此时不会再报错)
tar -zxvf /tmp/ruby-2.7.8.tar.gz
# 进入解压后的目录
cd /tmp/ruby-2.7.8
# 配置编译参数(指定安装路径,关联 openssl)
./configure --prefix=/usr/local/ruby --with-openssl-dir=/usr/include/openssl
# 编译(用4线程加速,根据CPU核心数调整,如 -j8)
make -j4
# 安装(耐心等待,约5-10分钟)
make install

后续步骤
安装完成后,继续执行之前的 环境变量配置 和 redis gem 安装:
# 配置环境变量
echo 'export PATH=/usr/local/ruby/bin:$PATH' >> /etc/profile
source /etc/profile
# 验证 Ruby 版本(需显示 2.7.8)
ruby -v
# 安装 redis gem
gem sources --add https://mirrors.aliyun.com/rubygems/ --remove https://rubygems.org/
gem install redis -v 4.8.0

1

posted @ 2025-08-11 20:29  秀妍泽  阅读(25)  评论(0)    收藏  举报