中级DBA

```bash

入门篇

第一章 介绍与安装

第二章 体系结构和基础管理

第三章 SQL基础

核心篇

第四章 索引及执行计划

第五章 存储引擎

第六章 日志管理

第七章 备份恢复

第八章 复制

架构篇

第九章 高可用与读写分离

第十章 分布式架构

优化篇

第十一章 全面优化

NoSQL 篇

MongoDB

redis

NewSQL

```

### 第一章  介绍与安装

#### 1.多版本之前的初始的不同

```css

5.7之前是不一样,5.7 和 5.8 是 一样

a.5.7之前初始化操作---->/usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/data/3306/data

b.5.7之后--initialize-insecure

```

#### 2.初始化密码与不初始化

```bash

a.初始化密码 --initialize: ----> 会生成一个12位,4种密码复杂度临时管理密码,但第一次登陆需要修改.

b.不初始化密码 --initialize-insecure  ----> 管理员密码为空

```

### 第二章 体系结构和基础管理

#### 1.版本插件使用

```css

1. 8.0 之后必须先建用户后授权,grant不再支持建用户功能和密码修改功能.

2. 密码插件,8.0之前使用mysql_native_password,8.0 之后使用caching_sha2_password

导致的问题:  使用老的客户端程序,连接不了8.0版本

解决方法:

a. 建用户时,指定mysql_native_password插件进行密码加密.

b. 修改用户时,可以修改插件

c. 配置文件中指定默认加密插件为mysql_native_password

在[mysqld]中添加下边的代码

default_authentication_plugin=mysql_native_password

[mysqld]

default-authentication-plugin=sha256_password 

sha256_password的安全程度要比mysql_native_password高,尝试切换为sha256_password。

```

```bash

--initialize-insecure 初始化核心参数

--user 指定初始化用户

--basedir 数据库软件位置

--datadir 数据存储位置

mysqld_safe --defaults-file 启动命令

defaluts-file读取的代替通用选项文件的选项文件名。如果给出,必须首选该选项

/usr/local/mysql56/bin/mysqld_safe --defaults-file=/data/3316/my.cnf &

mysql -S /tmp/mysql.sock 连接数据库

--skip-grant-tables 跳过授权表

--skip-networking 跳过远程登陆

set global innodb_fast_shutdown=0 在做数据库关闭升级的时候,这个时候能最大保障数据的完整性

innodb_fast_shutdown=0

会做清除脏页和插入缓冲区的合并操作,也会将脏页全部刷新到磁盘上面去但是这个时候关闭的速度也是最慢的

innodb_fast_shutdown=1

关闭MySQL的时候不会做清除脏页和插入缓冲区的合并操作,也不会将脏页刷新到磁盘

innodb_fast_shutdown=2 都不会,但是会刷新redo log里面,再下次启动mysql的时候恢复

/usr/local/mysql57/bin/mysqladmin -S /tmp/mysql3316.sock shutdown 关闭数据库

util.checkForServerUpgrade 升级检测

mysqld --verbose --help 查看全部列表列

3360端口

mysql_upgrade  --force 强制 强制

```

###  第三章 SQL基础

表 ibd2sdi t1.ibd 打开表文件 时间戳 json

#### 1.mysql 5.7之后的使用group by查询参数出现的sql_mode=only_full_group_by错误问题

```bash

执行SET GLOBAL sql_mode = ”; 把sql_mode 改成非only_full_group_by模式

第二种方法:除去group_by 以外的参数加上any_value(*) 如:SELECT any_value(`name`) FROM ts_product GROUP BY type_id;

```

#### 2.utf8和utfmb4区别

```bash

utf8  : 最大存储3字节字符,中文占3字节,数字\字母\特殊符号占1字节

uf8mb4 : 最大存储4字节字符,中文占3字节,数字\字母\特殊符号占1字节,可以存储emoji表情

```

#### 3.整数的区别

```bash

tinyint    1bytes      0-255    -128~127

int        4bytes      0-2^32-1  -2^31~2^31-1  10位数

bigint      8bytes      0-2^64-1  -2^63~2^63-1  20位数

```

#### 4.浮点数你们公司怎么存储的?

```

金钱有关的用decimal,对精度要求高

对精度要求不高的,放大N倍,用整数存储,整数类型

```

#### 5.char和varchar区别

```css

共同点: 都是字符串类型,最多都只能存10个字符.

不同点:

1. char定长,varchar变长.如果存储变长字符串,一般建议varchar

2. varchar类型,额外占用1-2bytes,存储字符长度.

```

#### 6.drop  truncate  delete 区别 ?

```bash

drop  : 表定义+数据全部删除,立即释放磁盘空间.

truncate : 整表所有数据全部删除,清空数据页,立即释放磁盘空间.

delete : 逐行"删除"(只是打一个标记),表中每行数据,逻辑删除,不会立即释放磁盘.HWM(高水位线)没有降低

```

#### 7.DDL规范

```bash

DDL 规范

-- 库的DDL

1. 禁止线上业务系统出现DROP操作.

2. 库名: 不能大写字母,不能是关键字,不能使数字开头.一般和业务有关.

3. 显式的设置字符集.

-- 表的DDL

1. 建表时,表名小写, 建议格式: wp_user,不要出现数字开头和大写字母

2. 显式的设置存储引擎\字符集\表的注释.

3. 列名要和业务有关

4. 列的数据类型,讲究:完整\简短\合适,精度不高浮点数,放大N倍.

5. 每个表必须要有主键,数字自增无关列.

6. 每个列尽量是非空的,而且设置默认值.

7. 每个列要有注释.

8. 变长列,一般选择varchar类型,定长列一般选择char.

9. 大字段,可以选择附件形式,可以选择ES.

10. 对于Online-DDL ,对于追加方式添加列,可以online,添加索引可以online(8.0)

其他情况下,需要在数据库低谷时间点去做.如果很紧急,pt-osc或者gh-ost

```

#### 8.DML、DQL表属性查询

```bash

DML

生产应用中,update必须要加where条件

mysql> set global sql_safe_updates=1;

重启数据库会失效

写入vim /etc/my.cnf中 sql_safe_updates=1

1, 查看MySQL服务器配置信息

mysql> show variables;

2, 查看MySQL服务器运行的各种状态值

mysql> show global status;

NOTNULL 说明这个字段不能为空值

DEFAULT '1' 说明这个字段的默认值是1

DQL

use school

show tables;

desc stu;

show create table stu;

CREATE TABLE ceshi LIKE stu;

```

```css

where 过滤;

group by 聚合函数;(count(),sum(),avg(),max(),min(),group_concat()) 按照固定条件进行分组

having  后过滤;

order by  排序;

limit  限制;

source /root/world.sql 在mysql导入

show columns from stu=show tables from mysql

select @@sql_mode; 查看所有名词

show charset; 查看字符集 8.0 默认: utf8mb4 8.0 之前默认: latin1

show collation; 排序查询

show variables; 系统变量

select @@basedir; 系统变量 两个@@符号

select @@innodb_flush_log_at_trx_commit; 控制MySQL磁盘写入策略以及数据安全性 1性能最差

当设置为0,该模式速度最快,但不太安全,mysqld进程的崩溃会导致上一秒钟所有事务数据的丢失。

当设置为1,该模式是最安全的, 但也是最慢的一种方式。在mysqld 服务崩溃或者服务器主机crash的情况下,binary log 只有可能丢失最多一个语句或者一个事务。

当设置为2,该模式速度较快,也比0安全,只有在操作系统崩溃或者系统断电的情况下,上一秒钟所有事务数据才可能丢失。

```

