mysql日志和备份高级语言

日志

MySQL 的日志默认保存位置为 /usr/local/mysql/data

1日志类型与作用:

1.redo 重做日志:达到事务一致性(每次重启会重做)
作用:确保日志的持久性,防止在发生故障,脏页未写入磁盘。重启数据库会进行redo log执行重做,达到事务一致性

2.undo 回滚日志

作用:保证数据的原子性,记录事务发生之前的一个版本,用于回滚,innodb事务可重复读和读取已提交 隔离级别就是通过mvcc+undo实现

3.errorlog 错误日志
作用:Mysql本身启动,停止,运行期间发生的错误信息

  1. slow query log 慢查询日志
    作用:记录执行时间过长的sql,时间阈值(10s)可以配置,只记录执行成功
    另一个作用:在于提醒优化

  2. bin log 二进制日志
      作用:用于主从复制,实现主从同步
    记录的内容是:数据库中执行的sql语句

6.relay log 中继日志

作用:用于数据库主从同步,将主库发来的bin log保存在本地,然后从库进行回放

  1. general log 普通日志
      作用:记录数据库的操作明细,默认关闭,开启后会降低数据库性能
mysql -u root -P
show variables like 'general%';       #查看通用查询日志是否开启
show variables like 'log_bin%';       #查看二进制日志是否开启
show variables like '%slow%';         #查看慢查询日功能是否开启
show variables like 'long_query_time';    #查看慢查询时间设置
set global slow_query_log=ON;         #在数据库中设置开启慢查询的方法

PS: variables 表示变量 like 表示模糊查询



##配置文件
vim /etc/my.cnf
[mysqld]
##错误日志,用来记录当MySQL启动、停止或运行时发生的错误信息,默认已开启
log-error=/usr/local/mysql/data/mysql_error.log     #指定日志的保存位置和文件名

##通用查询日志,用来记录MySQL的所有连接和语句,默认是关闭的
general_log=ON
general_log_file=/usr/local/mysql/data/mysql_general.log

##二进制日志(binlog),用来记录所有更新了数据或者已经潜在更新了数据的语句,记录了数据的更改,可用于数据恢复,默认已开启
log-bin=mysql-bin      
或
log_bin=mysql-bin

##慢查询日志,用来记录所有执行时间超过long_query_time秒的语句,可以找到哪些查询语句执行时间长,以便提醒优化,默认是关闭的
s1ow_query_log=ON
slow_query_log_file=/usr/local/mysql/data/mysql_slow_query.log
long_query_time=5        #设置超过5秒执行的语句被记录,缺省时为10秒

##复制段
log-error=/usr/local/mysql/data/mysql_error.log
general_log=ON
general_log_file=/usr/local/mysql/data/mysql_general.log
log-bin=mysql-bin
slow_query_log=ON
slow_query_log_file=/usr/local/mysql/data/mysql_slow_query.log
long_query_time=5


systemctl restart mysqld


#xxx(字段)
xxx% 以xxx为开头的字段
%xxx 以xxx为结尾的字段
%xxx% 只要出现xxx字段的都会显示出来
xxx   精准查询

#二进制日志开启后,重启mysql 会在目录中查看到二进制日志
cd /usr/local/mysql/data
ls
mysql-bin.000001		#开启二进制日志时会产生一个索引文件及一个索引列表

索引文件:记录更新语句
索引文件刷新方式:
1、重启mysql的时候会更新索引文件,用于记录新的更新语句
2、刷新二进制日志

mysql-bin.index:
二进制日志文件的索引

备份

1为什么要备份

灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击、误操作测试等数据丢失场景

2备份类型

完全备份,部分备份

完全备份:整个数据集

部分备份:只备份数据子集,如部分库或表

完全备份、增量备份、差异备份

增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较

快,还原复杂

冷、温、热备份
冷备:读、写操作均不可进行,数据库停止服务
温备:读操作可执行;但写操作不可执行
热备:读、写操作均可执行
 MyISAM:温备,不支持热备
 InnoDB:都支持
 
物理和逻辑备份
物理备份:直接复制数据文件进行备份,与存储引擎有关,占用较多的空间,速度快
逻辑备份:从数据库中“导出”数据另存而进行的备份,与存储引擎无关,占用空间少,速度慢,可
能丢失精度

3实际操作

3.1 冷备份:

环境准备:
use kgc;
create table if not exists info1 (
id int(4) not null auto_increment,
name varchar(10) not null,
age char(10) not null,
hobby varchar(50),
primary key (id));

insert into info1 values(1,'user1',20,'running');
insert into info1 values(2,'user2',30,'singing');

InnoDB 存储引擎的数据库在磁盘上存储成三个文件: db.opt(表属性文件)、表名.frm(表结构文件)、表名.ibd(表数据文件)。

