JC/基础/二阶段MYSQL.txt
2024-12-26 10:22:14 +08:00

2180 lines
66 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据库
## 第一章:数据库基础
### 数据库
Mysql 数据库软件 Oracle Sql-server Mariadb 自研数据库 云产品 云数据库
------
###### 数据库技术:
DBS DBMS
------
###### 数据库分类:
关系型数据库SQLMysql Oracle 数据采用库表的形式存储
非关系型数据库NoSQLNot only SQLRedis Memcache Mongodb K-V 键值对
------
###### 数据库访问技术:
Java
JDBC
实现在项目后端源码中添加数据库的相关信息: 数据库IP地址 数据库端口 数据库用户名 数据库密码 数据库库名
------
php
ODBC
实现在项目后端源码中添加数据库的相关信息: 数据库IP地址 数据库端口 数据库用户名 数据库密码 数据库库名
------
python
settings.py
实现在项目后端源码中添加数据库的相关信息: 数据库IP地址 数据库端口 数据库用户名 数据库密码 数据库库名
------
###### 数据库部署:
版本:
mysql8.0
mysql5.7
网址www.mysql.com
------
#### YUM安装
安装在BASE和EPEL仓库中没有Mysql的RPM包但是有Mariadb的RPM包
```
1.准备Mysql的yum仓库
yum -y install https://dev.mysql.com/get/mysql80-community-release-el7-11.noarch.rpm
2.修改安装版本,启用5.7版本
yum -y install yum-utils
yum-config-manager --disable mysql80-community
yum-config-manager --enable mysql57-community
3.安装
yum -y install mysql mysql-server
客户端mysql-community-client
服务器端mysql-community-server
初始化:
[root@mysql-rpm ~]# systemctl start mysqld
[root@mysql-rpm ~]# systemctl enable mysqld
修改密码:
cat /var/log/mysqld.log | grep password
[root@mysql-rpm ~]# mysqladmin -uroot -p'uEe0vMb#kRHY' password 'QianFeng@123'
[root@mysql-rpm ~]# mysql -uroot -pQianFeng@123
```
------
#### 编译安装
```
1.准备编译安装的环境
yum -y install ncurses ncurses-devel openssl-devel bison gcc gcc-c++ make cmake
2.获取编译安装包wget
[root@xingdian ~]# wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-boost-5.7.39.tar.gz
[root@xingdian ~]# tar xf mysql-boost-5.7.39.tar.gz
3.采用cmake的方式配置指定安装目录 存放数据的目录 指定了端口号 指定了字符集等)
cd mysql-5.7.43/
vi 1.sh写入
cmake . \
-DWITH_BOOST=boost/boost_1_59_0/ \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DSYSCONFDIR=/etc \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DINSTALL_MANDIR=/usr/share/man \
-DMYSQL_TCP_PORT=3306 \
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
-DDEFAULT_CHARSET=utf8 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_READLINE=1 \
-DWITH_SSL=system \
-DWITH_EMBEDDED_SERVER=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1
4.make进行编译
5.make install 进行安装
初始话:
1.准备用户和组
[root@xingdian ~]# groupadd mysql
[root@xingdian ~]# useradd -r -g mysql -s /bin/nolgin mysql
2.创建了所需要的目录 (在指定的目录下创建)
mkdir /usr/local/mysql/mysql-files
3.修改安装目录所有者和所属组
chown mysql.mysql /usr/local/mysql/ -R
4.进行指定用户指定安装目录指定数据存放目录的初始化操作,这一步可以获取到对应的初始密码
/usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
5.利用mysqld_safe的命令指定用户后台运行了mysql
/usr/local/mysql/bin/mysqld_safe --user=mysql &
排错yum -y remove mariadb-libs
6.利用mysqladmin的命令修改了数据库的初始密码
./bin/mysqladmin -u root -p'#l5.i0suoijM' password 'Zhuwenbao@123'
7.登录测试 mysql的命令指定用户和密码
./bin/mysql -uroot -p 'Zhuwenbao@123'
```
------
###### 目录和文件
YUM 安装:
/etc/my.cnf默认的数据库mysql的主配置文件
/var/lib/mysql/:用来存放数据的目录
/var/log/mysqld.log mysql的错误日志文件
如果在数据库mysql没有运行的情况下删除/var/lib/mysql这个目录下的内容相当于是重置恢复出厂设置当在次启动的时候数据全部被删除了得到了新的初始密码
------
编译安装:
指定了安装目录和数据存放目录 /usr/local/mysql /usr/local/mysql/data
如果在数据库mysql没有运行的情况下删除了/usr/local/mysql 安装目录相当于卸载了mysql
如果在数据库mysql没有运行的情况下删除了/usr/local/mysql/data 数据存放目录,相当于是重置了数据库
------
###### 编译安装扩展:
```
设置环境变量可以直接使用mysql相关命令
[root@xingdian ~]# echo "export PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
[root@xingdian ~]# source /etc/profile
设置开机启动并用systemctl管理mysql服务
[root@xingdian ~]# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
[root@xingdian ~]# chkconfig mysqld on //做开机启动
[root@xingdian ~]# systemctl start mysqld
[root@xingdian ~]# systemctl stop mysqld
```
------
#### 数据库引擎
数据库存储引擎是数据库底层软件组织数据库管理系统DBMS使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能使用不同的存储引擎还可以 获得特定的功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是存储引擎
------
##### InnoDB存储引擎
InnoDB是事务型数据库的首选引擎支持事务安全表ACID支持行锁定和外键;InnoDB是默认的MySQL引擎
特点:
支持事务处理支持外键支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高比如银行要求实现并发控制比如售票那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库也可以选择InnoDB因为支持事务的提交和回滚
------
##### MyISAM存储引擎
MyISAM基于ISAM存储引擎并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度但不支持事务
特点:
插入数据快空间和内存使用比较低。如果表主要是用于插入新记录和读出记录那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低也可以使用
------
##### MEMORY存储引擎
MEMORY存储引擎将表中的数据存储到内存中为查询和引用其他表数据提供快速访问
特点:
所有的数据都在内存中数据的处理速度快但是安全性不高。如果需要很快的读写速度对数据的安全性要求较低可以选择MEMOEY。它对表的大小有要求不能建立太大的表。所以这类数据库只使用在相对较小的数据库表
------
##### 如何选择引擎
show engines;(查看)
如果要提供提交、回滚、崩溃恢复能力的事物安全ACID兼容能力并要求实现并发控制InnoDB是一个好的选择
如果数据表主要用来插入和查询记录则MyISAM引擎能提供较高的处理效率如果只是临时存放数据数据量不大并且不需要较高的数据安全性可以选择将数据保存在内存中的Memory引擎MySQL中使用该引擎作为临时表存放查询的中间结果
如果只有INSERT和SELECT操作可以选择ArchiveArchive支持高并发的插入操作但是本身不是事务安全的。Archive非常适合存储归档数据如记录日志信息可以使用Archive。
使用哪一种引擎需要灵活选择,一个数据库中多个表可以使用不同引擎以满足各种性能和实际需求,使用合适的存储引擎,将会提高整个数据库的性能
------
#### mysql事务
**MySQL 事务主要用于处理操作量大,复杂度高的数据。**比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行
事务用来管理 insert,update,delete 语句
------
##### 满足事务条件
**原子性**一个事务transaction中的所有操作要么全部完成要么全部不完成不会结束在中间某个环节。事务在执行过程中发生错误会被回滚Rollback到事务开始前的状态就像这个事务从来没有执行过一样
**一致性**:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作
**隔离性**数据库允许多个并发事务同时对其数据进行读写和修改的能力隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别包括读未提交Read uncommitted、读提交read committed、可重复读repeatable read和串行化Serializable
**持久性**:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
------
## 第二章:数据库管理及数据类型
##### 一.数据类型
###### 1.数值类型
###### 2.整数类型
整数类型TINYINT SMALLINT MEDIUMINT INT BIGINT
作用用于存储用户的年龄、游戏的Level、经验值等
------
###### 3.浮点数类型
浮点数类型FLOAT DOUBLE
作用:用于存储用户的身高、体重、薪水等
float(5,3) 5宽度 3精度
------
###### 4.定点数类型
定点数类型DEC
定点数在MySQL内部以字符串形式存储比浮点数更精确适合用来表示货币等精度高的数据
###### 5.位类型
位类型BIT
BIT(M)可以用来存放多位二进制数M范围从1~64如果不写默认为1位
------
##### 二.字符串类型
CHAR系列 CHAR VARCHAR
TEXT系列 TINYTEXT TEXT MEDIUMTEXT LONGTEXT
BLOB 系列 TINYBLOB BLOB MEDIUMBLOB LONGBLOB
BINARY系列 BINARY VARBINARY
------
###### 1.枚举类型
性别 男女
枚举类型:枚举列可以把一些不重复的字符串存储成一个预定义的集合
------
###### 2.时间和日期类型
时间和日期类型DATE TIME DATETIME TIMESTAMP YEAR
作用:用于存储用户的注册时间,文章的发布时间,文章的更新时间,员工的入职时间等
扩展select now();查看当前时间
------
#### 库操作
##### 相关命令
```
创建库create database 库名
mysql> create database qianfeng;
mysql> create database diandian default character set utf8; 指定默认字符集
删除库drop database 库名;
切换: 切换use 库名;
查看show databases;
```
------
#### 表操作
##### 相关命令
```
创建:
表名 字段(数据类型 [约束条件][存储引擎 字符集]
create table t1(name varchar(20),id int(4),sex enum('m','f'),class varchar(50));
插入:
insert into 表名 values(字段和值);
可以同时插入多条数据
指定字段插入数据(字段的约束条件)
按照字段的顺序依次插入
删除drop database 数据库名;
更新update Update 表名 set 列名=值where 条件
mysql> update student set name='123' where id=1;
删除某一行:
delete from 表名 where id=1
mysql> delete from type where id=1;
查看desc student1;
查询select * from 表名
修改alter
mysql> alter table t1 rename table1; //修改表名
mysql> alter table school.t2 rename school.table2
```
------
##### 表修改
------
###### 1.修改数据库引擎
```shell
mysql> alter table service engine=innodb; //engine=myisam|memory|....
```
------
###### 2.添加字段
```shell
mysql> create table student10 (id int);
mysql> alter table student10 add name varchar(20) not null, add age int not null default 22;
mysql> alter table student10 add stu_num int not null after name; //添加name字段之后
mysql> alter table student10 add sex enum('male','female') default 'male' first; //添加到最前面
```
------
###### 3.删除字段
```shell
mysql> alter table student10 drop sex;
```
------
###### 4.修改字段类型
```shell
MySQL [school]> desc student10;
MySQL [school]> alter table student10 modify age tinyint not null ;
MySQL [school]> desc student10;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| age | tinyint(4) | NO | | NULL | |
+-------+------------+------+-----+---------+-------+
MySQL [school]> alter table student10 modify id int not null primary key ; //修改字段类型、约束、主键
MySQL [school]> desc student10;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| age | tinyint(4) | NO | | NULL | |
+-------+------------+------+-----+---------+-------+
```
------
###### 5.增加约束
```shell
MySQL [school]> alter table student10 modify id int not null primary key ;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
MySQL [school]> desc student10;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| age | tinyint(4) | NO | | NULL | |
+-------+------------+------+-----+---------+-------+
MySQL [school]> alter table student10 modify id int not null primary key auto_increment;
ERROR 1068 (42000): Multiple primary key defined //错误该字段已经是primary key
MySQL [school]> alter table student10 modify id int not null auto_increment;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
```
------
###### 6.增加主键
```shell
MySQL [school]> alter table student1 add primary key(id);
MySQL [school]> desc student1;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| age | int(11) | YES | | NULL | |
| name | char(1) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
```
------
###### 7.修改主键和自增
```shell
MySQL [school]> alter table student1 modify id int auto_increment;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
MySQL [school]> desc student1;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| age | int(11) | YES | | NULL | |
| name | char(1) | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+
```
------
###### 8.删除主键
```shell
MySQL [school]> desc student10;
MySQL [school]> alter table student10 drop primary key;
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
删除自增
ySQL [school]> alter table student10 modify id int not null;
MySQL [school]> alter table student10 drop primary key;
```
------
###### 9.复制表
复制表结构+记录 key不会复制: 主键、外键和索引)复制表结构/记录+表结构不会将Key复制
```shell
mysql> create table new_service select * from service;
```
只复制表结构:
```shell
mysql> create table new1_service select * from service where 1=2; //条件为假,查不到任何记录
```
可以复制主键,只复制表结构:
```shell
mysql> create table t4 like employees;
```
------
###### 10.删除表
```shell
mysql> DROP TABLE 表名;
```
------
###### 11.修改数据表中字段的值
语法:Update 表名 set 列名=值where 条件
```shell
mysql> update student set name='123' where id=1;
```
删除某一行:delete from 表名 where id=1
```shell
mysql> delete from type where id=1;
```
------
## 第三章:数据库查询
### 一:基本查询
1.单表查询
2.简单查询
3.通过条件查询
4.查询排序
5.限制查询记录数
6.使用集合函数查询
7.分组查询
8.使用正则表达式查询
#### 2.查询案例
创建案例所需表company.employee5
插入模拟数据select 字段名称,字段名称2...... from 表名 [条件]
------
##### a.简单查询
```shell
MySQL [company]> select * from employee5;
MySQL [company]> select name, salary, dep_id from employee5 where id <=5;
+-------+---------+--------+
| name | salary | dep_id |
+-------+---------+--------+
| jack | 5000.00 | 100 |
| tom | 5500.00 | 100 |
| robin | 8000.00 | 100 |
| alice | 7200.00 | 100 |
| | 600.00 | 101 |
+-------+---------+--------+
5 rows in set (0.00 sec)
```
------
##### b.避免重复
不能部分使用DISTINCT通常仅用于某一字段
```shell
MySQL [company]> SELECT post FROM employee5;
MySQL [company]> SELECT distinct post FROM employee5;
+------------+
| post |
+------------+
| instructor |
| hr |
| sale |
+------------+
```
------
##### c.四则运算查询
```shell
MySQL [company]> SELECT name, salary, salary*14 FROM employee5;
+-----------+----------+-----------+
| name | salary | salary*14 |
+-----------+----------+-----------+
| jack | 5000.00 | 70000.00 |
MySQL [company]> SELECT name, salary, salary*14 AS Annual_salary FROM employee5;(名字)
+-----------+----------+---------------+
| name | salary | Annual_salary |
+-----------+----------+---------------+
```
##### d.定义显示格式
CONCAT() 函数用于连接字符串
```shell
MySQL [company]> SELECT concat(name, 's annual salary: ', salary*14) AS Annual_salary FROM employee5;
+------------------------------------+
| Annual_salary |
+------------------------------------+
| jacks annual salary: 70000.00 |
```
------
##### e.单条件查询
```shell
MySQL [company]> SELECT name,post FROM employee5 WHERE post='hr';
+-------+------+
| name | post |
+-------+------+
| | hr |
| harry | hr |
+-------+------+
```
------
##### f.多条件查询
```shell
MySQL [company]> SELECT name,salary FROM employee5 WHERE post='hr' AND salary>10000;
Empty set (0.00 sec)
MySQL [company]> select * from employee5 where salary>5000 and salary<10000 or dep_id=102;
```
------
##### g.关键字
BETWEEN AND
```shell
MySQL [company]> SELECT name,salary FROM employee5 where salary BETWEEN 5000 AND 15000;
between .....and (之间)
MySQL [company]> SELECT name,salary FROM employee5 WHERE salary NOT BETWEEN 5000 AND 15000;
```
IS NULL
```shell
MySQL [company]> SELECT name,job_description FROM employee5 WHERE job_description IS NULL;
+--------+-----------------+
| name | job_description |
+--------+-----------------+
| harry | NULL |
| zhuzhu | NULL |
+--------+-----------------+
MySQL [company]> SELECT name,job_description FROM employee5 WHERE job_description IS NOT NULL;
MySQL [company]> SELECT name,job_description FROM employee5 WHERE job_description='';
+--------+-----------------+
| name | job_description |
+--------+-----------------+
| gougou | |
+--------+-----------------+
1 row in set (0.00 sec)
```
注意NULL说明
等价于没有任何值、是未知数
NULL与0、空字符串、空格都不同,NULL没有分配存储空间
对空值做加、减、乘、除等运算操作,结果仍为空
比较时使用关键字用“is null”和“is not null”
排序时比其他数据都小索引默认是降序排列小→大所以NULL值总是排在最前
IN集合查询
```shell
MySQL [company]> SELECT name, salary FROM employee5 WHERE salary=4000 OR salary=5000 OR salary=6000 OR salary=9000 ;
+-------+---------+
| name | salary |
+-------+---------+
| jack | 5000.00 |
| harry | 6000.00 |
+-------+---------+
MySQL [company]> SELECT name, salary FROM employee5 WHERE salary IN (4000,5000,6000,9000) ;
MySQL [company]> SELECT name, salary FROM employee5 WHERE salary NOT IN (4000,5000,6000,9000) ;
```
------
##### h.模糊查询
关键字LIKE
通配符%:所有字符
通配符_ 一个字符
```shell
MySQL [company]> SELECT * FROM employee5 WHERE name LIKE 'al%';
MySQL [company]> SELECT * FROM employee5 WHERE name LIKE 'al___';
```
------
##### i.排序查询
```shell
MySQL [company]> select name,salary from employee5 order by salary;(升序)
MySQL [company]> select name,salary from employee5 order by salary desc; (降序)
MySQL [company]> select name,salary from employee5 order by salary desc limit 3; //控制显示前3行
MySQL [company]> select name,salary from employee5 order by salary desc limit 1,3; //从序号1开始显示三行的内容
```
------
##### j.集合函数查询
count可以查看共有多少条记录
```shell
MySQL [company]> select count(*) from employee5;
MySQL [company]> select count(name) from employee5;
```
max查看最大值
```shell
MySQL [company]> select max(salary) from employee5;
```
min查看最小值
```shell
MySQL [company]> select min(salary) from employee5;
```
avg查看平均值
```shell
MySQL [company]> select avg(salary) from employee5;
```
sum求和
sale这个部门的总工资
```shell
MySQL [company]> select concat("Total Department Wages",sum(salary)) from employee5 where post='sale';
+-------------------------------------------------+
| concat("Total Department Wages",sum(salary)) |
+-------------------------------------------------+
| Total Department Wages26600.00 |
+-------------------------------------------------+
1 row in set (0.00 sec)
```
获取薪水最高的这个人的详细信息
```shell
MySQL [company]> select * from employee5 where salary = (select max(salary) from employee5);
```
------
##### k.分组查询
GROUP BY和GROUP_CONCAT()函数一起使用
获取部门ID相同的员工并把名字拼接到一起
```shell
MySQL [company]> SELECT dep_id,GROUP_CONCAT(name) FROM employee5 GROUP BY dep_id;
+--------+------------------------------+
| dep_id | GROUP_CONCAT(name) |
+--------+------------------------------+
| 100 | jack,tom,robin,alice |
| 101 | ,harry |
| 102 | emma,christine,zhuzhu,gougou |
+--------+------------------------------+
3 rows in set (0.01 sec)
```
GROUP BY和集合函数一起使用
获取部门最高薪资
```shell
MySQL [company]> SELECT post,max(salary) FROM employee5 GROUP BY post;
+------------+-------------+
| post | max(salary) |
+------------+-------------+
| hr | 6000.00 |
| instructor | 8000.00 |
| sale | 20000.00 |
+------------+-------------+
3 rows in set (0.00 sec)
```
------
##### l.正则查询
```shell
以什么开头
MySQL [company]> SELECT * FROM employee5 WHERE name REGEXP '^ali';
以什么结尾
MySQL [company]> SELECT * FROM employee5 WHERE name REGEXP 'ce$';
连续出现n次
MySQL [company]> SELECT * FROM employee5 WHERE name REGEXP 'm{2}';
```
------
### 二:多表联合查询【扩展了解】
#### 1.数据准备
###### 两张表
#### 2.多表连接查询
交叉连接:生成笛卡尔积,它不使用任何匹配条件;交叉联接返回左表中的所有行,左表中的每一行与右表中的所有行组合
内连接:只连接匹配的行
外连接:
1.左连接:会显示左边表内所有的值,不论在右边表内匹不匹配
2.右连接:会显示右边表内所有的值,不论在左边表内匹不匹配
全外连接:包含左、右两个表的全部行
------
##### 交叉连接
```shell
MySQL [company]> select employee6.emp_name,employee6.age,employee6.dept_id,department6.dept_name from employee6,department6;
```
------
##### 内连接
获取有部门的员工 (部门表中没有natasha所在的部门)
```shell
MySQL [company]> select employee6.emp_name,employee6.age,employee6.dept_id,department6.dept_name from employee6,department6 where employee6.dept_id=department6.dept_id;
MySQL [company]> select employee6.emp_name,department6.dept_name from employee6 inner join department6 on
employee6.dept_id=department6.dept_id;
```
------
##### 外连接
语法:
SELECT 字段列表 FROM 表1 LEFT|RIGHT JOIN 表2 ON 表1.字段 = 表2.字段;
注意:
先用谁谁就是左
------
###### 左连接 left join
```shell
找出所有员工及所属的部门,包括没有部门的员工
MySQL [company]> select emp_id,emp_name,dept_name from employee6 left join department6 on employee6.dept_id = department6.dept_id;
```
------
###### 右连接right join
```
找出所有部门包含的员工,包括空部门
MySQL [company]> select emp_id,emp_name,dept_name from employee6 right join department6 on employee6.dept_id = department6.dept_id;
```
------
##### 全外连接
```shell
MySQL [company]> select * from employee6 full join department6;
```
------
#### 3.复合条件连接查询
------
##### 案例一
找出公司所有部门中年龄大于25岁的员工
以内连接的方式查询employee6和department6表并且employee6表中的age字段值必须大于25
```shell
MySQL [company]> select emp_id,emp_name,dept_name FROM employee6,department6 WHERE employee6.dept_id = department6.dept_id AND age > 25;
```
------
##### 案例二
以内连接的方式查询employee6和department6表并且以age字段的升序方式显示
```shell
MySQL [company]> select emp_id,emp_name,dept_name FROM employee6,department6 WHERE employee6.dept_id = department6.dept_id ORDER BY age asc;
```
------
#### 4.子查询
子查询是将一个查询语句嵌套在另一个查询语句中
内层查询语句的查询结果,可以为外层查询语句提供查询条件
子查询中可以包含IN、NOT IN等关键字还可以包含比较运算符= 、 !=、> 、<等
------
##### 案例一
带IN关键字的子查询查询employee表但dept_id必须在department表中出现过
```shell
MySQL [company]> select * from employee6 WHERE dept_id IN (select dept_id FROM department6);
```
------
##### 案例二
带比较运算符的子查询查询年龄大于等于25岁员工所在部门查询老龄化的部门
```
MySQL [company]> select dept_id,dept_name FROM department6 WHERE dept_id IN (SELECT DISTINCT dept_id FROM employee6 WHERE age >=25);
```
------
## 第四章:数据库日志管理
### 一:日志管理
<img src="https://xingdian-image.oss-cn-beijing.aliyuncs.com/xingdian-image/image-20220925214046253.png" alt="image-20220925214046253" style="zoom:50%;" />
------
#### 1.日志分类
错误日志 启动停止关闭失败报错。rpm安装日志位置 /var/log/mysqld.log
通用查询日志:所有的查询都记下来
二进制日志实现备份增量备份。只记录改变数据除了select都记
中继日志读取主服务器的binlog在本地回放。保持一致
slow log慢查询日志指导调优定义某一个查询语句定义超时时间通过日志提供调优建议给开发人员
DDL log 定义语句的日志
------
#### 2.Error Log
```shell
log-error=/var/log/mysqld.log
```
#### 3.Binary Log
```
vi /etc/my.cnf
log-bin=/var/log/mysql-bin/slave2
server-id=2
[root@slave2 ~]# mkdir /var/log/mysql-bin
[root@slave2 ~]# chown mysql.mysql /var/log/mysql-bin/
[root@slave2 ~]# systemctl restart mysqld
```
注意:需要提前开启
查看binlog日志
```shel
[root@slave2 ~]# mysqlbinlog slave2-bin.000001 -v -base64-output=decode-rows
注:
1. 重启mysqld 会截断
2. flush logs 会截断
3. reset master 删除所有binlog
4. 删除部分
PURGE BINARY LOGS TO 'mysql-bin.010';
PURGE BINARY LOGS BEFORE '2019-04-02 22:46:26';
截取binlog
all
# mysqlbinlog mysql.000002
```
------
#### 4.Slow Query Log
开启慢查询日志:
```shell
[root@xingdian ~]# vi /etc/my.cnf
slow_query_log=1
slow_query_log_file=/var/lib/mysql/slow.log
long_query_time=3 设置慢查询超时时间 单位是:秒
```
创建对应目录:
```shell
[root@xingdian ~]# mkdir /var/log/mysql-slow
[root@xingdian ~]# chown mysql.mysql mysql-slow
```
重启服务:
```shell
[root@xingdian ~]# systemctl restart mysqld
```
验证mysql -uroot -pQianFeng@123
cat slow.log
------
## 第五章:权限管理及数据备份与恢复
------
### 一:权限管理
------
#### 1.权限级别
```
Global level系统级所有库所有表的权限
Database level某个数据库中的所有表的权限
Table level库中的某个表的权限
Column level表中的某个字段的权限
procs level某个存储过程的权限
proxies level代理服务器的权限
```
------
#### 2.查看权限记录表
因为超级管理员默认已经设置;所以直接查询权限即可
##### Global level(*)
```
mysql> select * from mysql.user\G
```
------
字段介绍:
```shell
用户字段root
权限字段Select_priv
安全字段:*B1DD4ADE47888D9AEC4D705C85230F1B52D2A817
Select_priv查询权限
Insert_priv插入权限
Update_priv更新权限
Delete_priv删除权限
```
------
##### Database level(*)
```shell
mysql> select * from mysql.db\G;
```
测试库权限:
```shell
mysql> create database t1;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on t1.* to 't1'@'localhost' identified by 'QianFeng@123';
Query OK, 0 rows affected, 1 warning (0.00 sec)
查看mysql> select * from mysql.db\G
验证:[root@xingdian ~]# mysql -u t1 -pQianFeng@123
```
------
##### Table level(*)
```shell
mysql> select * from mysql.tables_priv\G;
创建库表验证:
mysql> create database t2;
mysql> use t2;
mysql> insert into u1 values (1);
mysql> grant all on t2.u1 to 't2'@'localhost' identified by 'QianFeng@123';
mysql> create table u2(id int);
mysql> show tables;
权限查看mysql> select * from mysql.tables_priv\G;
验证登录t2账户看到u1表看不到u2代表权限成功
mysql -u t2 -pQianFeng@123
show databases;
use t2
show tables;
```
------
##### Column level
```shell
[root@xingdian ~]# mysql -uroot -pQianFeng@123
mysql> select * from mysql.columns_priv\G;
mysql> insert into mysql.columns_priv(host,db,user,table_name,column_name,column_priv) values('%','t2','t2','u1','id','select');
mysql> select * from mysql.columns_priv\G;
注意:前提是有库,有表,有权限
```
------
### 二:用户管理
#### 1.登录和退出
```shell
[root@xingdian ~]# mysql -h 192.168.18.160 -P 30042 -u root -pmysql -e "show databases;"
[root@xingdian ~]# mysql -h 192.168.18.160 -P 30042 -u root -pmysql mysql -e "show tables;"
-h 指定主机名 【默认为localhost】
-P MySQL服务器端口 【默认3306】
-u 指定用户名 【默认root】
-p 指定登录密码 【默认为空密码】
此处mysql为指定登录的数据库
-e 接SQL语句 (在脚本中使用)
```
------
#### 2.创建用户
方式一:
```shell
mysql> create user xingdian;
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
注意:该报错是因为密码强度问题,取消密码强度即可创建用户
mysql> create user xingdian@'%' identified by 'QianFeng@123';
Query OK, 0 rows affected (0.00 sec)
```
------
方式二:
```shell
mysql> grant all on *.* to 'diange'@'localhost' identified by 'QianFeng@123';
注意:该方式采用授权的方式 ALL所有权限 select单独某一个权限多个权限用逗号隔开
mysql> grant select on *.* to 'dianye'@'localhost' identified by 'QianFeng@123';
*.* :所有的库所有的表 也可以单独某一个库某一个表
```
```shell
xingdian@localhost 用户有则授权无则创建 localhost % 10.19.40.% 10.19.40.11
```
------
#### 3.删除用户
方式一:
```shell
MySQL [(none)]> Drop user xingdian@'%';
```
------
方法二:
```shell
MySQL [(none)]> delete from mysql.user where user='diandian' AND Host='%';
```
------
#### 4.修改密码
方式一:
```shell
[root@xingdian ~]# mysqladmin -uroot -p'123' password 'new_password' //123为旧密码
```
------
方式二:
```shell
MySQL [(none)]> update mysql.user set authentication_string=password(123456) where user='diange' And Host='%';
刷新授权表后生效flush privileges
```
自己设置自己密码:
```shell
自己设置自己密码:
MySQL [(none)]> set password='123';
root用户修改其他用户密码
方法一:
mysql> SET PASSWORD FOR user3@'localhost'='new_password';
方法二:
UPDATE mysql.user SET authentication_string=password('new_password') WHERE user='user3' AND host='localhost';
```
------
#### 5.查看密码策略
```shell
mysql> show variables like 'validate_password%'
参数解释:
validate_password_dictionary_file 指定密码验证的文件路径
validate_password_length 密码最小长度
validate_password_mixed_case_count 密码至少要包含的小写字母个数和大写字母个数
validate_password_number_count 密码至少要包含的数字个数
validate_password_policy 密码强度检查等级对应等级为0/LOW、1/MEDIUM、2/STRONG,默认为1
0/LOW只检查长度
1/MEDIUM检查长度、数字、大小写、特殊字符
2/STRONG检查长度、数字、大小写、特殊字符字典文件
validate_password_special_char_count密码至少要包含的特殊字符数
修改密码策略:
set global validate_password_length=4;
关闭密码策略:(简单密码设置)
修改配置文件,添加以下参数:
vi /etc/my.cnf
添加:validate_password=off
```
------
### 三:数据备份及恢复
#### 1.概述
```
所有备份数据都应放在非数据库本地,而且建议有多份副本
备份: 能够防止由于机械故障以及人为误操作带来的数据丢失,例如将数据库文件保存在了其它地方
冗余: 数据有多份冗余,但不等备份,只能防止机械故障还来的数据丢失,例如主备模式、数据库集群
备份考虑的因素:数据的一致性,服务的可用性
分类:
逻辑备份:备份的是建表、建库、插入等操作所执行SQL语句适用于中小型数据库效率相对较低mysqldump
物理备份:直接复制数据库文件适用于大型数据库环境不受存储引擎的限制但不能恢复到不同的MySQL版本tar、xtrabackup
```
------
#### 2.tar备份
注意:备份期间,服务不可用
备份过程:完全物理备份
```shell
停止数据库:
[root@xingdian ~]# systemctl stop mysqld
tar备份数据:
[root@xingdian ~]# mkdir /opt
[root@xingdian ~]# cd /var/lib/mysql
[root@xingdian ~]# tar -cf /opt/`date +%F`-mysql-all.tar.gz ./*
恢复过程:模拟数据丢失,恢复数据:
清理环境:rm -rf /var/lib/mysql/*
导入备份数据:
[root@xingdian ~]# tar -xf /opt/2019-08-20-mysql-all.tar.gz -C /var/lib/mysql
修改所属组所属主:
[root@xingdian ~]# chown mysql.mysql /var/lib/mysql/* -R
启动数据库(恢复后验证数据是否恢复成功):
[root@xingdian ~]# systemctl start mysqld
```
------
#### 3.xtrabackup备份
安装软件:
```shell
[root@xingdian ~]# yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm -y
[root@xingdian ~]# yum install percona-xtrabackup-24 -y
```
##### 完整备份
```shell
创建备份目录:
[root@xingdian ~]# mkdir -p /opt/full/
备份:
[root@xingdian ~]# innobackupex --user=root --password='Zhuwenbao@123' /opt/full/
查看备份数据:
[root@xingdian ~]# ls /opt/full/
2022-09-25_19-40-47
模拟增加数据
模拟数据丢失:
[root@xingdian ~]# systemctl stop mysqld
[root@xingdian ~]# rm -rf /var/lib/mysql/*
[root@xingdian ~]# rm -rf /var/log/mysqld.log
[root@xingdian ~]# rm -rf /var/log/mysql-slow/slow.log (有则删除,无则不需要操作)
恢复前的验证:
[root@xingdian ~]# innobackupex --apply-log /xtrabackup/full/2022-09-25_19-40-47/
恢复数据:
[root@xingdian ~]# innobackupex --copy-back /xtrabackup/full/2022-09-25_19-40-47/
修改权限:
[root@xingdian ~]# chown mysql.mysql /var/lib/mysql -R
启动服务:
[root@xingdian ~]# systemctl start mysqld
验证: mysql -u root -pZhuwenbao@123
```
------
##### 增量备份
原理:每次备份上一次备份到现在产生的新数据
注意:在进行增量备份前先进行完整备份
案例:周一进行全备,周二到周天进行增量备份
```shell
完整备份:(周一)
[root@xingdian ~]# innobackupex --user=root --password='Zhuwenbao@123' /opt/full
创建增量备份存放数据目录:
[root@xingdian ~]# mkdir /opt/zeng -p
模拟增加数据
第一次增量备份:(周二)
[root@xingdian ~]# innobackupex --user=root --password='Zhuwenbao@123' --incremental /opt/zeng/ --incremental-basedir=/opt/full/2022-09-25_19-40-47/
[root@xingdian ~]# ls /opt/zeng/
模拟增加数据
第二次增量备份:(周三)
[root@xingdian ~]# innobackupex --user=root --password='Zhuwenbao@123' --incremental /opt/zeng/ --incremental-basedir=/opt/zeng/2022-09-25_19-56-00/
[root@xingdian ~]# ls /opt/zeng/
模拟数据丢失
[root@xingdian ~]# systemctl stop mysqld
删除数据
[root@xingdian ~]# rm -rf /var/lib/mysql/*
[root@xingdian ~]# rm -rf /var/log/mysqld.log
依次重演回滚:(从前往后回滚)
全备回滚
[root@xingdian ~]# innobackupex --apply-log --redo-only /opt/full/2022-09-25_19-40-47/
第一次增量回滚:
[root@xingdian ~]# innobackupex --apply-log --redo-only /opt/full/2022-09-25_19-40-47/ --incremental-dir=/opt/zeng/2022-09-25_19-56-00/
第二次增量回滚:
[root@xingdian ~]# innobackupex --apply-log --redo-only /opt/full/2022-09-25_19-40-47/ --incremental-dir=/opt/zeng/2022-09-25_19-58-12/
恢复数据:
[root@xingdian ~]# innobackupex --copy-back /opt/full/2022-09-25_19-40-47/
修改权限:
chown mysql.mysql /var/lib/mysql -R
启动数据库
验证
```
------
##### 差异备份
原理:只备份跟完整备份不一样的
注意:在进行增量备份前先进行完整备份
案例:周一进行全备,周二到周天进行差异备份
```shell
完整备份:(周一)
[root@xingdian ~]# mkdir -p /opt/full
[root@xingdian ~]# mkdir -p /opt/jian
[root@xingdian ~]# innobackupex --user=root --password=QianFeng@123 /xtrabackup/full
模拟数据增加
第一次差异备份:(周二)
[root@xingdian ~]# innobackupex --user=root --password=Zhuwenbao@123 --incremental /opt/jian --incremental-basedir=/opt/full/2022-09-25_20-10-52/
模拟数据增加
第二次差异备份:(周三)
[root@xingdian ~]# innobackupex --user=root --password=Zhuwenbao@123 --incremental /opt/jian --incremental-basedir=/opt/full/2022-09-25_20-10-52/
模拟数据丢失
停止数据库
删除数据:
[root@xingdian ~]# rm -rf /var/lib/mysql/*
[root@xingdian ~]# rm -rf /var/log/mysqld.log
数据回滚:
完整备份回滚:
[root@xingdian ~]# innobackupex --apply-log --redo-only /opt/full/2022-09-25_20-10-52/
差异备份回滚(根据差异备份的原理,如果恢复所有数据只需要将最后依次差异回滚)
[root@xingdian ~]# innobackupex --apply-log --redo-only /opt/full/2022-09-25_20-10-52/ --incremental-dir=/opt/jian/2022-09-25_20-14-32/(最后一次差异备份数据)
恢复数据:
[root@xingdian ~]# innobackupex --copy-back /opt/full/2022-09-25_20-10-52/
修改权限
启动数据库
验证
```
------
#### 4.mysqldump备份
```shell
备份表:(前提有库有表)
[root@xingdian ~]# mysqldump -u root -pQianFeng@123 k1 t1 > /t1.sql
恢复表:(恢复之前模拟数据丢失)
[root@xingdian ~]# mysql -u root -pQianFeng@123 k1 < /t1.sql
验证
```
------
备份一个库:
```shell
[root@xingdian ~]# mysqldump -u root -pQianFeng@123 k1 > /k1.sql
```
------
备份多个库:
```shell
[root@xingdian ~]# mysqldump -u root -pQianFeng@123 -B k1 k2 > /kall.sql
```
------
备份所有库:
```shell
[root@xingdian ~]# mysqldump -u root -pQianFeng@123 -A > /all.sql
```
------
数据恢复:
为保证数据一致性,应在恢复数据之前停止数据库对外的服务,停止binlog日志
binlog使用binlog日志恢复数据时也会产生binlog日志如果开启的话需要关闭
```shell
mysql> set sql_log_bin=0;
```
模拟数据丢失(略)
```shell
[root@xingdian ~]# mysql -u root -pQianFeng@123 -D k1 < /k1.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1049 (42000): Unknown database 'k1'
出现该错误是因为在恢复的时候需要有库的存在
[root@xingdian ~]# mysql -u root -pQianFeng@123 -e "create database k1"
[root@xingdian ~]# mysql -u root -pQianFeng@123 -D k1 < /k1.sql
[root@xingdian ~]# mysql -u root -pQianFeng@123 -e "create database k1"
[root@xingdian ~]# mysql -u root -pQianFeng@123 -e "create database k2"
[root@xingdian ~]# mysql -u root -pQianFeng@123 -D k1 k2 < /kall.sql
或者
mysql> source /k1.sql
```
------
#### 5.binlog日志备份
原理:日志方法备份恢复数据
日志默认存储位置: /var/lib/mysql
rpm安装永久
```shell
[root@xingdian ~]# vim /etc/my.cnf
log-bin=mylog
server-id=1 //做主从复制使用
[root@xingdian ~]# systemctl restart mysqld
查看:[root@xingdian ~]# ls /var/lib/mysql
方法一:
[root@xingdian ~]# mysqlbinlog /var/lib/mysql/mylog.000001 -v --base64-output=decode-rows
方法二:
mysql> show binlog events in "mylog.000001";
默认查看第一个
mysql> show binlog events;
```
------
数据恢复:
根据时间点恢复数据:
```shell
[root@xingdian ~]# mysqlbinlog --start-datetime='2022-9-25 21:12:47' --stop-datetime='2022-9-25 21:16:55' /var/lib/mysql/mylog.000001 | mysql -u root -pQianFeng@123
```
根据位置点恢复数据:
```
mysql> show binlog events;(查看位置点)
[root@xingdian ~]# mysqlbinlog --start-position 219 --stop-position 307 /var/lib/mysql/mylog.000001 | mysql -u root -pQianFeng@123shell
```
------
## 第六章:主从复制
### 一:主从复制
#### 1.主从复制概念
```
什么是主从复制:
主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;主数据库一般是准实时的业务数据库
主从复制的作用:
做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失
架构的扩展业务量越来越大I/O访问频率过高单机无法满足多库的存储降低磁盘I/O访问的频率提高单个机器的I/O性能读写分离使数据库能支撑更大的并发
主从复制的原理:
数据库有个bin-log二进制文件记录了所有sql语句我们的目标就是把主数据库的bin-log文件的sql语句复制到从库让其在从数据的relay-log(中继日志)重做日志文件中再执行一次这些sql语句即可
总结:
从库slave生成两个线程i/o线程和sql线程i/o将变更记录写到二进制日志文件中再写到中继日志中sql线程读取中继日志解析操作最终数据统一
注意:
I/O进程负责通信
SQL进程负责写数据根据log日志写数据
```
------
#### 2.主从复制部署
##### 环境准备
```
注意:
所有节点关闭防火墙和selinux
保证yum仓库可用
保证网络畅通
如果是克隆的服务器需要修改每台数据库的server-uuid修改主机名
修改主机名:
添加本地解析vi /etc/hosts
```
------
##### Master部署
```
安装数据库: 重置MySQL
启动数据库: systemctl stop mysql
修改数据库初始密码 rm -rf /var/lib/mysql/*
主服务器部署: systemctl start mysql
[root@master ~]# vi /etc/my.cnf
log-bin = my1log
server-id = 1
创建授权账户:
mysql -u root -pQianFeng@123
grant all on *.* to 'slave'@'%' identified by 'QianFeng@123';
flush privileges;
重启服务:
[root@master ~]# systemctl restart mysqld
```
##### Slave部署
```
安装数据库
启动数据库
修改数据库初始密码
[root@slave ~]# vi /etc/my.cnf
log-bin = my2log
server-id = 2
重启服务:
[root@slave ~]# systemctl restart mysqld
获取主服务器信息:(主服务器操作)
[root@master ~]# mysql -u root -pQianFeng@123
show binlog events;
指定主服务器信息:(从服务器操作)
[root@slave ~]# mysql -u root -pQianFeng@123
edit添加
CHANGE MASTER TO
MASTER_HOST='master',
MASTER_USER='slave',
MASTER_PASSWORD='QianFeng@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='my1log.000001',
MASTER_LOG_POS=4,
MASTER_CONNECT_RETRY=10;
获取参数:
mysql> help change master to
start slave;
show slave status\G
验证:主服务器创建数据,从服务器可以看到代表成功
```
```
注意:
stop slave停止slave
reset master删除所有的binglog日志文件并将日志索引文件清空重新开始所有新的日志文件用于第一次进行搭建主从库时进行主库binlog初始化工作
reset slave用于删除SLAVE数据库的relaylog日志文件并重新启用新的relaylog文件
```
------
### 二GTID主从复制
#### 1.GTID概念
```
GTID基于事务ID复制
GTID全局事务标识global transaction identifiers
是用来代替传统复制的方法GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置
不再使用MASTER_LOG_FILE+MASTER_LOG_POS开启复制。而是使用MASTER_AUTO_POSTION=1的方式开始复制
```
------
#### 2.GTID组成
```
GTID = source_id:transaction_id
source_id源id用于鉴别原服务器即mysql服务器唯一的server_uuid由于GTID会传递到slave所以也可以理解为源ID
transaction_id事务id为当前服务器上已提交事务的一个序列号通常从1开始自增长的序列一个数值对应一个事务
示例:
3E11FA47-71CA-11E1-9E33-C80AA9429562:23
前面的一串为服务器的server_uuid
后面的23为transaction_id
```
------
#### 3.GTID工作原理
```
master更新数据时会在事务前产生GTID一同记录到binlog日志中
slave端的i/o 线程将变更的binlog写入到本地的relay log中
sql线程从relay log中获取GTID然后对比slave端的binlog是否有记录
如果有记录说明该GTID的事务已经执行slave会忽略
如果没有记录slave就会从relay log中执行该GTID的事务并记录到binlog
```
------
#### 4.主从部署
##### Master部署
```shell
主服务器部署:
[root@master ~]# vim /etc/my.cnf
log-bin
server-id=1
gtid_mode = ON
enforce_gtid_consistency=1
创建授权用户:
mysql -u root -pQianFeng@123
grant all on *.* to slave@'%' identified by 'QianFeng@123';
flush privileges;
重启服务:
[root@master ~]# systemctl restart mysqld
```
##### Slave部署
```shell
[root@slave ~]# vim /etc/my.cnf
log-bin
server-id=2
gtid_mode = ON
enforce_gtid_consistency=1
relay_log_recovery = on
master-info-repository=TABLE
relay-log-info-repository=TABLE
//这两个参数会将master.info和relay.info保存在表中默认是Myisam引擎官方建议用
重启服务:
[root@slave ~]# systemctl restart mysqld
配置连接主服务器:
mysql -u root -pQianFeng@123
mysql> change master to
-> master_host='master',
-> master_user='slave',
-> master_password='QianFeng@123',
-> master_auto_position=1;
启动Slave
mysql> start slave;
mysql> show slave status\G
验证:主服务器创建数据,从服务器可以看到代表成功
```
------
### 三GTID双主双从
#### Master-1部署
```shell
主服务器一部署:
[root@master-1 ~]# vim /etc/my.cnf
log-bin = my1log
server-id = 1
gtid_mode=ON
enforce_gtid_consistency=1
创建授权账户:
[root@master-1 ~]# mysql -u root -pQianFeng@123
grant all on *.* to 'slave'@'%' identified by 'QianFeng@123';
flush privileges;
重启服务:
[root@master-1 ~]# systemctl restart mysqld
```
------
#### Master-2部署
```shell
主服务器二部署:
[root@master-2 ~]# vim /etc/my.cnf
log-bin = my2log
server-id = 2
gtid_mode=ON
enforce_gtid_consistency=1
创建授权账户:
[root@master-1 ~]# mysql -u root -pQianFeng@123
grant all on *.* to 'slave'@'%' identified by 'QianFeng@123';
flush privileges;
重启服务:
[root@master-1 ~]# systemctl restart mysqld
```
------
#### 双主互为主从
```shell
Master-1
[root@master-1 ~]# mysql -u root -pQianFeng@123
mysql> change master to
-> master_host='master-2',
-> master_user='slave',
-> master_password='QianFeng@123',
-> master_auto_position=1;
mysql> start slave;
mysql> show slave status\G
```
```shell
Master-2
[root@master-2 ~]# mysql -u root -pQianFeng@123
mysql> change master to
-> master_host='master-1',
-> master_user='slave',
-> master_password='QianFeng@123',
-> master_auto_position=1;
mysql> start slave;
mysql> show slave status\G
```
------
#### Slave-1部署
从服务器一部署:
```shell
从服务器一部署:
[root@slave-1 ~]# vim /etc/my.cnf
log-bin = my3log
server-id = 3
gtid_mode=ON
enforce_gtid_consistency=1
relay_log_info_repository = TABLE
master_info_repository = TABLE
relay_log_recovery = on
重启服务:
[root@slave-1 ~]# systemctl restart mysqld
从连接主服务器:
mysql -u root -pQianFeng@123
mysql> CHANGE MASTER TO
-> MASTER_HOST='master-1',
-> MASTER_USER='slave',
-> MASTER_PASSWORD='QianFeng@123',
-> MASTER_AUTO_POSITION=1 FOR CHANNEL 'master-1';
mysql> start slave;
show slave status\G
mysql> CHANGE MASTER TO
-> MASTER_HOST='master-2',
-> MASTER_USER='slave',
-> MASTER_PASSWORD='QianFeng@123',
-> MASTER_AUTO_POSITION=1 FOR CHANNEL 'master-2';
mysql> start slave;
show slave status\G
```
------
#### Slave-2部署
```shell
从服务器二部署:
[root@slave-2 ~]# vim /etc/my.cnf
log-bin = my4log
server-id = 4
gtid_mode=ON
enforce_gtid_consistency=1
relay_log_info_repository = TABLE
master_info_repository = TABLE
relay_log_recovery = on
重启服务:
[root@slave-2 ~]# systemctl restart mysqld
从连接主服务器:
与Slave-1部署一样无变化
验证:两个主服务器创建数据,别的三台都能看到代表成功
```
------
## 第七章:读写分离
### 一:读写分离部署
#### 1.环境介绍
![image-20221006131313211](https://xingdian-image.oss-cn-beijing.aliyuncs.com/xingdian-image/image-20221006131313211.png)
------
#### 2.读写分离集群部署
##### A数据库集群部署
单主单从;多主多从等均可
##### BMycat部署
```shell
新机器不需要安装mysql
安装jdk环境
[root@mycat ~]# tar xf jdk-8u211-linux-x64.tar.gz -C /usr/local/
[root@mycat ~]# mv /usr/local/jdk1.8.0_211/ /usr/local/java
设置环境变量:
[root@mycat ~]# vi /etc/profile
JAVA_HOME=/usr/local/java
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH
[root@mycat ~]# source /etc/profile
[root@mycat ~]# java -version
安装mycat
[root@mycat ~]# tar xf Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz -C /usr/local/
设置环境变量:
[root@mycat ~]# vi ~/.bash_profile
PATH=$PATH:$HOME/bin:/usr/local/mycat/bin
[root@mycat ~]# source ~/.bash_profile
```
------
##### C数据库部署
Mysql中添加数据库和账户
```shell
Mysql中添加数据库和账户
[root@master-1 ~]# mysql -u root -pQianFeng@123
mysql> grant all on bbs.* to bbs@'%' identified by 'QianFeng@123';
```
```
注意:
创建的库跟mycat关联原则上一个库对应一个项目根据实际情况创建
创建的库需要单独授权用户进行管理,用户名和库名根据实际情况决定
```
------
##### DMycat配置
server.xmlMycat的配置文件设置账号、参数等
```shell
[root@mycat conf]# vim server.xml 修改
schema.xmlMycat对应的物理数据库和数据库表的配置
[root@mycat conf]# cat schema.xml
```
------
注意:
```shell
user 用户配置节点
name 登录的用户名也就是连接Mycat的用户名
password 登录的密码也就是连接Mycat的密码
schemas 数据库名这里会和schema.xml中的配置关联多个用逗号分开例如需要这个用户需要管理两个数据库db1,db2则配置db1,db2
```
------
注意:
```shell
balance=1 开启读写分离机制,所有读操作都发送到当前备用的 writeHost 上。
wirteType=0 所有写操作发送到第一个writeHost第一个挂了切换到第二个
switchType=3 基于MySQL Galera cluster的切换机制心跳语句为show status like 'wsrep%'
```
------
##### E启动服务
```shell
[root@mycat conf]# mycat start
Starting Mycat-server...
[root@mycat conf]# jps
1494 WrapperSimpleApp
1528 Jps
查看端口:[root@mycat conf]# ss -antpl 8066端口
客户端测试: mysql -u shop -p123456 -P 8066 -h 10.0.0.47
从服务数据验证:
```
------
#### 3.Mycat配置文件
##### server.xml
```shell
server.xml 配置文件
1.privileges标签
对用户的 schema以及表进行精细化的DML(数据操纵语言)权限控制
<privileges check="false"> </privileges> --check 表示是否开启DML权限检查。默认是关闭。
--dml 顺序说明insert,update,select,delete
<schema name="db1" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table> </schema>
db1的权限是update,select。
tb01的权限是啥都不能干。
tb02的权限是insert,update,select,delete。
其他表默认是udpate,select。
2.system标签
这个标签内嵌套的所有 property 标签都与系统配置有关。
<property name="charset">utf8</property>
字符集
<property name="processors">1</property>
处理线程数量默认是cpu数量。
<property name="processorBufferChunk">4096</property>
每次读取留的数量默认4096。
<property name="processorBufferPool">409600</property>
创建共享buffer需要占用的总空间大小。processorBufferChunk*processors*100。
<property name="processorBufferPoolType">0</property>
默认为0。0表示DirectByteBufferPool1表示ByteBufferArena。
<property name="processorBufferLocalPercent">100</property>
二级共享buffer是processorBufferPool的百分比这里设置的是百分比。
<property name="sequnceHandlerType">100</property>
全局ID生成方式。(0:为本地文件方式1:为数据库方式2:为时间戳序列方式3:为ZK生成ID4:为ZK递增ID生成。
<property name="useCompression">1</property>
是否开启mysql压缩协议。1为开启0为关闭默认关闭。
<property name="packetHeaderSize">4</property>
指定 Mysql 协议中的报文头长度。默认 4。
<property name="maxPacketSize">16M</property>
指定 Mysql 协议可以携带的数据最大长度。默认 16M。
<property name="idleTimeout">1800000</property>
指定连接的空闲超时时间。某连接在发起空闲检查下,发现距离上次使用超过了空闲时间,那么这个连接会被回收,就是被直接的关闭掉。默认 30 分钟,单位毫秒。
<property name="txIsolation">3</property>
前端连接的初始化事务隔离级别,只在初始化的时候使用,后续会根据客户端传递过来的属性对后端数据库连接进行同步。默认为 REPEATED_READ设置值为数字默认 3。
READ_UNCOMMITTED = 1;
READ_COMMITTED = 2;
REPEATED_READ = 3;
SERIALIZABLE = 4;
<property name="sqlExecuteTimeout">300</property>
SQL 执行超时的时间Mycat 会检查连接上最后一次执行 SQL 的时间,若超过这个时间则会直接关闭这连接。默认时间为 300 秒,单位秒。
<property name="processorCheckPeriod">1000</property>
清理 NIOProcessor 上前后端空闲、超时和关闭连接的间隔时间。默认是 1 秒,单
位毫秒。
<property name="dataNodeIdleCheckPeriod">300000</property>
对后端连接进行空闲、超时检查的时间间隔,默认是 300 秒,单位毫秒。
<property name="dataNodeHeartbeatPeriod">10000</property>
对后端所有读、写库发起心跳的间隔时间,默认是 10 秒,单位毫秒。
<property name="bindIp">0.0.0.0</property>
mycat 服务监听的 IP 地址,默认值为 0.0.0.0。
<property name="serverPort">8066</property>
定义 mycat 的使用端口,默认值为 8066。
<property name="managerPort">9066</property>
定义 mycat 的管理端口,默认值为 9066。
<property name="fakeMySQLVersion">5.6</property>
mycat 模拟的 mysql 版本号,默认值为 5.6 版本,如非特需,不要修改这个值,目前支持设置 5.5,5.6,5.7 版本,其他版本可能会有问题。
<property name="useSqlStat">0</property>
是否开启实时统计。1为开启0为关闭 。
<property name="useGlobleTableCheck">0</property>
是否开启全局表一致性检测。1为开启0为关闭 。
<property name="handleDistributedTransactions">0</property>
分布式事务开关。0为不过滤分布式事务1为过滤分布式事务2 为不过滤分布式事务,但是记录分布式事务日志。
<property name="maxStringLiteralLength">65535</property>
默认是65535。 64K 用于sql解析时最大文本长度
以上举例的属性仅仅是一部分,可以配置的变量很多。
System标签下的属性一般是上线后需要根据实际运行的情况分析后调优的时候进行修改。
3. Firewall标签
防火墙的设置也就是在网络层对请求的地址进行限制主要是从安全角度来保证Mycat不被匿名IP进行访问
<firewall>
<whitehost>
<host host="127.0.0.1" user="mycat"/>
<host host="127.0.0.2" user="mycat"/>
</whitehost>
<blacklist check="false">
</blacklist>
</firewall>
```
##### schema.xml
```shell
schema.xml
schema 数据库设置此数据库为逻辑数据库name与server.xml中schema对应
dataNode 分片信息,也就是分库相关配置
dataHost 物理数据库,真正存储数据的数据库
1、schema 标签
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="10"> </schema>
schema标签用来定义mycat实例中的逻辑库mycat可以有多个逻辑库每个逻辑库都有自己的相关配置。可以使用schema标签来划分这些不同的逻辑库,如果不配置schema标签所有表的配置会属于同一个默认的逻辑库。逻辑库的概念和MySql的database的概念一样我们在查询两个不同逻辑库中的表的时候需要切换到该逻辑库下进行查询。
name 逻辑数据库名与server.xml中的schema对应
checkSQLschema 数据库前缀相关设置当该值为true时例如我们执行语句select * from TESTDB.company 。mycat会把语句修改为 select * from company 去掉TESTDB。
sqlMaxLimit 当该值设置为某个数值时每条执行的sql语句如果没有加上limit语句Mycat会自动加上对应的值。不写的话默认返回所有的值。需要自己sql语句加limit。
2、dataNode标签
<dataNode name="dn1" dataHost="localhost1" database="db1" />
datanode标签定义了mycat中的数据节点也就是数据分片。一个datanode标签就是一个独立的数据分片。
localhost1数据库实例上的db1物理数据库这就组成一个数据分片最后我们用dn1来标示这个分片。
name 定义数据节点的名字这个名字需要唯一。我们在table标签上用这个名字来建立表与分片对应的关系
dataHost 用于定义该分片属于哪个数据库实例属性与datahost标签上定义的name对应
database 用于定义该分片属于数据库实例上 的具体库。
3、dataHost标签
这个标签直接定义了具体数据库实例,读写分离配置和心跳语句。
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.1.100:3306" user="root" password="123456">
<readHost host="hostS1" url="192.168.1.101:3306" user="root" password="123456" />
</writeHost>
</dataHost>
name 唯一标示dataHost标签供上层使用
maxCon 指定每个读写实例连接池的最大连接。
minCon 指定每个读写实例连接池的最小连接,初始化连接池的大小
balance 负载均称类型
balance=“0”不开启读写分离机制所有读操作都发送到当前可用的writeHost上
balance=“1”全部的readHost与stand by writeHost参与select语句的负载均衡简单的说当双主双从模式M1-S1M2-S2 并且M1 M2互为主备正常情况下M2,S1,S2都参与select语句的负载均衡。
balance=“2”所有读操作都随机的在writeHost、readHost上分发
balance=“3”所有读请求随机的分发到writeHst对应的readHost执行writeHost不负担读写压力。
writeType 负载均衡类型。
writeType=“0”, 所有写操作发送到配置的第一个 writeHost第一个挂了切到还生存的第二个writeHost重新启动后已切换后的为准切换记录在配置文件中:dnindex.properties .
writeType=“1”所有写操作都随机的发送到配置的 writeHost。1.5以后版本废弃不推荐。
switchType -1不自动切换
1 默认值 自动切换
2 基于MySql主从同步的状态决定是否切换心跳语句为 show slave status
3 基于mysql galary cluster 的切换机制(适合集群) 心跳语句为 show status like wsrep%
dbType 指定后端链接的数据库类型目前支持二进制的mysql协议还有其他使用jdbc链接的数据库例如mongodboraclespark等
dbDriver 指定连接后段数据库使用的driver目前可选的值有native和JDBC。使用native的话因为这个值执行的是二进制的mysql协议所以可以使用mysql和maridb其他类型的则需要使用JDBC驱动来支持。
如果使用JDBC的话需要符合JDBC4标准的驱动jar 放到mycat\lib目录下并检查驱动jar包中包括如下目录结构文件 META-INF\services\java.sql.Driver。 在这个文件写上具体的driver类名例如com.mysql.jdbc.Driver
writeHost readHost指定后端数据库的相关配置给mycat用于实例化后端连接池。
tempReadHostAvailable
如果配置了这个属性 writeHost 下面的 readHost 仍旧可用,默认 0 可配置0、1
1heartbeat标签
这个标签内指明用于和后端数据库进行心跳检查的语句。
例如MYSQL 可以使用 select user()Oracle 可以使用 select 1 from dual 等。
2) writeHost /readHost 标签
这两个标签都指定后端数据库的相关配置用于实例化后端连接池。唯一不同的是writeHost 指定写实例、readHost 指定读实例。
在一个 dataHost 内可以定义多个 writeHost 和 readHost。但是如果 writeHost 指定的后端数据库宕机,那么这个 writeHost 绑定的所有 readHost 都将不可用。
另一方面,由于这个 writeHost 宕机,系统会自动的检测到,并切换到备用的 writeHost 上去。这两个标签的属性相同,这里就一起介绍。
host 用于标识不同实例,一般 writeHost 我们使用M1readHost 我们用S1。
url 后端实例连接地址。Native地址端口 JDBCjdbc的url
password 后端存储实例需要的密码
user 后端存储实例需要的用户名字
weight 权重 配置在 readhost 中作为读节点的权重
usingDecrypt 是否对密码加密默认0。
```