#### 9.元数据获取

```

数据字典

```

```css

use school

student :学生表

sno:    学号

sname:学生姓名

sage: 学生年龄

ssex: 学生性别

teacher :教师表

tno:    教师编号

tname:教师名字

course :课程表

cno:  课程编号

cname:课程名字

tno:  教师编号

score  :成绩表

sno:  学号

cno:  课程编号

score:成绩

统计zhang3,学习了几门课

查询zhang3,学习的课程名称有哪些?

查询oldguo老师教的学生名.

查询oldguo所教课程的平均分数

每位老师所教课程的平均分,并按平均分排序

查询oldguo所教的不及格的学生姓名

查询所有老师所教学生不及格的信息

查询平均成绩大于60分的同学的学号和平均成绩;

查询所有同学的学号、姓名、选课数、总成绩;

查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分

统计各位老师,所教课程的及格率

查询每门课程被选修的学生数

查询出只选修了一门课程的全部学生的学号和姓名

查询选修课程门数超过1门的学生信息

统计每门课程:优秀(85分以上),良好(70-85),一般(60-70),不及格(小于60)的学生列表

查询平均成绩大于85的所有学生的学号、姓名和平均成绩

```

```bash

show  databases;                          #查看所有数据库

show tables;                                          #查看当前库的所有表

SHOW TABLES FROM                        #查看某个指定库下的表

show create database world                #查看建库语句

show create table world.city                #查看建表语句

show  grants for  root@'localhost'      #查看用户的权限信息

show  charset;                                  #查看字符集

show collation                                      #查看校对规则

show processlist;                                  #查看数据库连接情况

show index from                                #表的索引情况

show status                                        #数据库状态查看

SHOW STATUS LIKE '%lock%';        #模糊查询数据库某些状态

SHOW VARIABLES                            #查看所有配置信息

SHOW variables LIKE '%lock%';          #查看部分配置信息

show engines                                      #查看支持的所有的存储引擎

show engine innodb status\G              #查看InnoDB引擎相关的状态信息

show binary logs                                    #列举所有的二进制日志

show master status                                #查看数据库的日志位置信息

show binlog evnets in                            #查看二进制日志事件

show slave status \G                            #查看从库状态

SHOW RELAYLOG EVENTS              #查看从库relaylog事件信息

desc  (show colums from city)              #查看表的列定义信息

http://dev.mysql.com/doc/refman/5.7/en/show.html

show variables like 'character_set_connection'    #查看当前会话字符集

show create table world.countrylanguage          #查看表的字符集

set character_set_connection=[字符集]              #更新当前会话字符集

```

### 第四章 索引

```bash

压测语句

mysqlslap --defaults-file=/etc/my.cnf \

--concurrency=100 --iterations=1 --create-schema='test' \

--query="select * test oldboy.t1000w where k2='VMlm'" engine=innodb \

--number-of-queries=200 -uroot -p123 -verbose

```

#### 1.请你从数据库的角度分析我们公司业务满的原因

```css

1.mysql性能问题

a.应急性蛮,突然卡了

exolain 分析SQL的执行计划,有没有走索引,索引的类型情况

c.建索引、改造句

```

#### 2.选择唯一性索引

```

使用重复值较多的列作为查询条件,可以将表逻辑拆分

可以将此列和其他的查询类,做联合索引

```

#### 3.限制索引的数目

```bash

索引的数目不是越多越好。

可能会产生的问题:

(1) 每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。

(2) 修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。

(3) 优化器的负担会很重,有可能会影响到优化器的选择.

percona-toolkit中有个工具,专门分析索引是否有用

```

删除索引 pt-duplicate-key-checker

```css

<> , not in 不走索引(辅助索引),like "%__"百分号在最前面不走

table  :  操作的表

type  :  操作类型(全表\索引) ,ALL  index  range  ref  eq_ref  const(system)

possible_keys : 有可能用的索引

key    : 真正要用是哪索引

key_len: 索引覆盖长度(联合索引)

rows  : 预估需要扫描的行数

Extra  : using where  using index  using index condition  using  filesort sort  using temp

```

#### 5.自优化AHI(自适应hash索引)\change buffer

```bash

AHI: 索引的所有,为内存中的热点索引页,做了一个hash索引表,可以快速找到需要的索引页地址

change buffer: 对于辅助索引的变化,不会立即更新到索引中,站存在change buffer.

--skip-innodb-adaptive-hash-index

自适应哈希索引功能已分区。每个索引都绑定到一个特定的分区,并且每个分区都由单独的锁存器保护。分区由innodb_adaptive_hash_index_parts 变量控制 。该 innodb_adaptive_hash_index_parts 变量默认设置为8。最大设置为512。

```

mysql查询过程

![image-20201108164835934](C:\Users\苗杰\AppData\Roaming\Typora\typora-user-images\image-20201108164835934.png)

```bash

你能说说为什么B+树相对于B树在查询上会更加优胜吗?

除了上面这个范围查询的,你还能说出其他的一些区别吗?

刚刚我们聊到B+ Tree,那你知道B+Tree的叶子节点都可以存哪些东西吗?

聚簇索引和非聚簇索引,在查询数据的时候有区别吗?

刚刚你提到主键索引查询只会查一次,而非主键索引需要回表查询多次。是所有情况都是这样的吗?非主键索引一定会查询多次吗?

联合索引、最左前缀匹配

你们在创建索引的时候都会考虑哪些因素呢?你们有用过联合索引吗?

那你们在创建联合索引的时候,需要做联合索引多个字段之间顺序你们是如何选择的呢?

索引下推、查询优化

你知道在MySQL 5.6中,对索引做了哪些优化吗?

你们创建的那么多索引,到底有没有生效,或者说你们的SQL语句有没有使用索引查询你们有统计过吗?

那排查的时候,有什么手段可以知道有没有走索引查询呢?

那什么情况下会发生明明创建了索引,但是执行的时候并没有通过索引呢?

哦,索引有关的知识我们暂时就问这么多吧。你们线上数据的事务隔离级别是什么呀?

mysql 数据库中,什么情况下设置了索引但无法使用?

mysql 优化会不会,mycat 分库,垂直分库,水平分库?

mysql 的存储引擎了解过没有?

```

#### 6.冗余索引

```bash

mysql> use sys;

mysql> desc sys.  schema_redundant_indexes;

mysql> select table_schema,table_name,redundant_index_name,redundant_index_columns from  sys.schema_redundant_indexes;  #查询冗余索引

```

#### 7.优化器算法ICP/MRR

```bash

mysql> show variables like  '%switch%';

select @@optimizer_switch; #查询优化器算法

配置文件 my.cnf

mysql> set global optimizer_switch='index_condition_pushdown=off';  #调试关闭

1.压测 开ICP 20000次语句压测 顺序不调整

2.开启关闭求平均值测试发现相差一秒

mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='test' --query=" select * from t100w where k1='Vs'  and num<27779 and k2='mnij'" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

3.索引顺序优化 压测

4.hit方式

5.MRR

nysql> set optimizer_switch='mrr_cost_based=off';  #设置关闭  范围查找才有效果,不能等值

在缓存区read_end_buffer #减少回表次数 优化器自动决战

MRR可用于InnoDB和 MyISAM索引范围扫描和表相等联接的操作。

MRR可以 NDB用于多范围索引扫描的表,或者在按属性执行等值联接时使用。

对于MRR,存储引擎将read_rnd_buffer_size系统变量的值 用作可为其缓冲区分配多少内存的准则。引擎最多使用 read_rnd_buffer_size字节,并确定要在一次通过中处理的范围数。

```