1.物理冷备份与恢复
systemctl stop mysqld
yum -y install xz
#压缩备份
tar Jcvf /opt/mysql_all_$(date +%F).tar.xz /usr/local/mysql/data/
mv /usr/local/mysql/data/ /opt/
#解压恢复
tar Jxvf /opt/mysql_all_2020-11-22.tar.xz -C /usr/local/mysql/data/
cd /usr/local/mysql/data
mv /usr/local/mysql/data/* ./
注意是移动不是复制,复制貌似会无法启动mysql,复制注意权限问题。



2. mysqldump 备份与恢复(温备份)
(1)、完全备份一个或多个完整的库 (包括其中所有的表)
mysqldump -uroot -p[密码] --databases 库名1 [库名2] ... > /备份路径/备份文件名.sql    #导出的就是数据库脚本文件
例:
mysqldump -u root -p --databases kgc > /opt/kgc.sql       
#备份一个kgc库
mysqldump -u root -p --databases mysql kgc > /opt/mysql-kgc.sql    
#备份mysql与 kgc两个库

(2)、完全备份 MySQL 服务器中所有的库
mysqldump -u root -p[密码] --all-databases > /备份路径/备份文件名.sql
例:
mysqldump -u root -p --all-databases > /opt/all.sql

(3)、完全备份指定库中的部分表
mysqldump -u root -p[密码] 库名 [表名1] [表名2] ... > /备份路径/备份文件名.sql
例:
mysqldump -u root -p [-d] kgc info1 info2 > /opt/kgc_info1.sql
#使用“-d”选项,说明只保存数据库的表结构
#不使用“-d"选项,说明表数据也进行备份
#做为一个表结构模板

(4)查看备份文件
grep -v "^--" /opt/kgc_info1.sql | grep -v "^/" | grep -v "^$"

3.2 mysqldump 备份与恢复


完全备份一个或多个完整的库 (包括其中所有的表)
mysqldump -u root -p[密码] --databases 库名1 [库名2] ... > /备份路径/备份文件名.sql    #导出的就是数据库脚本文件
例:
mysqldump -u root -p --databases kgc > /opt/kgc.sql       
#备份一个kgc库
mysqldump -u root -p --databases mysql kgc > /opt/mysql-kgc.sql    
#备份mysql与 kgc两个库

(2)、完全备份 MySQL 服务器中所有的库
mysqldump -u root -p[密码] --all-databases > /备份路径/备份文件名.sql
例:
mysqldump -u root -p --all-databases > /opt/all.sql

(3)、完全备份指定库中的部分表
mysqldump -u root -p[密码] 库名 [表名1] [表名2] ... > /备份路径/备份文件名.sql
例:
mysqldump -u root -p [-d] kgc info1 info2 > /opt/kgc_info1.sql
#使用“-d”选项,说明只保存数据库的表结构
#不使用“-d"选项,说明表数据也进行备份
#做为一个表结构模板

(4)查看备份文件
grep -v "^--" /opt/kgc_info1.sql | grep -v "^/" | grep -v "^$



mysql 完全恢复
模拟删库
drop database 库名;

mysql -u root -p123123 < /backup/bbs.sql
#恢复数据库操作

#恢复数据表
当备份文件中只包含表的 备份时,而不包含创建库时的语句,执行操作时必须指定库名,且目标库必须存在。

mysqldump -u root -p123123 kgc info > /backup/kgc_info.sql
#只备份表

drop database kgc;
 
create database kgc;

mysql -u root -p123123 kgc < /backup/kgc_info.sql
#######恢复表时需要指定对应的库##########

3.3增量备份与恢复

MySQL数据库增量恢复
1.一般恢复

将所有备份的二进制日志内容全部恢复

2.基于位置恢复

数据库在某一时间点可能既有错误的操作也有正确的操作
可以基于精准的位置跳过错误的操作
发生错误节点之前的一个节点,上一次正确操作的位置点停止

3.基于时间点恢复

跳过某个发生错误的时间点实现数据恢复
在错误时间点停止,在下一个正确时间点开始



一、增备实验
1.开启二进制日志功能
vim /etc/my.cnf
[mysqld]
log-bin=mysql-bin
binlog_format = MIXED      #可选,指定二进制日志(binlog)的记录格式为MIXED(混合输入)
server-id = 1              #可加可不加该命令

#二进制日志(binlog)有3种不同的记录格式: 
#STATEMENT (基于SQL语句)、
#ROW(基于行)、
#MIXED(混合模式),
#默认格式是STATEMENT

[root@localhost backup]#ls /usr/local/mysql/data
#二进制日志位置


2 可以每周对数据库或表进行完全备份
mysqldump -uroot -p123123 kgc info >/backup/kgc_info.sql
mysqldump -uroot -p123123 --all-databases  >/backup/kgc_info.sql

3.可以每天进行增量备份操作,生成新的二进制文件(mysql-bin.000002)
mysqladmin -uroot -p123123 -p flush-logs


4插入新数据
use info 
insert into info values(2,'gk',22);
insert into info values(3,'jk',23);

5再次生成新的二进制日志文件
mysqladmin -uroot -p123123  flush-logs
#之前的操作会保存在上一个二进制文件中,之后的操作会保存在新的二进制文件中

6.查看二进制日志文件
cp /usr/loacal/mysql/data/mysql-bin.000002 /opt/
mysqlbinlog --no-defaults --base64-output=decode-rows -v /opt/mysql-bin.000002


增量恢复:
1模拟丢失文件
delete from info where id=1;
mysqlbinlog --no-defaults /opt/mysql-bin.000002 |mysql -u -root -p123123


3.3-1增量备份与恢复

实际操作

#首先修改配置文件启用二进制日志
[root@localhost ~]#vim /etc/my.cnf
#修改二进制日志文件
[mysqld]
log-bin=mysql-bin
binlog_format = MIXED 

[root@localhost ~]#systemctl restart mysqld.service
#重启服务
root@localhost ~]#ls /usr/local/mysql/data/
#查看日志文件是否生成 mysql-bin.000001
auto.cnf  ib_buffer_pool  ib_logfile0  ibtmp1  mysql-bin.000001  performance_schema
bbs       ibdata1         ib_logfile1  mysql   mysql-bin.index   sys

[root@localhost ~]#mysql -uroot -p123123
#进入数据库创建环境
mysql> create database ky15;
#创建数据库 ky15
mysql> use ky15
#进入数据库 ky15
mysql> create table info (id int , name char(20),age int,address char(50),hobby char(50));
mysql> desc info;
#查看表结构
+---------+----------+------+-----+---------+-------+
| Field   | Type     | Null | Key | Default | Extra |
+---------+----------+------+-----+---------+-------+
| id      | int(11)  | YES  |     | NULL    |       |
| name    | char(20) | YES  |     | NULL    |       |
| age     | int(11)  | YES  |     | NULL    |       |
| address | char(50) | YES  |     | NULL    |       |
| hobby   | char(50) | YES  |     | NULL    |       |
+---------+----------+------+-----+---------+-------+
5 rows in set (0.00 sec)
mysql> insert into info values(1,'jk',18,'南京','吃饭');
mysql> insert into info values(2,'ll',19,'北京','跳舞');
#插入数据
mysql> select * from info;
+------+------+------+---------+--------+
| id   | name | age  | address | hobby  |
+------+------+------+---------+--------+
|    1 | jk   |   18 | 南京    | 吃饭   |
|    2 | ll   |   19 | 北京    | 跳舞   |
+------+------+------+---------+--------+
2 rows in set (0.00 sec)


mkdir /backup
#创建存放备份文件的目录
mysqldump -uroot -p123123 ky15 info > /backup/ky15_info.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
#备份ky15 下的info表
mysqladmin -uroot -p123123 flush-logs
#刷新日志
ls /usr/local/mysql/data/
#查看是否生成了新的 二进制日志
auto.cnf  ib_buffer_pool  ib_logfile0  ibtmp1  mysql             mysql-bin.000002  performance_schema
bbs       ibdata1         ib_logfile1  ky15    mysql-bin.000001  mysql-bin.index   sys

#数据库中插入新的文件
mysql> use ky15
#进入数据库 ky15
mysql> insert into info values(3,'lili',23,'北京','唱歌');
Query OK, 1 row affected (0.00 sec)
mysql> insert into info values(4,'lihua',23,'北京','骂人');
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;
+------+-------+------+---------+--------+
| id   | name  | age  | address | hobby  |
+------+-------+------+---------+--------+
|    1 | jk    |   18 | 南京    | 吃饭   |
|    2 | ll    |   19 | 北京    | 跳舞   |
|    3 | lili  |   23 | 北京    | 唱歌   |
|    4 | lihua |   23 | 北京    | 骂人   |
+------+-------+------+---------+--------+
4 rows in set (0.00 sec)


cat /usr/local/mysql/data/mysql-bin.000002 
mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql-bin.000002
#查看日志文件

mysql> drop database ky15;
Query OK, 1 row affected (0.00 sec)                        
#模拟删库

mysql> create database ky15;


mysql -uroot -p123123 ky15 < ky15_info.sql 
mysql: [Warning] Using a password on the command line interface can be insecure.
#恢复表

mysql> show tables;
mysql> select * from info;
+------+------+------+---------+--------+
| id   | name | age  | address | hobby  |
+------+------+------+---------+--------+
|    1 | jk   |   18 | 南京    | 吃饭   |
|    2 | ll   |   19 | 北京    | 跳舞   |
+------+------+------+---------+--------+
2 rows in set (0.00 sec)


mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000002 |mysql -uroot -p123123
mysql: [Warning] Using a password on the command line interface can be insecure.
#恢复 增量备份

mysql> select * from info;
+------+-------+------+---------+--------+
| id   | name  | age  | address | hobby  |
+------+-------+------+---------+--------+
|    1 | jk    |   18 | 南京    | 吃饭   |
|    2 | ll    |   19 | 北京    | 跳舞   |
|    3 | lili  |   23 | 北京    | 唱歌   |
|    4 | lihua |   23 | 北京    | 骂人   |
+------+-------+------+---------+--------+
4 rows in set (0.00 sec)

3.4断点恢复

基于位置恢复

删除库中的数据
mysql> delete from info where id=3;
Query OK, 1 row affected (0.01 sec)

mysql> delete from info where id=4;
Query OK, 1 row affected (0.00 sec)


mysql> select * from info;
+------+------+------+---------+--------+
| id   | name | age  | address | hobby  |
+------+------+------+---------+--------+
|    1 | jk   |   18 | 南京    | 吃饭   |
|    2 | ll   |   19 | 北京    | 跳舞   |
+------+------+------+---------+--------+
2 rows in set (0.00 sec)

只恢复其中之一
[root@localhost backup]#mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql-bin.000002 >/backup/mysqlbin.log
#查看 相关的序号

[root@localhost backup]#mysqlbinlog --no-defaults --stop-position='601' /usr/local/mysql/data/mysql-bin.000002 |mysql -uroot -p123123
#从头开始  到601结束
mysql> select * from info;
+------+------+------+---------+--------+
| id   | name | age  | address | hobby  |
+------+------+------+---------+--------+
|    1 | jk   |   18 | 南京    | 吃饭   |
|    2 | ll   |   19 | 北京    | 跳舞   |
|    3 | lili |   23 | 北京    | 唱歌   |
+------+------+------+---------+--------+
3 rows in set (0.00 sec)

[root@localhost backup]#mysqlbinlog --no-defaults --start-position='601' /usr/local/mysql/data/mysql-bin.000002 |mysql -uroot -p123123
mysql: [Warning] Using a password on the command line interface can be insecure.
#从601 开始

mysql> select * from info;
+------+-------+------+---------+--------+
| id   | name  | age  | address | hobby  |
+------+-------+------+---------+--------+
|    1 | jk    |   18 | 南京    | 吃饭   |
|    2 | ll    |   19 | 北京    | 跳舞   |
|    4 | lihua |   23 | 北京    | 骂人   |
+------+-------+------+---------+--------+
3 rows in set (0.00 sec)


基于时间点

#格式只将position 改为datetime 时间日期 格式  年-月-日 时:分:秒
[root@localhost backup]#mysqlbinlog --no-defaults --start-datetime='2021-11-29 14:31:14' /usr/local/mysql/data/mysql-bin.000002 |mysql -uroot -p123123
mysql: [Warning] Using a password on the command line interface can be insecure.

  

SQL 高级语言

1导入数据库

mysql> source /backup/hellodb_innodb.sql;
#将脚本导入  source  加文件路径

2. select

显示表格中的一个或者多个字段中所有的信息
语法:
select 字段名  from 表名;
例子
select * from info;
select name from info;
select name,id,age from info;

3. distinct

distinct 查询不重复记录
中文含义:/dɪˈstɪŋkt/ 不同的 明显的
语法:
select distinct 字段 from 表名﹔

例子:
select distinct age from students;
#去除年龄字段中重复的
select distinct gender from students;
#查找性别

4. where

where 有条件的查询
语法:select '字段' from 表名  where 条件

select name,age from students where age < 20;
#显示name和age 并且要找到age 小于20的

5.and;or

and 且           or  或
语法:
select 字段名  from 表名 where 条件1 (and|or) 条件2 (and|or)条件3;

例子:
select name,age from students where 30 > age and age > 20;
select name,age,classid from students where 30 > age and age > 20 and classsid=3;
select name,age from students where gender='m' or(30 > age and age > 20);
#男的 或 30到20岁之间  

6.in

in:
显示已知值的数值
语法:
select 字段名  from 表名 where 字段 in ('值1','值2'....);
例子:
select * from students where StuID in (1,2,3,4);
select * from students where ClassID in (1,4);

7.between

between:
显示两个值范围内的资料
语法:
select 字段名  from 表名 where 字段 between  '值1' and '值2';
包括 and两边的值
例子:
select * from students where name between 'ding dian' and 'ling chong';
# 一般不使用在字符串上
select * from students where stuid between 2 and 5;
#id 2到5 的信息 包括2和5
select * from students where age between '22' and '30';
#不需要表中一定有该字段,只会将22 到30 已有的都显示出来

8. like 通配符模糊查询

通配符通常是和  like 一起使用
语法:
select 字段名  from 表名 where 字段 like 模式

select * from students where name like 's%';
select * from students where name like '%on%';

通配符 含义
% 表示零个,一个或者多个字符
_ 下划线表示单个字符
A_Z 所有以A开头 Z 结尾的字符串 ‘ABZ’ ‘ACZ’ 'ACCCCZ’不在范围内 下划线只表示一个字符 AZ 包含a空格z
ABC% 所有以ABC开头的字符串 ABCD ABCABC
%CBA 所有以CBA结尾的字符串 WCBA CBACBA
%AN% 所有包含AN的字符串 los angeles
_AN% 所有 第二个字母为 A 第三个字母 为N 的字符串

9. order by

order by 按关键字排序
语法:
select 字段名  from 表名 where 条件 order by 字段 [asc,desc];
默认 asc 正向排序
desc 反向排序

select age,name from students order by age;
#正向排序

select name,age from info order by age desc;
#反向排序

可以加上where
select name,age from students where classid=3 order by age;
#显示 name和age字段的数据  并且只显示classid字段为3 的 并且以age字段排序

10.函数

10.1 数学函数

函数 含义
abs(x) 返回x 的 绝对值 |+ -1| = 1
rand() 返回0到1的随机数
mod(x,y) 返回x除以y以后的余数 x 除以 y 的值 取余
power(x,y) 返回x的y次方 x是底数 y是次方
round(x) 返回离x最近的整数 round(1.4) 取1 round(1.5)2
round(x,y) 保留x的y位小数四舍五入后的值round(3.1415926,5) 3.14159
sqrt(x) 返回x的平方根 4 2
truncate(x,y) 返回数字 x 截断为 y 位小数的值 truncate(3.1415926345,3); 3.141直接截断
ceil(x) 返回大于或等于 x 的最小整数 正整数就返回本身 小数就整数加一
floor(x) 返回小于或等于 x 的最大整数 就是整数本身
greatest(x1,x2…) 返回返回集合中最大的值
least(x1,x2…) 返回返回集合中最小的值

例子:

select abs(-1);
select rand();
select mod(6,4);
select power(2,2);
select round(2.5);
select round(3.1415926345,3);
select truncate(3.1415926345,3);
select ceil(2.6);
select floor(2.4);
select least(22,33,44);
select greatest(55,66,88);

10.2 聚合函数

函数 含义
avg() 返回指定列的平均值
count() 返回指定列中非 NULL 值的个数 空值返回
min() 返回指定列的最小值
max() 返回指定列的最大值
sum(x) 返回指定列的所有值之和

例子:

语法:
select 函数(字段) from  表名;

select avg(age) from students;
#求表中年龄的平均值
select sum(age) from students;
#求表中年龄的总和
select max(age) from students;
#求表中年龄的最大值
select min(age) from students;
#求表中年龄的最小值
select count(classid) from students;
#求表中有多少非空记录
select count(distinct gender) from students;

select count(*) from students;

insert into test values ('');
#加入null值

insert into test values(null);
select count(name) from test;

如果某表只有一个字段使用*不会忽略 null
如果count后面加上明确字段会忽略 null


select sum(age) from students where classid is Null;
#查询空值

#####思考空格字符 会被匹配么?########

insert into students values(26,' ',22,'m',3,1);

select count(name) from students;
+-------------+
| count(name) |
+-------------+
|          27 |
+-------------+
空格字符是会被匹配的。

10.3 字符串函数

函数 描述
trim() 返回去除指定格式的值
concat(x,y) 将提供的参数 x 和 y 拼接成一个字符串
substr(x,y) 获取从字符串 x 中的第 y 个位置开始的字符串,跟substring()函数作用相同
substr(x,y,z) 获取从字符串 x 中的第 y 个位置开始长度为z 的字符串
length(x) 返回字符串 x 的长度
replace(x,y,z) 将字符串 z 替代字符串 x 中的字符串 y
upper(x) 将字符串 x 的所有字母变成大写字母
lower(x) 将字符串 x 的所有字母变成小写字母
left(x,y) 返回字符串 x 的前 y 个字符
right(x,y) 返回字符串 x 的后 y 个字符
repeat(x,y) 将字符串 x 重复 y 次
space(x) 返回 x 个空格
strcmp(x,y) 比较 x 和 y,返回的值可以为-1,0,1
reverse(x) 将字符串 x 反转

例子

#trim:
语法:
select trim (位置 要移除的字符串 from 原有的字符串) #区分大小写
其中位置的值可以是 
leading(开始) 
trailing(结尾)
both(起头及结尾)
要移除的字符串:从字符串的起头、结尾或起头及结尾移除的字符串,缺省时为空格。#区分大小写
select trim(leading 'Sun' from 'Sun Dasheng');
select trim(both  from ' Sun Dasheng      ');
#去除空格

#length:
语法:select length(字段) from 表名;
#可以在函数前再加字段
select name,length(name) from students;
#计算出字段中记录的字符长度

#replace(替换)
语法:select replace(字段,'原字符''替换字符') from 表名;
select replace(name,'ng','gl') from students;
#把ng换成gl

#concat:
语法:select concat(字段1,字段2)from 表名
#如有任何一个参数为NULL ,则返回值为 NULL          
select concat(name,classid) from students;
elect concat(name,classid) from students where classid=3;
select name || classid from students where classid=3;
select concat(name,'\t',classid) from students where classid=3;
select concat(classid,name) from students order by classid;

#substr:               
语法:select substr(字段,开始截取字符,截取的长度)  where 字段='截取的字符串'               
select substr(name,6) from students where name='Sun Dasheng';
#从第六个开始保留 (包括第六个)
select substr(name,6,2) from students where name='Sun Dasheng';

11 group by

group by:
对group by  后面的字段的查询结果进行汇总分组,通常是结合聚合函数一起使用的
group by    有一个原则,就是select 后面的所有列中,没有使用聚合函数的列必须出现在 group by 的后面。

语法:
select 字段1,sum(字段2) from 表名 group by 字段1;

例子:
select classid,sum(age) from students group by classid;
#求各个班的年龄总和
select classid,avg(age) from students group by classid;
#求平均年龄
select classid,count(age) from students group by classid;

12 having

having:用来过滤由group by语句返回的记录集,通常与group by语句联合使用
having 语句的存在弥补了where关键字不能与聚合函数联合使用的不足。如果被SELECT的只有函数栏,那就不需要GROUP BY子句。
语法:SELECT 字段1,SUM("字段")FROM 表格名 GROUP BY 字段1 having(函数条件);

select classid,avg(age) from students group by classid where age > 30;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where age > 30' at line 1

select classid,avg(age) from students group by classid having age > 30;
ERROR 1054 (42S22): Unknown column 'age' in 'having clause'

select classid,avg(age) from students group by classid having avg(age) > 30;


要根据新表中的字段 来制定条件

13 别名

在 MySQL 查询时,当表的名字比较长或者表内某些字段比较长时,为了方便书写或者 
多次使用相同的表,可以给字段列或表设置别名。使用的时候直接使用别名,简洁明了,增强可读性
语法
对于字段的别名:
select 原字段 as 修改字段,原字段 as 修改字段 from 表名 ;
#as 可以省略。
例子:
select s.name as n, s.stuid as id from students s;
#对于列的别名

#如果表的长度比较长,可以使用 AS 给表设置别名,在查询的过程中直接使用别名临时设置info的别名为i
对于表的别名:
select 表格别名.原字段 as 修改字段[,表格别名.原字段 as 修改字段]from 原表名 as 表格别名 ;
#as可以省略

select avg(age) '平均值' from students;
#将聚合函数字段 设置成平均值


使用场景:
1、对复杂的表进行查询的时候,别名可以缩短查询语句的长度
2、多表相连查询的时候(通俗易懂、减短sql语句长度)

此外,AS 还可以作为连接语句的操作符。
创建t1表,将info表的查询记录全部插入t1表

create table test as select * from students;
#可以使用as直接创建,不继承 特殊键

create table test2 (select * from students);
#或者不继承 特殊键
create table test2 like students;
#继承特殊键

14 子查询

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dCxZCIzj-1640048934875)(日志和备份.assets/image-20211201003447788.png)]

子查询也被称作内查询或者嵌套查询,是指在一个查询语句里面还嵌套着另一个查询语句。
子查询语句是先于主查询语句被执行的,其结果作为外层的条件返回给主查询进行下一 步的查询过滤。
#子查询:在SQL语句嵌套着查询语句,性能较差,基于某语句的查询结果再次进行的查询
语法:
select 字段 from 表1 where 字段2 [比较运算符] (select 字段1 from 表格2 where 条件)
#比较运算符 可以是 =  >  <  >= <= 也可以是文字运算符 like in between

例子:
select name,age from students where age in (select age from students where age>30);
#同一表中
select * from teachers where tid in (select teacherid from students where teacherid<3);
#显示s 表中 老师id小于3的

select avg(age) from students;
#计算平均年龄
select * from teachers where age > (select avg(age) from students);
#找到大于平均年龄的人
update students set teacherid=2 where stuid=6;
#更新数据再试一次

update teachers set age=(select avg(age) from students) where tid=4;

select name,age from students where age> (select avg(age) from teachers);
#显示 students 表中 name和age 字段中大于  teachers表中的平均值 






select * from students inner join teachers on students.teacherid=teachers.tid;

15 exists

这个关键字在子查询时,主要用于判断子查询的结果集是否为空。如果不为空, 则返回 TRUE;反之,则返回 FALSE

select * from teachers where tid in (select teacherid from students where teacherid<3);

select * from teachers where  exists (select teacherid from students where teacherid<1);

16 连接查询

inner join on(内连接)只返回两个表中联结字段的相等的行
left join on(左连接): 返回包括左表中的所有记录和右表中联结字段相等的记录
right join on(右连接): 返回包括右表中的所有记录和左表中联结字段相等的记录

语法:
select 字段 from 表1 inner join 表2 on 条件
select 字段 from 表1 left join 表2 on 条件
select 字段 from 表1 right join 表2 on 条件

例子:
#内连接:
select * from teachers inner join students on students.teacherid=teachers.tid;
#显示 teacher表的所有字段,采用内连接  要求 teacgerid=tid
select * from teachers t inner join students  s on s.teacherid=t.tid;

select * from students , teachers where students.teacherid=teachers.tid;
select * from students s ,teachers  t where s.teacherid=t.tid;

#左连接
select * from students s left join teachers  t on s.teacherid=t.tid;
#右连接
select * from teachers t right join students  s on s.teacherid=t.tid;
 显示内容:
 students表是 全部  teacherid 有1 2 3 4
 teachers表是 teacherid=tid 只显示 tid=1 2 3 4     上面没有5  所以xiaolongnv 不显示

17视图

---- CREATE VIEW ----视图,可以被当作是虚拟表或 存储查询结果的表。
#视图跟表格的不同是,表格中有实际储存资料,而视图是建立在表格之上的一个架构,它本身并不实际储存资料。

#临时表在用户退出出或同步数据库的连接断开后就自动消失了,而视图不会消失。

视图不含有数据,只存储它的定义,它的用途一般可以简化复杂的查询。
比如你要对几个表进行连接查询,而且还要进行统计排序等操作,写SQL语句会很麻烦的,
用视图将几个表联结起来,然后对这个视图进行查询操作,就和对一个表查询一样,很方便。

语法:
create view “视图表名” as select 语句;

例子:
create view v_test as select t.name from teachers t inner join students s on s.teacherid=t.tid;

查看视图表
show tables;

删除视图表
drop view 视图名字


视图表 本身并不实际存储数据  只是保存一个select语句查询结果

18 联集

---- UNION ----
联集,将两个sQL语句的结果合并起来,两个sqL语句所产生的字段需要是同样的数据类型;
UNION:生成结果的资料值将没有重复,且按照字段的顺序进行排序
语法:select 语句1 union select 语句2

select 语句1 union all select 语句2

例子:
select * from teachers union select stuid,name,age,gender from students;
#合并
select * from teachers union select name,stuid,age,gender from students;

注意 字段 数据类型 要一致  int和int   char和char 

19 case

是sql 用来 作为 if-then-else 之类的关键字
语法:
select 
需要显示的字段名1 '可以自定义',
需要显示的字段名2 '可以自定义',
case 
when 条件1 then 结果1
when 条件2 then 结果2
else 
end '显示结果的字段名'
条件可以是一个 数值 或是公式 else 子句 不是必须的
mysql> select                      #语法
    -> name '名字',                #需要显示的字段
    -> age '年龄',                 #需要显示的字段
    -> case 					  #语法
    -> when age < 18 then '少年'   #条件
    -> when age < 30 then '青年'   #条件
    -> when age < 45 then '中年'  #条件
    -> else '老年'                #条件
    -> end '状态'                 #显示结果的字段名
    -> from students;


例1:
select name,
case
when age <18 then '未成年'
when age >=18 then '成年'
end '是否成年' 
from students;

例2:
select 
*,
case
when gender='m' then '男' 
when gender='f' then '女'  
end '性别' from students;

20 日期时间函数

字符串函数 描述
curdate() 返回当前时间的年月日
curtime() 返回当前时间的时分秒
now() 返回当前时间的日期和时间
month(x) 返回日期 x 中的月份值
week(x) 返回日期 x 是年度第几个星期
hour(x) 返回 x 中的小时值
minute(x) 返回 x 中的分钟值
second(x) 返回 x 中的秒钟值
dayofweek(x) 返回 x 是星期几,1 星期日,2 星期一
dayofmonth(x) 计算日期 x 是本月的第几天
dayofyear(x) 计算日期 x 是本年的第几天
select curdate();
#当前日期
select curtime();
#当前时间的 时分秒
select now();
#当前时间 年月日时分秒
select month('2021-08-11');
#返回月份
select week('2021-12-02');
#返回一年中的第几天
select hour('2021-12-02 14:18');
#返回小时值
select minute('2021-12-05 14:30:9');
#返回分钟的值
select second()
#返回秒值
select dayofweek('2021-12-05');
#返回星期几
select dayofmonth('2021-12-05');
#返回月中某天的值
select dayofyear('2021-12-05');
#返回一年中的 第几天

21 空值和无值

NULL
值和空值有什么区别呢?二者的区别如下:
空值的长度为 0,不占用空间的;而 NULL 值的长度是 NULL,是占用空间的。
IS NULL 或者 IS  NOT NULL,是用来判断字段是不是为 NULL 或者不是 NULL,不能查出是不是空值的。
空值的判断使用=’’或者<>’’来处理。
在通过 count()计算有多少记录数时,如果遇到 NULL 值会自动忽略掉,遇到空值会加入到记录中进行计算。

mysql> select length(null),length(' '),length('abc');
+--------------+-------------+---------------+
| length(null) | length(' ') | length('abc') |
+--------------+-------------+---------------+
|         NULL |           1 |             3 |
+--------------+-------------+---------------+

mysql> select length(null),length(''),length('abc');
+--------------+------------+---------------+
| length(null) | length('') | length('abc') |
+--------------+------------+---------------+
|         NULL |          0 |             3 |
+--------------+------------+---------------+
1 row in set (0.00 sec)

select * from students where name is not null;
select * from students where teacherid is null;

22 regexp正则表达式

匹配模式 描述 实例
^ 匹配文本的开始字符 ‘^bd’ 匹配以 bd 开头的字符串
$ 匹配文本的结束字符 ‘qn$’ 匹配以 qn 结尾的字符串
. 匹配任何单个字符 ‘s.t’ 匹配任何s 和t 之间有一个字符的字符串
* 匹配零个或多个在它前面的字符 ‘fo*t’ 匹配 t 前面有任意个 o
+ 匹配前面的字符 1 次或多次 ‘hom+’ 匹配以 ho 开头,后面至少一个m 的字符串
字符串 匹配包含指定的字符串 ‘clo’ 匹配含有 clo 的字符串
p1|p2 匹配 p1 或 p2 ‘bg|fg’ 匹配 bg 或者 fg
[…] 匹配字符集合中的任意一个字符 ‘[abc]’ 匹配 a 或者 b 或者 c
[^…] 匹配不在括号中的任何字符 [^ab] 匹配不包含 a 或者 b 的字符串
{n} 匹配前面的字符串 n 次 ‘g{2}’ 匹配含有 2 个 g 的字符串
{n,m} 匹配前面的字符串至少 n 次,至多m 次 f{1,3}’ 匹配 f 最少 1 次,最多 3 次
select id,name from info where name regexp '^sh';
#查询以sh开头的学生信息
select id,name from info where name regexp 'n$';
#查询以n结尾的学生信息
select id,name from info where name regexp 'an';
#查询名字中包含an的学生信息
select id,name from info where name regexp 'tangy.n';
#查询名字是tangy开头,n结尾,中间不知道是一个什么字符的学生信息
select id,name from info where name regexp 'an|zh';
#查询名字中包含an或者zh的学生信息
select id,name from info where name regexp '^[s-x]';
#查询名字以s-x开头的学生信息
select id,name from info where name regexp '^[^a-z]';
#

23 运算符

1、算术运算符
以 SELECT 命令来实现最基础的加减乘除运算,MySQL 支持使用的算术运算符,

+		加法
-		减法
*		乘法
/		除法
%		取余

select 1+2,2-1,3*4,4/2,5%2;

24 存储过程

使用方法 是shell脚本

格式和函数很像

MySQL 数据库存储过程是一组为了完成特定功能的 SQL 语句的集合
存储过程在使用过程中是将常用或者复杂的工作预先使用 SQL 语句写好并用一个指定的名称存储起来,
这个过程经编译和优化后存储在数据库服务器中。当需要使用该存储过程时,只需要调用它即可。
存储过程在执行上比传统sql速度更快、执行效率更高。

存储过程优势:

  1. 封装性

    通常完成一个逻辑功能需要多条 SQL 语句,而且各个语句之间很可能传递参数,所以,编写逻辑功能相对来说稍微复杂些,而存储过程可以把这些 SQL 语句包含到一个独立的单元中,使外界看不到复杂的 SQL 语句,只需要简单调用即可达到目的。并且数据库专业人员可以随时对存储过程进行修改,而不会影响到调用它的应用程序源代码

  2. 可增强 SQL 语句的功能和灵活性

    存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。

  3. 可减少网络流量

    由于存储过程是在服务器端运行的,且执行速度快,因此当客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而可降低网络负载。

  4. 提高性能

当存储过程被成功编译后,就存储在数据库服务器里了,以后客户端可以直接调用,这样所有的 SQL 语句将从服务器执行,从而提高性能。但需要说明的是,存储过程不是越多越好,过多的使用存储过程反而影响系统性能

  1. 提高数据库的安全性和数据的完整性

    存储过程提高安全性的一个方案就是把它作为中间组件,存储过程里可以对某些表做相关操作,然后存储过程作为接口提供给外部程序。这样,外部程序无法直接操作数据库表,只能通过存储过程来操作对应的表,因此在一定程度上,安全性是可以得到提高的。

  2. 使数据独立

    数据的独立可以达到解耦的效果,也就是说,程序可以调用存储过程,来替代执行多条的 SQL 语句。这种情况下,存储过程把数据同用户隔离开来,优点就是当数据表的结构改变时,调用表不用修改程序,只需要数据库管理者重新编写存储过程即可。

语法:
CREATE PROCEDURE <存储过程名> ( [过程参数[,…] ] ) <过程体>
[过程参数[,…] ] 格式
<过程名>:尽量避免与内置的函数或字段重名
<过程体>:语句
[ IN | OUT | INOUT ] <参数名><类型>

1) 过程名
存储过程的名称,默认在当前数据库中创建。若需要在特定数据库中创建存储过程,则要在名称前面加上数据库的名称,即 db_name.sp_name。
需要注意的是,名称应当尽量避免选取与 MySQL 内置函数相同的名称,否则会发生错误。

2) 过程参数
存储过程的参数列表。其中,<参数名>为参数名,<类型>为参数的类型(可以是任何有效的 MySQL 数据类型)。当有多个参数时,参数列表中彼此间用逗号分隔。存储过程可以没有参数(此时存储过程的名称后仍需加上一对括号),也可以有 1 个或多个参数。
MySQL 存储过程支持三种类型的参数,即输入参数、输出参数和输入/输出参数,分别用 IN、OUT 和 INOUT 三个关键字标识。其中,输入参数可以传递给一个存储过程,输出参数用于存储过程需要返回一个操作结果的情形,而输入/输出参数既可以充当输入参数也可以充当输出参数。

3) 过程体
存储过程的主体部分,也称为存储过程体,包含在过程调用的时候必须执行的 SQL 语句。这个部分以关键字 BEGIN 开始,以关键字 END 结束
在 MySQL 中,服务器处理 SQL 语句默认是以分号作为语句结束标志的。然而,在创建存储过程时,存储过程体可能包含有多条 SQL 语句,这些 SQL 语句如果仍以分号作为语句结束符,那么 MySQL 服务器在处理时会以遇到的第一条 SQL 语句结尾处的分号作为整个程序的结束符,而不再去处理存储过程体中后面的 SQL 语句,这样显然不行。
为解决以上问题,通常使用 DELIMITER 命令将结束命令修改为其他字符。语法格式如下: delimiter $$
语法说明如下:
$$ 是用户定义的结束符,通常这个符号可以是一些特殊的符号,如两个“?”或两个“¥”等。
当使用 DELIMITER 命令时,应该避免使用反斜杠“\”字符,因为它是 MySQL 的转义字符

成功执行这条 SQL 语句后,任何命令、语句或程序的结束标志就换为两个??
mysql > DELIMITER ??
若希望换回默认的分号“;”作为结束标志,则在 MySQL 命令行客户端输入下列语句即可
mysql > DELIMITER ;
注意:DELIMITER 和分号“;”之间一定要有一个空格

delimiter ??
CREATE PROCEDURE 存储过程名()					                          
BEGIN				
执行的sql语句 1 ;
执行的sql语句 2 ;
end ??

delimiter(一定要加空格,一定要加空格,一定要加空格);

call 存储过程名

示例(不带参数的创建)
##创建存储过程##
DELIMITER $$							                          #将语句的结束符号从分号;临时改为两个$$(可以自定义)
CREATE PROCEDURE Proc()					                          #创建存储过程,过程名为Proc,不带参数
-> BEGIN								                          #过程体以关键字 BEGIN 开始
-> create table mk (id int (10), name char(10),score int (10));   #过程体语句
-> insert into mk values (1, 'wang',13);                          #过程体语句
-> select * from mk;			                                  #过程体语句
-> END $$								                          #过程体以关键字 END 结束

DELIMITER ;								                          #将语句的结束符号恢复为分号


mysql> delimiter //
mysql> create procedure data()
    -> begin
    -> select now();
    -> end //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call data;
+---------------------+
| now()               |
+---------------------+
| 2021-12-01 17:36:43 |
+---------------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)




delimiter @@
create procedure proc (in inname varchar(40))    
begin
select * from info where name=inname;
end @@

delimiter ;		

call proc2('wangwu');    





条件判断
if then else   ..... end if
delimiter $$
create procedure  proc6(in var int)
begin
if var>10 then
update students set age=age+1 where stuid=1;
end if;
end $$
 
delimiter ;
call proc(11)




循环 while do....end while

create table testlog (id int auto_increment primary key,name char(10),age int default 20);

delimiter $$

create procedure  ky15() 
begin  
declare i int;
set i = 1; 
while i <= 100000 
do  insert into testlog(name,age) values (concat('zhou',i),i); 
set i = i +1; 
end while; 
end$$

delimiter ;

select concat(zhou,1);
select * from testlog limit 10;






##查看存储过程##
格式:
SHOW CREATE PROCEDURE [数据库.]存储过程名;		#查看某个存储过程的具体信息
SHOW CREATE PROCEDURE  proc1

##删除存储过程##
存储过程内容的修改方法是通过删除原有存储过程,之后再以相同的名称创建新的存储过程。

DROP PROCEDURE IF EXISTS Proc;

24生产环境 my.cnf 配置案例

32G

#打开独立表空间
innodb_file_per_table = 1
#MySQL 服务所允许的同时会话数的上限,经常出现Too Many Connections的错误提示,则需要增大此值
max_connections = 8000
#所有线程所打开表的数量
open_files_limit = 10240
#back_log 是操作系统在监听队列中所能保持的连接数
back_log = 300
#每个客户端连接最大的错误允许数量,当超过该次数,MYSQL服务器将禁止此主机的连接请求,直到MYSQL
服务器重启或通过flush hosts命令清空此主机的相关信息
max_connect_errors = 1000
#每个连接传输数据大小.最大1G,须是1024的倍数,一般设为最大的BLOB的值
max_allowed_packet = 32M #指定一个请求的最大连接时间
wait_timeout = 10
# 排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序
sort_buffer_size = 16M 
#不带索引的全表扫描.使用的buffer的最小值
join_buffer_size = 16M 
#查询缓冲大小
query_cache_size = 128M #指定单个查询能够使用的缓冲区大小,缺省为1M
query_cache_limit = 4M    
# 设定默认的事务隔离级别
transaction_isolation = REPEATABLE-READ
# 线程使用的堆大小. 此值限制内存中能处理的存储过程的递归深度和SQL语句复杂性,此容量的内存在每次
连接时被预留.
thread_stack = 512K 
# 二进制日志功能
log-bin=/data/mysqlbinlogs/
#二进制日志格式
binlog_format=row
#InnoDB使用一个缓冲池来保存索引和原始数据, 可设置这个变量到物理内存大小的80%
innodb_buffer_pool_size = 24G 
#用来同步IO操作的IO线程的数量
innodb_file_io_threads = 4 #在InnoDb核心内的允许线程数量,建议的设置是CPU数量加上磁盘数量的两倍
innodb_thread_concurrency = 16
# 用来缓冲日志数据的缓冲区的大小
innodb_log_buffer_size = 16M
在日志组中每个日志文件的大小
innodb_log_file_size = 512M 
# 在日志组中的文件总数
innodb_log_files_in_group = 3
# SQL语句在被回滚前,InnoDB事务等待InnoDB行锁的时间
innodb_lock_wait_timeout = 120
#慢查询时长
long_query_time = 2 #将没有使用索引的查询也记录下来
log-queries-not-using-indexes

25基础规范

(1)必须使用InnoDB存储引擎
解读:支持事务、行级锁、并发性能更好、CPU及内存缓存页优化使得资源利用率更高
(2)使用UTF8MB4字符集
解读:万国码,无需转码,无乱码风险,节省空间,支持表情包及生僻字
(3)数据表、数据字段必须加入中文注释
解读:N年后谁知道这个r1,r2,r3字段是干嘛的
(4)禁止使用存储过程、视图、触发器、Event
解读:高并发大数据的互联网业务,架构设计思路是“解放数据库CPU,将计算转移到服务层”,并发量
大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现
“增机器就加性能”。数据库擅长存储与索引,CPU计算还是上移吧!
(5)禁止存储大文件或者大照片
解读:为何要让数据库做它不擅长的事情?大文件和照片存储在文件系统,数据库里存URI多好。

26命名规范

(6)只允许使用内网域名,而不是ip连接数据库
(7)线上环境、开发环境、测试环境数据库内网域名遵循命名规范
业务名称:xxx
线上环境:xxx.db
开发环境:xxx.rdb
测试环境:xxx.tdb
从库在名称后加-s标识,备库在名称后加-ss标识
innodb_log_file_size = 512M 
# 在日志组中的文件总数
innodb_log_files_in_group = 3
# SQL语句在被回滚前,InnoDB事务等待InnoDB行锁的时间
innodb_lock_wait_timeout = 120
#慢查询时长
long_query_time = 2 
#将没有使用索引的查询也记录下来
log-queries-not-using-indexes
线上从库:xxx-s.db
线上备库:xxx-sss.db
(8)库名、表名、字段名:小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用
(9)库名与应用名称尽量一致,表名:t_业务名称_表的作用,主键名:pk_xxx,非唯一索引名:idx_xxx,唯
一键索引名:uk_xxx

27表设计规范

(10)单实例表数目必须小于500
单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。
说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表
(11)单表列数目必须小于30
(12)表必须有主键,例如自增主键
解读:
a)主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用
b)主键要选择较短的数据类型, Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的
减少索引的磁盘空间,提高索引的缓存效率
c) 无主键的表删除,在row模式的主从架构,会导致备库夯住
(13)禁止使用外键,如果有外键完整性约束,需要应用程序控制
解读:外键会导致表与表之间耦合,update与delete操作都会涉及相关联的表,十分影响sql 的性能,
甚至会造成死锁。高并发情况下容易造成数据库性能,大数据高并发业务场景数据库使用以性能优先

28字段设计规范

(14)必须把字段定义为NOT NULL并且提供默认值
解读:
a)null的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化
b)null 这种类型MySQL内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较
多空字段的时候,数据库的处理性能会降低很多
c)null值需要更多的存储空,无论是表还是索引中每行中的null的列都需要额外的空间来标识
d)对null 的处理时候,只能采用is null或is not null,而不能采用=、in、<、<>、!=、not in这些操作符
号。如:where name!='shenjian',如果存在name为null值的记录,查询结果就不会包含name为null
值的记录
(15)禁止使用TEXT、BLOB类型
解读:会浪费更多的磁盘和内存空间,非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能
BLOB 是二进制字符串,TEXT 是非二进制字符串,两者均可存放大容量的信息。BLOB 主要存储图片、音频信息等,而 TEXT 只能存储纯文本文件。

(16)禁止使用小数存储货币
解读:使用整数吧,小数容易导致钱对不上

(17)必须使用varchar(20)存储手机号    
解读:
a)涉及到区号或者国家代号,可能出现+-()
b)手机号会去做数学运算么?
c)varchar可以支持模糊查询,例如:like“138%”

(18)禁止使用ENUM,可使用TINYINT代替
解读:
a)增加新的ENUM值要做DDL操作
b)ENUM的内部实际存储就是整数,你以为自己定义的是字符串?

29索引设计规范

(19)单表索引建议控制在5个以内
(20)单索引字段数不允许超过5个
解读:字段超过5个时,实际已经起不到有效过滤数据的作用了
(21)禁止在更新十分频繁、区分度不高的属性上建立索引
解读:
a)更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能
b)“性别”这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似
(22)建立组合索引,必须把区分度高的字段放在前面
解读:能够更加有效的过滤数据

30 SQL使用规范

(23)禁止使用SELECT *,只获取必要的字段,需要显示说明列属性
解读:
a)读取不需要的列会增加CPU、IO、NET消耗
b)不能有效的利用覆盖索引
c)使用SELECT * 容易在增加或者删除字段后出现程序 BUG
(24)禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性
解读:容易在增加或者删除字段后出现程序BUG

(25)禁止使用属性隐式转换
解读:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone
索引,猜猜为什么?(这个线上问题不止出现过一次)

(26)禁止在WHERE条件的属性上使用函数或者表达式
解读:SELECT uid FROM t_user WHERE from_unixtime(day)>='2017-02-15' 会导致全表扫描
正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')
(27)禁止负向查询,以及%开头的模糊查询
解读:
a)负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描
b)%开头的模糊查询,会导致全表扫描
(28)禁止大表使用JOIN查询,禁止大表使用子查询
解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能
(29)禁止使用OR条件,必须改为IN查询
解读:旧版本Mysql的OR查询是不能命中索引的,即使能命中索引,为何要让数据库耗费更多的CPU帮
助实施查询优化呢?
(30)应用程序必须捕获SQL异常,并有相应处理

常见错误代码

常见的服务器错误代码及说明如下表所示:

错误代码 说 明
1004 无法创建文件
1005 无法创建数据表、创建表失败
1006 无法创建数据库、创建数据库失败
1007 无法创建数据库,数据库己存在
1008 无法删除数据库,数据库不存在
1009 不能删除数据库文件导致删除数据库失败
1010 不能删除数据目录导致删除数据库失败
1011 删除数据库文件时出错
1012 无法读取系统表中的记录
1013 无法获取的状态
1014 无法获得工作目录
1015 无法锁定文件
1016 无法打开文件
1017 无法找到文件
1018 无法读取的目录
1019 无法为更改目录
1020 记录已被其它用户修改
1021 硬盘剩余空间不足,请加大硬盘可用空间
1022 关键词重读,更改记录失败
1023 关闭时发生错误
1025 更改名字时发生错误
1032 记录不存在
1036 数据表是只读的,不能对它进行修改
1037 系统内存不足,请重启数据库或重启服务器
1042 无效的主机名
1044 当前用户没有访问数据库的权限
1045 不能连接数据库,用户名或密码错误

常见的客户端错误代码及说明如下所示:

2000 未知 MySQL 错误
2001 不能创建 UNIX 套接字(%d)
2002 不能通过套接字“ %s”(%d)连接到本地 MySQL 服务器, self 服务未启动
2003 不能连接到 %s ”(%d )上的 MySQL 服务器,未启动 mysql 服务
2004 不能创建 TCP/IP 接字(%d)
2005 未知的 MySQL 服务器主机“ %s”(%d)
2007 协议不匹配,服务器版本=%d,客户端版本=%d
2008 MySQL 客户端内存溢出
2009 错误的主机信息
2010 通过 UNIX 套接字连接的本地主机
2012 服务器握手过程中出错
2013 查询过程中丢失了与 SQL 服务器的连接
2014 命令不同步,现在不能运行该命令
2024 连接到从服务器时出错
2025 连接到主服务器时出错
2026 SSL 连接错误

死锁

是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。就是所谓的锁资源请求产生了回路现象,即死循环,此时称系统处于死锁状态或系统产生了死锁。常见的报错信息为“Deadlock found when trying to get lock…”。

在 A窗口中执行以下命令:

use hellodb
create index id_index on students(age);


在 A窗口中执行以下命令:
BEGIN;
UPDATE students set age=50 where stuid=1;
紧接着在 B窗口中执行以下命令。
BEGIN;
UPDATE students set age=60 where stuid=2;
由于 age 是索引字段,与 A窗口中更新的是不同行的数据,所以这时不会出现锁等待现象。

然后在 A窗口中,执行以下命令,这时就会出现锁等待现象了
UPDATE students set age=70 where stuid=2;
最后在 B窗口中,执行以下命令,这时会出现相互等待资源的现象,也就是死锁现象
UPDATE students set age=80 where stuid=1;


innoDB 的并发写操作会触发死锁,同时 InnoDB 也提供了死锁检测机制。通过设置 innodb_deadlock_detect 参数的值来控制是否打开死锁检测。
innodb_deadlock_detect = ON :默认值,打开死锁检测。数据库发生死锁时,系统会自动回滚其中的某一个事务,让其它事务可以继续执行。
innodb_deadlock_detect = OFF:关闭死锁检测。发生死锁时,系统会用锁等待来处理。
show VARIABLES like 'innodb_deadlock_detect';

MySQL 通过 innodb_lock_wait_timeout 参数控制锁等待的时间,单位是秒
SHOW VARIABLES LIKE '%innodb_lock_wait%';
set global VARIABLES innodb_lock_wait_timeout = 500

在实际应用中,我们要尽量防止死锁等待现象的发生,下面介绍几种避免死锁的方法:

  1. 如果不同程序会并发存取多个表,或者涉及多行记录时,尽量约定以相同的顺序访问表,这样可以大大降低死锁的发生。
  2. 业务中要及时提交或者回滚事务,可减少死锁产生的概率。
  3. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率。
  4. 对于非常容易产生死锁的业务部分,可以尝试使用升级锁粒度,通过表锁定来减少死锁产生的概率(表级锁不会产生死锁)。

MySQL集群Cluster

1MySQL 主从复制

1.1主从复制架构和原理

1.1.1服务性能扩展方式

  • 向上扩展,垂直扩展

  • 向外扩展,横向扩展

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v78UWpOK-1640048934876)(mysql日志和备份高级语言.assets/image-20211202142236168.png)]

1.2MySQL的扩展

  • 读写分离
  • 复制:每个节点都有相同的数据集,向外扩展,基于二进制日志的单向复制
1.2.1什么是读写分离?
读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),
而从数据库处理SELECT查询操作。
数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

MySQL 读写分离原理
读写分离就是只在主服务器上写,只在从服务器上读。基本的原理是让主数据库处理事务性操作,而从数据库处理 select 查询。数据库复制被用来把主数据库上事务性操作导致的变更同步到集群中的从数据库。
目前较为常见的 MySQL 读写分离分为以下两种:
1)基于程序代码内部实现
在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。
优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。

2)基于中间代理层实现
代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序。
(1)MySQL-Proxy。MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行SQL 判断。
(2)Atlas。是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。
(3)Amoeba。由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。

由于使用MySQL Proxy 需要写大量的Lua脚本,这些Lua并不是现成的,而是需要自己去写。这对于并不熟悉MySQL Proxy 内置变量和MySQL Protocol 的人来说是非常困难的。
Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层。


1.2.2为什么要读写分离呢?
因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。
但是数据库的“读”(读10000条数据可能只要5秒钟)。
所以读写分离,解决的是,数据库的写入,影响了查询的效率。
1.2.3 什么时候要读写分离?
数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用。
利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能。
1.2.4 主从复制与读写分离
在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。有点类似于rsync,但是不同的是rsync是对磁盘文件做备份,而mysql主从复制是对数据库中的数据、语句做备份。


mysq支持的复制类型
(1)STATEMENT:基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。
(2)ROW:基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。
(3)MIXED:混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。

1.3 复制的功用

  • 数据分布
  • 负载均衡读操作
  • 备份
  • 高可用和故障切换
  • MySQL升级测试

1.4 复制架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lRPz0sz3-1640048934877)(mysql日志和备份高级语言.assets/image-20211202144811304.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BKdx9xJE-1640048934877)(mysql日志和备份高级语言.assets/image-20211202144750987.png)]

1.5 主从复制原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qzVuFaqD-1640048934878)(mysql日志和备份高级语言.assets/image-20211202144924645.png)]

主从复制的工作过程:
1Master节点的数据的改变记录成二进制日志(bin log),
2当Master上的数据发生改变时,则将其改变写入二进制日志中。
3开启一个slave服务线程传递给从服务器
4Slave节点会在一定时间间隔内对Master的二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/O线程请求 Master的二进制事件。
5同时Master节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至Slave节点本地的中继日志(Relay log)中,Slave节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,即解析成 sql 语句逐一执行,使得其数据和 Master节点的保持一致,最后I/O线程和SQL线程将进入睡眠状态,等待下一次被唤醒。

注:
●中继日志通常会位于 OS 缓存中,所以中继日志的开销很小。
●复制过程有一个很重要的限制,即复制在 Slave上是串行化的,也就是说 Master上的并行更新操作不能在 Slave上并行操作
1.5.1主从复制相关线程

主节点:

dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events

从节点:

I/O Thread:向Master请求二进制日志事件,并保存于中继日志中

SQL Thread:从中继日志中读取日志事件,在本地完成重放

1.5.2 跟复制功能相关的文件:
  • master.info:用于保存slave连接至master时的相关信息,例如账号、密码、服务器地址等
  • relay-log.info:保存在当前slave节点上已经复制的当前二进制日志和本地relay log日志的对应关系
  • mariadb-relay-bin.00000#: 中继日志,保存从主节点复制过来的二进制日志,本质就是二进制日志
1.5.3 MySQL 主从复制延迟
  1. master服务器高并发,形成大量事务
  2. 网络延迟
  3. 主从硬件设备导致
    cpu主频、内存io、硬盘io
  4. 本来就不是同步复制、而是异步复制
    从库优化Mysql参数。比如增大innodb_buffer_pool_size,让更多操作在Mysql内存中完成,减少磁盘操作。
    从库使用高性能主机。包括cpu强悍、内存加大。避免使用虚拟云主机,使用物理主机,这样提升了i/o面性。
    从库使用SSD磁盘
    网络优化,避免跨机房实现同步

2.实际操作

1.环境配置
master服务器: 192.168.91.100   mysql5.7
slave1服务器: 192.168.91.101 	mysql5.7
slave2服务器: 192.168.91.102	mysql5.7
Amoeba服务器: 192.168.91.103   jdk1.6、Amoeba
客户端 服务器: 192.168.91.104	  mysql
2.初始环境准备
[root@localhost ~]#systemctl stop firewalld
[root@localhost ~]#setenforce 0
systemctl stop firewalld
setenforce 0
3.搭建mysql主从复制
3.1搭建时间同步:
[root@localhost ~]#yum install ntp -y
#安装时间同步服务器,主从都安装好后

################配置主服务器##################

[root@localhost ~]#vim /etc/ntp.conf 
#修改配置文件

server 127.127.91.0
#设置本地时钟源
fudge  127.127.91.0 stratum 8
#设置时间层级为8 限制在15 以内

server 127.127.91.0
fudge  127.127.91.0 stratum 8

[root@localhost ~]#service ntpd start
#开启服务


################配置从服务器##################
[root@localhost ~]#yum install ntpdate -y
#安装同步服务
[root@localhost ~]#service ntpd start
#开启服务
Redirecting to /bin/systemctl start ntpd.service
[root@localhost ~]#/usr/sbin/ntpdate 192.168.91.100
#执行同步
 4 Dec 13:21:17 ntpdate[70994]: the NTP socket is in use, exiting
 
[root@localhost ~]#crontab -e
*/30 * * * *  /usr/sbin/ntpdate 192.168.91.100

3.2配置主从
######开启二进制日志####
###主服务器#####
[root@localhost ~]#vim /etc/my.cnf
[mysqld]
server-id = 1
log-bin=master-bin
#开启二进制日志
binlog_format=MIXED
#二进制日志格式
log-slave-updates=true
#开启从服务器同步

log-bin=master-bin
binlog_format=MIXED
log-slave-updates=true

[root@localhost ~]#systemctl restart mysqld.service 
[root@localhost ~]#mysql -uroot -p123123

grant replication slave on *.* to 'myslave'@'192.168.91.%' identified by '123456';
flush privileges;
show master status;

####从服务器######
[root@localhost ~]#vim /etc/my.cnf
[mysqld]
server-id = 2
#修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin
#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index
#添加,定义中继日志文件的位置和名称,一般和relay-log在同一目录

server-id = 2
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
[root@localhost ~]# systemctl restart mysqld.service 
[root@localhost ~]#mysql -uroot -p123123
help change master to
change master to master_host='192.168.91.100',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;

start slave;
show slave status\G
#Slave_IO_Running: Yes
#Slave_SQL_Running: Yes


验证主从同步
create database ky15;
show databases;


3.3 搭建Amoeba 实现读写分离
##安装 Java 环境##
因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。

[root@localhost local]#cd /opt/
[root@localhost local]#cp jdk-6u14-linux-x64.bin /usr/local/
[root@localhost local]#chmod +x /usr/local/jdk-6u14-linux-x64.bin
[root@localhost local]#cd /usr/local/
[root@localhost local]#./jdk-6u14-linux-x64.bin
#一路回车到底,最后输入yes 自动安装
[root@localhost local]#mv jdk1.6.0_14/ jdk1.6
#改个名字
[root@localhost local]#vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin
[root@localhost local]#source /etc/profile
#刷新下
[root@localhost opt]#mkdir /usr/local/amoeba
[root@localhost opt]#cd /opt/
[root@localhost opt]#tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba
[root@localhost opt]#chmod -R 755 /usr/local/amoeba/
[root@localhost bin]#ls
amoeba      amoeba.classworlds  benchmark.bat
amoeba.bat  benchmark           benchmark.classworlds
[root@localhost bin]#/usr/local/amoeba/bin/amoeba
#如显示amoeba start|stop说明安装成功