#### 8.索引应用规范

```css

1. mysql截取字符 left 从左至右截取字符

mysql> select count(distinct left(name,5)) from city;

12.1 建立索引的原则(DBA运维规范)

(1) 必须要有主键,业务无关列。

(2) 经常做为where条件列  order by  group by  join on, distinct 的条件(业务:产品功能+用户行为)

(3) 最好使用唯一值多的列作为索引列,如果索引列重复值较多,可以考虑使用联合索引

(4) 列值长度较长的索引列,我们建议使用前缀索引.

mysql> select count(distinct left(name,19)) from city;

(5) 降低索引条目,一方面不要创建没用索引,不常使用的索引清理,percona toolkit(xxxxx)

(6) 索引维护要避开业务繁忙期,建议用pt-osc。

(7) 联合索引最左原则

12.2 不走索引的情况(开发规范)

11.2.1 没有查询条件,或者查询条件没有建立索引

select * from t1  ;

select * from t1 where id=1001 or 1=1;

12.2.2 查询结果集是原表中的大部分数据,应该是15-25%以上。

查询的结果集,超过了总数行数25%,优化器觉得就没有必要走索引了。

MySQL的预读功能有关。

可以通过精确查找范围,达到优化的效果。

1000000

>500000 and

12.2.3 索引本身失效,统计信息不真实(过旧)

索引有自我维护的能力。

对于表内容变化比较频繁的情况下,有可能会出现索引失效。

一般是删除重建

现象:

有一条select语句平常查询时很快,突然有一天很慢,会是什么原因

select?  --->索引失效,统计数据不真实

innodb_index_stats 

innodb_table_stats 

mysql> ANALYZE TABLE world.city;

12.2.4 查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等)

例子:

错误的例子:select * from test where id-1=9;

正确的例子:select * from test where id=10;

算术运算

函数运算

子查询

12.2.5 隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误.

mysql> desc select * from b where telnum=110;

mysql> desc select * from b where telnum='110';

12.2.6 <> ,not in 不走索引(辅助索引)

12.2.7 like "%_" 百分号在最前面不走

```

### 第五章 存储引擎

#### 1.存储引擎介绍

```

相当于linux文件系统,只不过比文件系统更强大

```

#### 2.存储引擎种类

```bash

oracle mysql自带的存储引擎种类

mysql> show engines #查看存储引擎类型

mysql> select @@default_storage_engine; #默认存储类型

请你列举mysql中支持的存储引擎种类

InnoDB MyISAM CSV MEMORY BLACKHOLE

分支产品存储引擎

Percona、Mariadb

TokuDB、MYRocks、ROCKSDB

特点: 1.压缩比15倍以上 2.插入数据性能

myisam 表  t1 

t1.frm  数据字典

t1.myd  数据行

t1.myi  索引

```

#### 3.Innodb功能特性

```css

MVCC: 多版本并发控制

聚簇索引: 用来组织存储数据和优化查询, IOT

支持事务: 数据安全保证

支持行级锁: 控制并发

外键

多缓冲区支持

自适应Hash索引: AHI

复制中支持高级特性

备份恢复,支持热备

自动故障修复: CR Crash Recovery

双写机制: DWB Double Write Buffer

InnoDB 支持: 事务、MVCC、聚簇索引、外键、缓冲区、AHI、CR、DWB,MyISAM不支持。

InnoDB 支持: 行级锁,MyISAM支持表级锁。  

InnoDB 支持热备(业务正常运行,影响低),MyISAM支持温备份(锁表备份)。

InnoDB 支持CR(自动故障恢复),宕机自动故障恢复,数据安全和一致性可以得到保证。MyISAM不支持,宕机可能丢失当前修改。

```

#### 4.TokuDB 功能特性

```bash

1.高达25倍的数据压缩快速插入

2.通过无读复制消除从机延迟

3. 热架构更改、热索引创建-TokuDB表支持插入、删除和查询,而索引添加到该表时没有停机时间

4.Hot column addition,deletion,expansion,and rename—当alter table添加、删除、扩展或重命名列时,TokuDB表支持插入、删除和查询,而不会停机

5.在线备份

```

#### 5.存储引擎查询

```css

1.查询支持的存储引擎

mysql> show engines;

2.查询、设置默认存储引擎

mysql> select @@default_storage_engine;

3.写入配置文件

vim /etc/my.cnf 

default_storage_engine=InnoDB

重启生效

4.查看某张表的存储引擎

mysql> show create table city;

5.查询系统中所有业务表的存储引擎信息

mysql> select

table_schema,

table_name ,

engine

from information_schema.tables 

where table_schema not in ('sys','mysql','information_schema','performance_schema');

6.创建表设定存储引擎

mysql> create table xxx (id int) engine=innodb charset=utf8mb4;

7.修改已有表的存储引擎

mysql> alter table xxx engine=myisam;

mysql> al3ter table world.xxx engine=innodb;

项目:将所有的非InnoDB引擎的表查询出来,批量修改为InnoDB

  mysql> select table_schema,table_name ,engine

  from information_schema.tables 

  where

  table_schema not in ('sys','mysql','information_schema','performance_schema')

  and engine !='innodb';

  mysql> select concat("alter table ",table_schema,".",table_name," engine=innodb;")  from information_schema.tables   

where   

table_schema not in ('sys','mysql','information_schema','performance_schema') and engine !='innodb' into outfile '/tmp/a.sql';

mysql> source /tmp/a.sql

```

#### 6. InnoDB的体系结构

```bash

1.表空间结构:概念源于Oracle数据库 最初的目的是为了能够很好的做存储的内容

## 共享表空间

## 存储方式

ibdata1~ibdataN,5.5版本默认的表空间类型

## ibdata1共享表空间在各个版本的变化

5.5版本:

系统相关:(全局)数据字典信息(表基本结构信息、状态、系统参数、属性..)、UNDO回滚日志(记录撤销操作)、Double Write Buffer信息、临时表信息、change buffer

用户数据: 表数据行、表的索引数据

5.6版本:共享表空间只存储于系统数据,把用户数据独立了,独立表空间管理。

系统相关:(全局)数据字典信息、UNDO回滚信息、Double Write信息、临时表信息、change buffer

5.7版本:在5.6基础上,把临时表独立出来,UNDO也可以设定为独立

系统相关:(全局)数据字典信息、UNDO回滚信息、Double Write信息、change buffer

8.0.11~8.0.19版本:

在5.7的基础上将UNDO回滚信息默认独立,数据字典不再集中存储了。

系统相关:Double Write信息、change buffer

8.0.20版本:在之前版本基础上,独立 Double Write信息

系统相关:change buffer

总结: 对于InnoDB表来讲, 例如 city表

city.ibd

city.frm

只是通过cp备份ibd和frm文件无法实现,数据表的恢复

```

![image-20201111200045401](C:\Users\苗杰\AppData\Roaming\Typora\typora-user-images\image-20201111200045401.png)

![image-20201111200125199](C:\Users\苗杰\AppData\Roaming\Typora\typora-user-images\image-20201111200125199.png)

![image-20201111200205469](C:\Users\苗杰\AppData\Roaming\Typora\typora-user-images\image-20201111200205469.png)