#配置 Amoeba读写分离,两个 Slave 读负载均衡##
#先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问
grant all on *.* to test@'192.168.91.%' identified by '123123';
flush privileges;

#修改amoeba配置
[root@localhost amoeba]#cd /usr/local/amoeba/conf/
[root@localhost conf]#cp amoeba.xml amoeba.xml.bak
#备份配置文件
[root@localhost conf]#vim amoeba.xml
#全局配置
30 <property name="user">amoeba</property>
#设置登录用户名
32<property name="password">123456</property>
#设置密码

115<property name="defaultPool">master</property>
#设置默认池为master
118<property name="writePool">master</property>
#设置写池
119<property name="readPool">slaves</property>
#设置读池

[root@localhost conf]#vim dbServers.xml 
23 <!-- <property name="schema">test</property> -->
#23行注释
26<property name="user">test</property>
#设置登录用户
28 <!--  mysql password -->
#删除
29<property name="password">123123</property>
#解决28注释,添加密码

45<dbServer name="master"  parent="abstractServer">
#服务池名
48<property name="ipAddress">192.168.91.100</property>
#添加地址

52<dbServer name="slave1"  parent="abstractServer">
55<property name="ipAddress">192.168.91.101</property>
复制6行 添加另一从节点
59<dbServer name="slave2"  parent="abstractServer">
62<property name="ipAddress">192.168.91.102</property>

66<dbServer name="slaves" virtual="true">
#定义池名
72<property name="poolNames">slave1,slave2</property>
#写上从节点名

[root@localhost conf]#amoeba start &
#开启服务

[root@localhost ~]#netstat -ntap |grep java
tcp6       0      0 127.0.0.1:49171         :::*                    LISTEN      38266/java          
tcp6       0      0 :::8066                 :::*                    LISTEN      38266/java          
tcp6       0      0 192.168.91.103:45624    192.168.91.102:3306     ESTABLISHED 38266/java          
tcp6       0      0 192.168.91.103:49984    192.168.91.100:3306     ESTABLISHED 38266/java          
tcp6       0      0 192.168.91.103:60266    192.168.91.101:3306     ESTABLISHED 38266/java




[root@localhost ~]#yum install mariadb mariadb-server.x86_64 -y
[root@localhost ~]#mysql -uamoeba -p123123 -h 192.168.91.103 -P8066

mysql> show variables like 'general%';
+------------------+-------------------------------------+
| Variable_name    | Value                               |
+------------------+-------------------------------------+
| general_log      | OFF                                 |
| general_log_file | /usr/local/mysql/data/localhost.log |
+------------------+-------------------------------------+
2 rows in set (0.00 sec)

mysql> set global general_log=1;
[root@localhost data]#tail -f /usr/local/mysql/data/localhost.log