```bash

##共享表空间管理

mysql> select @@innodb_data_file_path;

mysql>  select @@innodb_autoextend_increment;

##独立表空间 show variables like 'innodb_file_per_table';

参数用途: ibdatal文件,默认初始大小12M,不够用会自动扩展,默认每次扩展64M

设置方式:

innodb_data_file_path=ibdata1:12M;ibdata2:100M;ibdata3:100M:autoextend

报错--->实际大小和mc.cnf文件设置12M

### 模拟在初始化时设置共享表空间(生产建议)

5.7 中建议:设置共享表空间2-3个,大小建议1G或者4G,最后一个定制为自动扩展。

8.0 中建议:设置1-2个就ok,大小建议1-4G

# 清理数据

[root@db01 data]# /etc/init.d/mysqld stop

[root@db01 data]# rm -rf /data/3306/data/*

[root@db01 data]# vim /etc/my.cnf

# 修改

innodb_data_file_path=ibdata1:100M;ibdata2:100M;ibdata3:100M:autoextend

# 重新初始化

[root@db01 data]# mysqld --initialize-insecure  --user=mysql --basedir=/usr/local/mysql --datadir=/data/3306/data

# 重启数据库生效

[root@db01 data]# /etc/init.d/mysqld start

#----------------#独立表空间(数据+索引)

## 介绍

5.6版本开始,针对用户数据,单独的存储管理。存储表的数据行和索引。

8.0 之前: city  ---> city.ibd 数据行和索引  city.frm 单表的数据字典  ibdata1 全局的数据字典

8.0 之后  city      city.ibd mysql.ibd 元数据:统计信息和属性(可以理解为系统数据)

通过参数控制:

mysql> select @@innodb_file_per_table;

测试: 共享表空间存储用户数据

mysql> set global innodb_file_per_table=0;

## 利用独立表空间进行快速数据迁移

源端:3306/test/t100w  -----> 目标端:3307/test/t100w

1. 锁定源端t100w表

mysql> flush tables  test.t100w with read lock ;

mysql> show create table test.t100w;

CREATE TABLE `t100w` (

  `id` int(11) DEFAULT NULL,

  `num` int(11) DEFAULT NULL,

  `k1` char(2) DEFAULT NULL,

  `k2` char(4) DEFAULT NULL,

  `dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. 目标端创建test库和t100w空表

mysql> create database test charset=utf8mb4;