3 实际问题

3.1造成主从不一致的原因
  • 主库binlog格式为Statement,同步到从库执行后可能造成主从不一致。
  • 主库执行更改前有执行set sql_log_bin=0,会使主库不记录binlog,从库也无法变更这部分数据。
  • 从节点未设置只读,误操作写入数据
  • 主库或从库意外宕机,宕机可能会造成binlog或者relaylog文件出现损坏,导致主从不一致
  • 主从实例版本不一致,特别是高版本是主,低版本为从的情况下,主数据库上面支持的功能,从不支持
  • 数据库上面可能不支持该功能
  • MySQL自身bug导致
3.2主从不一致修复方法
  • 将从库重新实现

虽然这也是一种解决方法,但是这个方案恢复时间比较慢,而且有时候从库也是承担一部分的查询

操作的,不能贸然重建。

  • 使用percona-toolkit工具辅助

PT工具包中包含pt-table-checksum和pt-table-sync两个工具,主要用于检测主从是否一致以及修

复数据不一致情况。这种方案优点是修复速度快,不需要停止主从辅助,缺点是需要知识积累,需

要时间去学习,去测试,特别是在生产环境,还是要小心使用

关于使用方法,可以参考下面链接:https://www.cnblogs.com/feiren/p/7777218.html

  • 手动重建不一致的表

在从库发现某几张表与主库数据不一致,而这几张表数据量也比较大,手工比对数据不现实,并且

重做整个库也比较慢,这个时候可以只重做这几张表来修复主从不一致

这种方案缺点是在执行导入期间需要暂时停止从库复制,不过也是可以接受的

范例:A,B,C这三张表主从数据不一致

3.3如何避免主从不一致
  • 主库binlog采用ROW格式
  • 主从实例数据库版本保持一致
  • 主库做好账号权限把控,不可以执行set sql_log_bin=0
  • 从库开启只读,不允许人为写入
  • 定期进行主从一致性检验

中间件

mysql-proxy:Oracle,https://downloads.mysql.com/archives/proxy/

Atlas:Qihoo,https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md

dbproxy:美团,https://github.com/Meituan-Dianping/DBProxy

Cetus:网易乐得,https://github.com/Lede-Inc/cetus

Amoeba:https://sourceforge.net/projects/amoeba/

Cobar:阿里巴巴,Amoeba的升级版, https://github.com/alibaba/cobar

Mycat:基于Cobar http://www.mycat.io/ (原网站)

mycat

http://dl.mycat.org.cn/1.6.7.6/20210303094759/

1Mycat应用场景

Mycat适用的场景很丰富,以下是几个典型的应用场景