CREATE TABLE `t100w` (

  `id` int(11) DEFAULT NULL,

  `num` int(11) DEFAULT NULL,

  `k1` char(2) DEFAULT NULL,

  `k2` char(4) DEFAULT NULL,

  `dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.  单独删除空的表空间文件(5.7版本:保留t100w的frm,ibdata1中关于t100w的系统数据)

mysql> #alter table test.t100w discard tablespace;

4. 拷贝源端ibd文件到目标端目录,并设置权限

[root@db01 test]# cp /data/3306/data/test/t100w.ibd /data/3307/data/test/

[root@db01 test]# chown -R mysql.mysql /data/*

5. 导入表空间

mysql> #alter table test.t100w import tablespace;

mysql> select count(*) from test.t100w;

+----------+

| count(*) |

+----------+

|  1000000 |

6. 解锁源端数据表

mysql> unlock tables;

```

#### 7.undo表空间

```bash

1.作用: 用来作撤销操作

2.存储位置: 5.7版本,默认存储在共享表空间中(ibdataN)8.0版本以后默认就是独立的(undo_001-undo_002)

3.生产建议: 5.7版本后,将undo手工进行独立。

```

#### 7.1 undo配置参数

```bash

SELECT @@innodb_undo_tablespaces;  ---->3-5个  #打开独立undo模式,并设置undo的个数。

SELECT @@innodb_max_undo_log_size;              #undo日志的大小,默认1G。可以调1到4G

SELECT @@innodb_undo_log_truncate;              #开启undo自动回收的机制(undo_purge)。

SELECT @@innodb_purge_rseg_truncate_frequency;  #触发自动回收的条件,单位是检测次数。

SELECT @@innodb_undo_directory                  #INNODB undo日志所在表空间的物理路径,默认路径是数据文件路径

innodb_undo_log_truncate参数设置为1 #即开启在线回收(收缩)undo log日志文件,支持动态设置。

innodb_undo_tablespaces参数必须大于或等于2 #即回收(收缩)一个undolog日志文件时要保证另一个undolog是可用的。

innodb_undo_logs: undo回滚段的数量 #至少大于等于35,默认128。

innodb_max_undo_log_size:#当超过这个阀值(默认是1G)会触发truncate回收(收缩)动作truncate后空间缩小到10M。

innodb_purge_rseg_truncate_frequency:控制回收(收缩)undo log的频率.undo log空间在它的回滚段没有得到释放之前不会收缩,想要增加释放回滚区间的频率,就得降低innodb_purge_rseg_truncate_frequency设定值。

```

#### 7.2 配置undo(5.7和8.0)

```bash

vim /etc/my.cnf

# 添加参数

innodb_undo_tablespaces=3         

innodb_max_undo_log_size=128M

innodb_undo_log_truncate=ON

innodb_purge_rseg_truncate_frequency=32

innodb_undo_directory=/data/3306/undolog/

# 重新初始化数据库生效=

[root@db01 data]# /usr/local/mysql57/bin/mysqld --defaults-file=/data/3357/my.cnf  --initialize-insecure  --user=mysql --basedir=/usr/local/mysql57 --datadir=/data/3357/data

# 启动数据库

[root@db01 data]# /etc/init.d/mysqld start

[root@db01 data]# ll /data/3306/data/undo00*

-rw-r----- 1 mysql mysql 10485760 May  7 15:39 /data/3306/data/undo001

-rw-r----- 1 mysql mysql 10485760 May  7 15:39 /data/3306/data/undo002

-rw-r----- 1 mysql mysql 10485760 May  7 15:39 /data/3306/data/undo003

#如果进行undo独立存储到其他文件系统

a. 关闭数据库:

[root@db01 data]# systemctl start mysqld3357

b.设定路径参数

innodb_undo_directory=/data/3357/undologs

c. 创建目录,并拷贝文件

[root@db01 data]# systemctl stop mysqld3357

mkdir -p  /data/3357/undologs

chown -R mysql. /data/*

cp -a /data/3357/data/undo* /data/3357/undologs

# 注: 8.0 undo表空间与5.7稍有区别,可参考:

https://dev.mysql.com/doc/refman/8.0/en/innodb-undo-tablespaces.html

a.  innodb_undo_tablespaces参数不再使用,可以直接按需添加undo

mysql> CREATE UNDO TABLESPACE oldguo_undo_003 ADD DATAFILE 'undo_003.ibu';

b. 查询undo

SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES

  WHERE FILE_TYPE LIKE 'UNDO LOG';

c. 删除

ALTER UNDO TABLESPACE oldguo_undo_003 SET INACTIVE;

DROP UNDO TABLESPACE oldguo_undo_003;

```

#### 7.3 临时表空间

```bash

1.作用: 存储临时表 ------>大查询、或排序等 尽量设置大一点也可以多一点 默认12M

2.管理: innodb_temp_data_file_path=ibtmp1:12M;ibtmp2:128M:autoextend:max:500M  ---重启生效

3.建议数据初始化之前设定好,一般2-3个,大小512M-1G    ------------------5.6之前在ibdata1 之后独立于ibtmp1

#临时表说明

临时表空间不像普通InnoDB表空间那样,不支持裸设备(raw device)。#--------没有初始化的特殊块设备文件

临时表空间使用动态的表空间ID,因此每次重启时都会变化(每次重启时,都会重新初始化临时表空间文件)。

当选项设置错误或其他原因(权限不足等原因)无法创建临时表空间时,mysqld实例也无法启动。

临时表空间中存储这非压缩的InnoDB临时表,如果是压缩的InnoDB临时表,则需要单独存储在各自的表空间文件中,文件存放在 tmpdir(/tmp)目录下。

临时表元数据存储在 INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO 视图中。

有时执行SQL请求时会产生临时表,极端情况下,可能导致临时表空间文件暴涨,帮人处理过的案例中最高涨到快300G,比以前遇到的 ibdata1 文件暴涨还要猛…

#临时表使用的几点建议

设置 innodb_temp_data_file_path 选项,设定文件最大上限,超过上限时,需要生成临时表的SQL无法被执行(一般这种SQL效率也比较低,可借此机会进行优化)。

检查 INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO,找到最大的临时表对应的线程,kill之即可释放,但 ibtmp1 文件则不能释放(除非重启)。

择机重启实例,释放 ibtmp1 文件,和 ibdata1 不同,ibtmp1 重启时会被重新初始化而 ibdata1 则不可以。

定期检查运行时长超过N秒(比如N=300)的SQL,考虑干掉,避免垃圾SQL长时间运行影响业务。

```

#### 8. InnoDB 事务日志

```bash

#rego log 重做日志

1.作用: 记录内存数据页的变化.实现"前进"的功能.WAL(write ahead log),MySQL保证redo优先于数据写入磁盘。

2.存储位置: 数据路径下 /data/3306/data/ib_logfile0、ib_logfile1 轮训覆盖记录日志

ib_logfile0  48M    一般情况下1-4G,个数默认两个,一般三到五个

ib_logfile1  48M    每个事务1-2k,够不够一秒使用,可以算公司繁忙时间需要的日志再设置大小.一个节点4个G.

```

#### 8.1 redo log重做日志

```bash

(1)文件位置 /data/3306/id_logfile0

mysql> show variables like '%innodb_log%'; #查看日志参数

(2)控制参数 innodb_log_file_size=55331648  #设置文件大小

          innodb_log_files_in_group=2    #设置文件个数

          innodb_log_group_home_dir=./    #设置存储位置

(3)功能: 存储,mysql在做insert update delete 修改类(DML) 操作时的数据页变化过程及版本号(LSN) #属于物理日志-------------------默认两个文件存储redo,循环覆盖使用

1.查询redo log文件配置

mysql> show variables like '%innodb_log_file%';

2.设置

生产建议:

大小: 512M-4G

组数: 3-5组

vim  /etc/my.cnf

# 添加参数:

innodb_log_file_size=100M

innodb_log_files_in_group=3

#重启生效

[root@db01 data]# /etc/init.d/mysqld restart

[root@db01 data]# ll /data/3306/data/ib_logfile*

-rw-r----- 1 mysql mysql 104857600 May  7 16:17 /data/3306/data/ib_logfile0

-rw-r----- 1 mysql mysql 104857600 May  7 16:17 /data/3306/data/ib_logfile1

-rw-r----- 1 mysql mysql 104857600 May  7 16:17 /data/3306/data/ib_logfile2

```

#### 8.2 undo log 回滚日志

#### 8.3 disk memory结构

```bash

1.# ib_buffer_pool 预热文件

作用: 缓冲和缓存,用来做“热”(经常查询或修改)数据页,减少物理IO。

当关闭数据库的时候,缓冲和缓存会失效。

5.7版本中,MySQL正常关闭时,会将内存的热数据存放(流方式)至ib_buffer_pool。下次重启直接读取ib_buffer_pool加载到内存中。

mysql> show variables like '%shutdown%';

mysql> select @@innodb_buffer_pool_dump_at_shutdown;  #关闭

mysql> select @@innodb_buffer_pool_load_at_startup;    #加载

2.# Double Write Buffer(DWB) 双写缓冲区  (8.0.19之前 默认在ibdataN中,8.0.20以后可以独立了。)

oranle 直接和磁盘对接,不需要文件系统.直接操控裸盘.

写真实数据页之前,先让写到顺序的区域里,成功后再写真实数据页.宕机可以在DWB上找到好的页面副本

/data/3306/data/#ib_16384_0.dblwr

作用:

MySQL,最小IO单元page(16KB),OS中最小的IO单元是block(4KB)

为了防止出现以下问题:

mysqld process exit in the middle of a page write, InnoDB can find a good copy of the page from the doublewrite buffer during crash recovery.

mysqld进程退出在页面写入过程中,InnoDB可以在崩溃恢复期间从doublewrite缓冲区找到一个好的页面副本。

#3.内存结构---微观

数据内存区域:

3.1 共享内存区域

  #InnoDB buffer pool (IBP) 缓冲区池

作用: 用来缓冲、缓存,mysql的数据页和索引页.mysql中最大的、最重要的内存区域

管理、查询:

mysql> select @@innodb_buffer_pool_size;

默认大小: 128M

生产建议: 物理内存的:50-80%。

在线设置: mysql> set global innodb_buffer_pool_size=268435456;

重新登录mysql生效。

永久设置: vim /etc/my.cnf

#添加参数

innodb_buffer_pool_size=256M

    重启生效:

    /etc/init.d/mysqld restart

    mysql> select @@innodb_bufffer_pool_instances;  #默认为1

    事务会话访问内存结构,可以多块内存同时并发访问,内存较大,一般为4,8-16 instances,提高并发度.

3.12 #InnoDB LOG BUFFER (ILB)

作用: 用来缓冲 redo log日志信息。

管理 :

  查询:

mysql> select @@innodb_log_buffer_size;

    默认大小:16M

生产建议:和innodb_log_file_size有关,1-N倍

    设置方式: vim /etc/my.cnf innodb_log_buffer_size=33554432

    重启生效:  /etc/init.d/mysqld restart

3.2 会话内存缓冲区

join_buffer_size

key_buffer_size

read_buffer_size

read_rnd_buffer_size

sort_buffer_size

```

![image-20201112223138278](C:\Users\苗杰\AppData\Roaming\Typora\typora-user-images\image-20201112223138278.png)

#### 9.InnoDB核心特性-事务

```bash

1.介绍: 交易 事务可以保证,将所有一项交易涉及到SQL,要么全成功,要么全失败.

2.事务的ACID特性

#Atomicity(原子性) ----一个事务一个完整整体,不可再分

一个事务中所有的AML语句要么全执行成功,要么全失败

#Consistency(一致性) ----事务工作前,中.后,数据最终一致

只要提交成功的事务,数据保证最终一致

#Isolation(隔离性) ----多事务工作过程不会被影响

#Durability(持久性) ----已经提交的事务,保证日志落盘(数据不一定落盘)

3.事务的生命周期

标准事务控制语句 begin 开启事务 commit 提交 rollback 回滚

start transaction ==== begin  必须是DML语句 select insert update delete

mysql> use test;

mysql> begin;

mysql> select * from t100w limit 5;

mysql> update t100w set num=110 where id=1;  #改第一行数字为110

mysql> delete from t100w where id=5;  #删除第五行内容

mysql> rollback; #回滚之前操作

mysql> commit; #提交 结束当前的生命周期 提交过的事务不能回滚

4.自动提交机制(autocommit)默认开启 #mysql> select @@autocommit;

不进行begin操作,逐条提交

5.隐式提交

导致提交的非事务语句:

DDL语句: (ALTER、CREATE 和 DROP)

DCL语句: (GRANT、REVOKE 和 SET PASSWORD)

锁定语句:(LOCK TABLES 和 UNLOCK TABLES)

导致隐式提交的语句示例:

truncate table

#load data infile

SELECT for update

6.隐式回滚

会话窗口被关闭、数据库关闭、出现事务冲突(死锁)

7.事务的隔离级别

  a.介绍 读的隔离--->数据页的加载过程

  b.级别类型: RU、RC、RR、SE(SR)  ----->越往上,事务并发度越低,读的性能越好.

  READ-UNCOMMITTED 读未提交;

  READ-COMMITTED 读已提交(可以用);

  REPEATABLE-READ 可重复度(默认);

  SERIALIZABLE 串行读;

  RU: 事务并发度最高 脏读、不可重复读、幻读

  RC: 防止了脏读,事务并发度较好 不可重复度、幻读

  RR: 防止了脏读和不可重复读 事务并发度一般、幻读

  SE: 隔离性最好,问题读都ok  事务不能并发,只能串行

默认隔离级别RR,互联网大部分场景RC级别

8.设置隔离级别

select @@transaction_isolation; (默认RR):

设置方法: a.set global transaction_isllation='read-committed';

b.写入配置文件重启.

9.脏读、不可重复读、幻读介绍

#a.脏读

设置隔离级别为:'READ-COMMITTED'

mysql> set global transaction_isolation='READ-COMMITTED';

mysql> set global autocommit=0;

重新开启两个session;

mysql> select @@transaction_isolation;

mysql> select @@autocommit;

两个窗口同时begin 开启事务时,一个改了update num=119,还没提交,但另一个窗口会直接显示119,出现脏读的现象.

#b.不可重复读

设置隔离级别为:'READ-UNCOMMITTED'

mysql> set global transaction_isolation='READ-UNCOMMITTED';

mysql> set global autocommit=0;

#在同一个会话当中,对于同一个值有不一样的结果,互联网现象可以容忍.

#c.幻读

#两个会话中,第一个临时改之前,第二个直接插入新的.看到一的还会看到二的.

还原段用途:

事务处理回退——当某事务处理修改表中某行时,被修改的列的旧映像(要还原的数据)将存储在还原段中。如果将该事务处理回退,则Oracle 服务器通过将还原段中的值写回到该行来恢复原始值。

事务处理恢复——如果例程在事务处理正在进行时失败,那么Oracle 服务器需要在数据库再次打开时还原所有未提交的更改。这种回退操作是事务处理恢复的一部分。之所以有可能恢复事务处理,原因在于对还原段所做的更改同样受重做日志文件的保护。

读一致性——在事务处理正在进行时,数据库中的其他用户不应看到这些事务处理所做的任何未提交更改。此外,也不应从某条语句中看到该语句开始执行后所提交的任何更改。还原段中的旧值(要还原的数据)也可用于为读者提供给定语句的一致映像。---

```

#### 10.事务工作远程原理

```css

ACID特性如何保证

1.名词介绍: 重做日志(red log)

  磁盘: ib_loggile0~N  innodb_log_file 大小 innodb_log_in_froup 组数

  内存: innodb_log_buffer innodb_log_buffer_size 大小

2.表数据:

  磁盘: 独立表空间 XXX.ibd----> segment extents pages 段 区 页

  内存: innodb buffer pool innodb_log_buffer_size

3.日志序列号LSN----数据页变化的版本 一个顺序递增的数字 redo日志的变化量(字节)

a. LSN有哪些:

    redo buffer  Log sequence number          101963574

    redo log    Log flushed up to            101963574

    数据页       Last checkpoint at          101963574

b.查询方式: show engine innodb status \G

4.WAL(write ahead log)日志先行

  commit提交事务时,保证日志先写磁盘,数据后写

  Dirty Page 在内存中修改的数据页,没写到磁盘的叫做脏页.

  Check Point 检查点 将脏页刷新到磁盘的动作 #检查点触发,将内存中的脏页刷到磁盘中去

  DB_TRX_ID  (6字节) #重要  ++++++++++> 事务ID号  存储在数据页头部  隐藏的

  DB_ROLL_PTE (7字节) #重要  ++++++++++> 回滚指针  存储在数据页头部  隐藏的

1.事务中的I特性

# 锁机制: 写的隔离 作用: 保护并发访问资源

# 保护资源分类: latch(闩锁) rwlock、mutex,主要保护内存资源

table_lock: 表级别

lock table t1 read ;

mysqldump、XBK(PBK):备份非InnoDB数据时,触发FTWRL全局锁表(Global)。

行锁升级为表锁。

row lock:InnoDB 默认锁粒度,加锁方式都是在索引加锁的。

record lock : 记录锁,在聚簇索引锁定。RC级别只有record lock。

gap lock    : 间隙锁,在辅助索引间隙加锁。RR级别存在。防止幻读。

next lock  : 下一键锁, GAP+Record。    RR级别存在。防止幻读。

# 如何监控锁问题?

  mysql> select * from sys.innodb_lock_waits\G

# 功能性上:

IS  : select * from t1 lock in shared mode;

S    : 读锁。           

IX  :  意向排他锁。表上添加的。 select * from t1 for update;

X    :  排他锁,写锁。

# MVCC : 多版本并发控制

乐观锁: 乐观。

悲观锁: 悲观。

每个事务操作都要经历两个阶段:

# 读:  乐观锁。

MVCC利用乐观锁机制,实现非锁定读取。

read view:RV,版本号集合。

trx1 :

begin;

dml1  ---> 在做第一个查询的时候,当前事务,获取系统最新的:RV1 版本快照。

dml2  ---> 生成 RV2 版本快照。

select  查询  RV2 快照数据

commit; ---->  RV2 快照数据  ----》系统最新快照。

RC

trx1: Rv1  Rv2  commit;

trx2 RVV1 RVV1 RV2

RR

trx1 : 第一个查询时, 生成global consitence snapshot  RV-CS1(10:00) ,一直伴随着事务生命周期结束。

trx2 :  第一个查询时,生成global consitence snapshot  RV-CS2(10:01) ,一直伴随着事务生命周期结束。

快照技术由undo log来提供。

# 写: 悲观锁 X

总结:

1. MVCC采用乐观锁机制,实现非锁定读取。

2. 在RC级别下,事务中可以立即读取到其他事务commit过的readview

3. 在RR级别下,事务中从第一次查询开始,生成一个一致性readview,直到事务结束。

===========================

事务的ACID: redo  undo  dwb  cr  mvcc lock  ISO

```

案例

```bash

#案例一:

某期学员负责: 运维 + MySQL 工作

1.1 环境: zabbix 3.2  +  centos 7.3  +  mariaDB 5.5 InnoDB引擎  ,zabbix系统 监控了2000多个节点服务

1.2 现象 : 每隔一段时间zabbix卡的要死 , 每隔3-4个月,都要重新搭建一遍zabbix,存储空间经常爆满.

1.3 问题 :

1.3.1. zabbix 版本过低

1.3.2. 数据库版本

1.3.3 zabbix数据库500G,存在一个文件里ibdata1,手工删除1个月之前的数据,空间不释放。

1.4 优化建议:

1.4.1.数据库版本升级到percona 5.7+ 版本 mariadb 10.x+,zabbix升级更高版本

1.4.2.存储引擎改为tokudb

1.4.3.监控数据按月份进行切割(二次开发:zabbix 数据保留机制功能重写,数据库分表)

1.4.4.关闭binlog和双1

1.4.5.参数调整....

优化结果:

监控状态良好

参考:

https://www.jianshu.com/p/898d2e4bd3a7

1.4.6 #为什么?

(1) 原生态支持TokuDB,另外经过测试环境,5.7要比5.5 版本性能 高  2-3倍

(2) TokuDB:insert数据比Innodb快的多,数据压缩比要Innodb高

(3)监控数据按月份进行切割,为了能够truncate每个分区表,立即释放空间

(4)关闭binlog ----->减少无关日志的记录.

(5)参数调整...----->安全性参数关闭,提高性能.

扩展:部署 zabbix新版+ 新版本 tokudb  VS  部署  zabbix + 低版本mariadb

参考内容:

https://www.jianshu.com/p/898d2e4bd3a7

https://mariadb.com/kb/en/installing-tokudb/

https://www.percona.com/doc/percona-server/5.7/tokudb/tokudb_installation.html

#案例二:

利用表空间迁移功能实现数据损坏恢复

案例背景:

硬件及软件环境: 联想服务器(IBM), 8核16G 磁盘500G 没有raid

centos 6.8 mysql 5.6.33 innodb引擎 独立表空间

备份没有,日志也没开

开发自用专用库:

jira(bug追踪) 、 confluence(内部知识库)    ------>LNMT

故障描述:

断电了,启动完成后“/” 只读

fsck 重启,系统成功启动,mysql启动不了。

结果:confulence库在  , jira库不见了。

学员求助内容:

求助:

这种情况怎么恢复?

我问:

有备份没

求助:

连二进制日志都没有,没有备份,没有主从

我说:

没招了,jira需要硬盘恢复了。

求助:

1、jira问题拉倒中关村了

2、能不能暂时把confulence库先打开用着

将生产库confulence,拷贝到1:1虚拟机上/var/lib/mysql,直接访问时访问不了的

问:  有没有工具能直接读取ibd

我说:我查查,最后发现没有

我想出一个办法来:

表空间迁移:

create table xxx

alter table  confulence.t1 discard tablespace;

alter table confulence.t1 import tablespace;

虚拟机测试可行。

处理问题思路:

confulence库中一共有107张表。

困惑1:

1、创建107和和原来一模一样的表。

他有2016年的历史库,我让他去他同时电脑上 mysqldump备份confulence库

mysqldump -uroot -ppasswrd -B  confulence --no-data >test.sql

################

万一是自研数据库,怎么办?又没备份,那怎么办?

mysql工具包,mysqlfrm 读取frm文件获得表结构。

################

2、表空间删除。

select concat('alter table ',table_schema,'.'table_name,' discard tablespace;') from information_schema.tables where table_schema='confluence' into outfile '/tmp/discad.sql';

source /tmp/discard.sql

执行过程中发现,有20-30个表无法成功。主外键关系

很绝望,一个表一个表分析表结构,很痛苦。

set foreign_key_checks=0 跳过外键检查。

把有问题的表表空间也删掉了。

3、拷贝生产中confulence库下的所有表的ibd文件拷贝到准备好的环境中

select concat('alter table ',table_schema,'.'table_name,' import tablespace;') from information_schema.tables where table_schema='confluence' into outfile '/tmp/import.sql';

4、验证数据

表都可以访问了,数据挽回到了出现问题时刻的状态

```

双一

```bash

#innodb_flush_log_at_trx_commit

提交事务的时候将 redo 日志写入磁盘中,所谓的 redo 日志,就是记录下来你对数据做了什么修改,比如对 “id=10 这行记录修改了 name 字段的值为 xxx”,这就是一个日志。如果我们想要提交一个事务了,此时就会根据一定的策略把 redo 日志从 redo log buffer 里刷入到磁盘文件里去。此时这个策略是通过 innodb_flush_log_at_trx_commit 来配置的,他有几个选项。

值为0 : 提交事务的时候,不立即把 redo log buffer 里的数据刷入磁盘文件的,而是依靠 InnoDB 的主线程每秒执行一次刷新到磁盘。此时可能你提交事务了,结果 mysql 宕机了,然后此时内存里的数据全部丢失。

值为1 : 提交事务的时候,就必须把 redo log 从内存刷入到磁盘文件里去,只要事务提交成功,那么 redo log 就必然在磁盘里了。注意,因为操作系统的“延迟写”特性,此时的刷入只是写到了操作系统的缓冲区中,因此执行同步操作才能保证一定持久化到了硬盘中。

值为2 : 提交事务的时候,把 redo 日志写入磁盘文件对应的 os cache 缓存里去,而不是直接进入磁盘文件,可能 1 秒后才会把 os cache 里的数据写入到磁盘文件里去。

可以看到,只有1才能真正地保证事务的持久性,但是由于刷新操作 fsync() 是阻塞的,直到完成后才返回,我们知道写磁盘的速度是很慢的,因此 MySQL 的性能会明显地下降。如果不在乎事务丢失,0和2能获得更高的性能。

# 查询

select @@innodb_flush_log_at_trx_commit;

select @@sync_binlog;

sync_binlog

#该参数控制着二进制日志写入磁盘的过程。

该参数的有效值为0 、1、N:

0:默认值。事务提交后,将二进制日志从缓冲写入磁盘,但是不进行刷新操作(fsync()),此时只是写入了操作系统缓冲,若操作系统宕机则会丢失部分二进制日志。

1:事务提交后,将二进制文件写入磁盘并立即执行刷新操作,相当于是同步写入磁盘,不经过操作系统的缓存。

N:每写N次操作系统缓冲就执行一次刷新操作。

将这个参数设为1以上的数值会提高数据库的性能,但同时会伴随数据丢失的风险。

二进制日志文件涉及到数据的恢复,以及想在主从之间获得最大的一致性,那么应该将该参数设置为1,但同时也会造成一定的性能损耗。

```

lvs

```

[root@lb01 ~]#yum -y install ipvsadm

[root@lb01 ~]#ipvsadm -A -t 10.0.0.3:80 -s rr

[root@lb01 ~]#ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.7:80 -g

[root@lb01 ~]#ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.8:80 -g

```

### 第六章 日志管理

#### 1.普通日志

```css

1.介绍:默认是关闭的. 可以记录MySQL中发生过的所有操作日志.一般用来调试.

2.如何配置:

general_log = ON

general_log_file  = /data/3306/data/db01.log

3.作用: 审计和调试

```

#### 2.错误日志

```css

1.介绍: 记录数据库从启动以来,状态,报错,警告.

2.查询和配置:

mysql> show variables like '%error%';

log_error = ./db01.err

log_error_verbosity=3

mysql> set global log_error_verbosity=3;

3.怎么用:

每天定时巡检、主要关注 [ERROR] , [WARNING]

```

#### 3.二进制日志

#### 1.介绍

```bash

以event形式,记录MySQL数据库中变更类的操作日志(DDL  DCL  DML).

```

#### 2.作用: 数据恢复、复制

#### 3.配置

```bash

mysql> show variables like '%bin%';

log_bin=1

log_bin_basename=/data/3306/data/binlog

sync_binlog=1

binlog_format=row/statement/mixed

彩蛋1:  sync_binlog=1 是双一期中一个1.保证事务提交理解刷新binlog到磁盘.

彩蛋2:  binlog_format=row/statement/mixed

格式区别: 

1. row (RBR)      : 记录每个数据行的真实变化. 日志量会比较大.记录足够准确.

update t1 set num=20 where id<10;


    2. statement(SBR)  : 记录发生的是语句.日志量相对少.记录有可能不准确.

3.  mixed 混合模式

binlog_format 只影响DML语句.DDL和DCL都是Statement

```

#### 4.binlog 应用

```bash

1.查看和分析binlog

mysql> show binary logs;

mysql> show master status ;

mysql> show binlog events in 'binlog.000007';

[root@db01 data]# mysqlbinlog binlog.000007

[root@db01 data]# mysqlbinlog --base64-output=decode-rows -vvv    binlog.000007  #自动翻译日志

2.数据损坏模拟和恢复

2.1故障模拟:

mysql> flush logs;

Query OK, 0 rows affected (0.01 sec)

mysql> show master status ;

+---------------+----------+--------------+------------------+-------------------+

| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

+---------------+----------+--------------+------------------+-------------------+

| binlog.000008 |      156 |              |                  |                  |

+---------------+----------+--------------+------------------+-------------------+

1 row in set (0.00 sec)

#创建库,表,id------>直接把库删了-----drop database oldboy;

2.2恢复过程

mysql> show master status ;

mysql> show binlog events in 'binlog.000008';

| binlog.000008 |  233 | Query          |        1 |        347 | create database oldboy /* xid=772 */ 

| binlog.000008 | 1448 | Query          |        1 |        1558 | drop database oldboy /* xid=784 */   

[root@db01 data]# mysqlbinlog --start-position=233 --stop-position=1448 /data/3306/data/binlog.000008 >/tmp/bin.sql

mysql> set sql_log_bin=0;

mysql> source /tmp/bin.sql

mysql> set sql_log_bin=1;

```

#### 5.binlog2sql应用

```bash

1.安装 yum -y install python3

2.  vim requirements.tzt

    PyMySQL==0.9.3

wheel==0.29.0

mysql-replication==0.13

3. pip3 install -r requirements.txt

  pip3 show pymysql

```

#### 6.解析日志时间SQL

```css

#单独过滤某张表的binlog

[root@db01 binlog2sql-master]# python3 binlog2sql.py  -h 10.0.0.51 -P3306 -uroot -p123 -d test1 -t t1 --start-file='mysql-bin.000007'

INSERT INTO `test1`.`t1`(`id`) VALUES (1); #start 1647 end 1891 time 2020-09-18 08:46:53 gtid……

#单独过滤某些类型的binlog

[root@db01 binlog2sql-master]# python3 binlog2sql.py  -h 10.0.0.51 -P3306 -uroot -p123 -d test1 -t t1 --sql-type=update  --start-file='mysql-bin.000007'

UPDATE `test1`.`t1` SET `id`=10 WHERE `id`=1 LIMIT 1; #start 4882 end 5141 time 2020-09-18 09:17:35 gtid

#生成指定时间回滚语句

应用场景: 3000万数据 ,误删10行数据,怎么修复  --------- -B闪回

[root@db01 binlog2sql]# python3 binlog2sql.py  -h 10.0.0.51 -P3306 -uroot -p123 -d test -t t1  --start-file='mysql-bin.000003'  --sql-type=delete --start-position=932 --stop-position=1198 -B

[root@db01 binlog2sql]# python3 binlog2sql.py  -h 10.0.0.51 -P3306 -uroot -p123 -d test -t t1  --start-file='mysql-bin.000003'  --sql-type=delete --start-position=932 --stop-position=1198 -B>/tmp/flashback.sql

```

#### 7.GTID应用

```bash

1.介绍

Global  Transaction ID . 全局事务ID.不管有多少个binlog,都是连续生成的.具备幂等性.

1ced0886-23d4-11eb-9768-000c29f4772b:1

server_uuid  :  NO.

2.配置

mysql> show variables like '%gtid%'; 

set global gtid_mode=ON;  #

set global enforce_gtid_consistency=ON; #强制gtid的一致性.已经做过的事,就不会做了.

set global log_slave_updates=1          #主从环境,强制从库进入二进日志强制更新,默认开启

3 基于GTID截取日志

mysqlbinlog --skip-gtids --include-gtids='1ced0886-23d4-11eb-9768-000c29f4772b:1-3' /data/3306/data/binlog.000012 >/tmp/gtid.sql

mysqlbinlog --skip-gtids --include-gtids='1ced0886-23d4-11eb-9768-000c29f4772b:1-3' --exclude-gtids='1ced0886-23d4-11eb-9768-000c29f4772b:2'/data/3306/data/binlog.000012 >/tmp/gtid.sql

#排除第二个,留下1和3.

注意:  如果需要截取的日志需要在原库恢复,需要加--skip-gtids 参数.跳过导出文件gtid的记录.

4.其他管理

4.1日志滚动

show variables like '%expires%';

mysql> flush logs;

mysql> select @@max_binlog_size; 默认1G 字节量

重启数据数据库自动刷新

4.2日志的删除

a . 设置自动过期时间

binlog_expire_logs_seconds  过期时间.默认是一个月.  #时间或文件名进行删除

b . 手工清理

PURGE BINARY LOGS TO 'mysql-bin.010';

PURGE BINARY LOGS BEFORE '2019-04-02 22:46:26';

c . 全部重置  #命令非常危险,主从环境下,从库比泵.

reset master;

```

#### 8.彩蛋

```bash

1. 建库时间太久,日志量太多 , 日志有可能只剩部分了. 怎么破?

备份+binlog可以恢复到.

2. binlog 保存了多个不同库的日志. 只需要期中一个库的日志.怎么办?

mysqlbinlog -d

只需要期中一个表的日志.怎么办?

binlog2sql

3. 一张表10亿行,误删除10行数据. 怎么办 ?

binlog2sql 做数据闪回

4. 我需要的日志跨了多个文件,怎么办?

a.  单独截取多个文件日志,然后合并

binlog.000005    1080  1-3

binlog.000006          4-10

binlog.000007    789    11-12

b. gtid 日志记录模式 ----------5.6版本之后

  根据每个事物加唯一编号

```

#### 4.慢日志(默认不开启)

```css

1.介绍: 记录执行较慢的语句

2.配置:

mysql> set global slow_query_log=on;  #开启慢查询功能

mysql> set global long_query_time=0.01;  #时间,默认记录10秒内的查询

mysql> set global log_queries_not_using_indexes=1; #记录未使用索引的查询

    mysql> show variables like "%query%" ;

mysql> select @@slow_query_log;  是否开启慢查询,ON开启,OFF关闭

mysql> select @@long_query_time; 慢查询时间设置,默认10秒

mysql> select @@log_queries_not_using_indexes;  记录未使用索引的查询

        mysql> select @@slow_query_log_file 慢查询日志存放路径

3.模拟慢语句:时间改为0.0.1左右,将慢日志打开on,且不走索引

4.分析慢日志:

  mysqkdumpslow -s c -t 3 db01-sloe.log  # -s 按照何种方式排序 c 访问计数 -t 返回前面多少条数据

  下载 mysqlsla https://pan.baidu.com/s/1kfBYu49RtdSOhiT4hlvj_A

      1.安装mysqlsla perl Makefile.PL #配置 make #编译 make install #安装

#查询记录最多的10条,可以指定具体的数据库

mysqlsla -lt slow -sort t_sum  -sf  "+select,update,INSERT" -db hunaniptv  -top 10  /var/lib/mysql/mysqld_slow.log

#查询记录最多的20个sql语句,并写到select.log中去

mysqlsla -lt slow --sort t_sum --top 20  /data/mysql/127-slow.log >/tmp/select.log

#统计慢查询文件为/data/mysql/127-slow.log的所有select的慢查询sql,并显示执行时间最长的100条sql,并写到sql_select.log中去

mysqlsla -lt slow  -sf "+select" -top 100  /data/mysql/127-slow.log >/tmp/sql_select.log

#统计慢查询文件为/data/mysql/127-slow.log的数据库为mydata的所有select和update的慢查询sql,并查询次数最多的100条sql,并写到sql_num.sql中去

mysqlsla -lt slow  -sf "+select,update" -top 100 -sort c_sum  -db mydata /data/mysql/127-slow.log >/tmp/sql_num.log

```

你可能感兴趣的:(中级DBA)