单纯的读写分离,此时配置最为简单,支持读写分离,主从切换

分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片

多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化

报表系统,借助于Mycat的分表能力,处理大规模报表的统计

替代Hbase,分析大数据

作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来

结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时Mycat可能是最简单有效

的选择

Mycat长期路线图

强化分布式数据库中间件的方面的功能,使之具备丰富的插件、强大的数据库智能优化功能、全面

的系统监控能力、以及方便的数据运维工具,实现在线数据扩容、迁移等高级功能

进一步挺进大数据计算领域,深度结合Spark Stream和Storm等分布式实时流引擎,能够完成快

速的巨表关联、排序、分组聚合等 OLAP方向的能力,并集成一些热门常用的实时分析算法,让工程师以及DBA们更容易用Mycat实现一些高级数据分析处理功能

不断强化Mycat开源社区的技术水平,吸引更多的IT技术专家,使得Mycat社区成为中国的

Apache,并将Mycat推到Apache基金会,成为国内顶尖开源项目,最终能够让一部分志愿者成为

专职的Mycat开发者,荣耀跟实力一起提升

2Mycat 可以简单概括为

一个彻底开源的,面向企业应用开发的大数据库集群

支持事务、ACID、可以替代MySQL的加强版数据库

一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群

一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server

结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品

一个新颖的数据库中间件产品

实际操作:


[root@localhost ~]#vim /etc/my.cnf
[mysqld]
server-id = 1
log-bin=master-bin
#开启二进制日志
binlog_format=MIXED
#二进制日志格式
log-slave-updates=true
#开启从服务器同步

log-bin=master-bin
binlog_format=MIXED
log-slave-updates=true

grant replication slave on *.* to 'myslave'@'192.168.91.%' identified by '123456';
flush privileges;
show master status;



####从服务器######
[root@localhost ~]#vim /etc/my.cnf
[mysqld]
server-id = 2
#修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin
#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index
#添加,定义中继日志文件的位置和名称,一般和relay-log在同一目录

server-id = 2
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
[root@localhost ~]# systemctl restart mysqld.service 
[root@localhost ~]#mysql -uroot -p123123
help change master to
change master to master_host='192.168.91.100',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;

start slave;
show slave status\G
#Slave_IO_Running: Yes
#Slave_SQL_Running: Yes

################安装mycat##################
###主上安装java
[root@localhost ~]#yum install java -y
[root@localhost ~]#mkdir /apps
[root@localhost ~]#wget http://dl.mycat.org.cn/1.6.7.6/20210303094759/Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz
#下载软件
[root@localhost ~]#tar zxvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz -C /apps/
[root@localhost bin]#echo 'PATH=/apps/mycat/bin:$PATH' > /etc/profile.d/mycat.sh
[root@localhost bin]#source /etc/profile.d/mycat.sh
[root@localhost bin]#mycat start
#注意内存小于2G 起不来
Starting Mycat-server...
[root@localhost bin]#ll /apps/mycat/logs/
#mycat日志
[root@localhost bin]#tail -f /apps/mycat/logs/wrapper.log 
#日志最后可以看到启动成功
STATUS | wrapper  | 2021/12/04 21:49:27 | --> Wrapper Started as Daemon
STATUS | wrapper  | 2021/12/04 21:49:27 | Launching a JVM...
INFO   | jvm 1    | 2021/12/04 21:49:28 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO   | jvm 1    | 2021/12/04 21:49:28 |   Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.
INFO   | jvm 1    | 2021/12/04 21:49:28 | 
INFO   | jvm 1    | 2021/12/04 21:49:30 | MyCAT Server startup successfully. see logs in logs/mycat.log


###客户端连接数据库##
默认密码123456
[root@localhost bin]#mysql -uroot -p123456 -h 192.168.91.103 -P8066
MySQL [(none)]> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
+----------+
1 row in set (0.00 sec)

###########修改  mycat 配置文件###############
[root@localhost ~]#vim /apps/mycat/conf/server.xml
45<property name="serverPort">3306</property>
#去注释改端口,注意 另一个 注释在51行末尾去掉
#密码用户 在110 和111 可以修改这边不修改了
wget http://dl.mycat.org.cn/1.6.7.4/Mycat-server-1.6.7.4-release/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz

[root@localhost conf]#vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="hellodb" />
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
                  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="host1" url="192.168.91.100:3306" user="root" password="123456">
                 <readHost host="host2" url="192.168.91.101:3306" user="root" password="123456"/>
                </writeHost>
        </dataHost>
</mycat:schema>
[root@localhost conf]#cat /apps/mycat/logs/wrapper.log
[root@localhost conf]#ss -nt
GRANT ALL ON *.* TO 'root'@'192.168.91.%' IDENTIFIED BY '123456' ;

select user,host from mysql.user;


[root@localhost ~]#mysql -uroot -p123456 -h 192.168.91.103

MySQL [(none)]> use TESTDB
MySQL [TESTDB]> show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| scores            |
| students          |
| teachers          |
| toc               |
+-------------------+
7 rows in set (0.00 sec)

select @@server_id;
#mysql 的id号 读的显示

mysql> show variables like 'general%';
+------------------+-------------------------------------+
| Variable_name    | Value                               |
+------------------+-------------------------------------+
| general_log      | OFF                                 |
| general_log_file | /usr/local/mysql/data/localhost.log |
+------------------+-------------------------------------+
2 rows in set (0.00 sec)

mysql> set global general_log=1;
[root@localhost data]#tail -f /usr/local/mysql/data/localhost.log

[root@localhost ~]#vim /apps/mycat/conf/server.xml
453306
#去注释改端口,注意 另一个 注释在51行末尾去掉
#密码用户 在110 和111 可以修改这边不修改了
wget http://dl.mycat.org.cn/1.6.7.4/Mycat-server-1.6.7.4-release/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz

[root@localhost conf]#vim schema.xml





select user()





[root@localhost conf]#cat /apps/mycat/logs/wrapper.log
[root@localhost conf]#ss -nt
GRANT ALL ON . TO ‘root’@‘192.168.91.%’ IDENTIFIED BY ‘123456’ ;

select user,host from mysql.user;

[root@localhost ~]#mysql -uroot -p123456 -h 192.168.91.103

MySQL [(none)]> use TESTDB
MySQL [TESTDB]> show tables;
±------------------+
| Tables_in_hellodb |
±------------------+
| classes |
| coc |
| courses |
| scores |
| students |
| teachers |
| toc |
±------------------+
7 rows in set (0.00 sec)

select @@server_id;
#mysql 的id号 读的显示

mysql> show variables like ‘general%’;
±-----------------±------------------------------------+
| Variable_name | Value |
±-----------------±------------------------------------+
| general_log | OFF |
| general_log_file | /usr/local/mysql/data/localhost.log |
±-----------------±------------------------------------+
2 rows in set (0.00 sec)

mysql> set global general_log=1;
[root@localhost data]#tail -f /usr/local/mysql/data/localhost.log




你可能感兴趣的:(mysql,数据库,sql)