MySQL体系结构

image.png

image.png

thread pool是在连接层处理

image.png

这里的授权是这个用户对某个表某个列是否有权限

image.png

image.png

查询缓存是全局锁 不建议使用查询缓存

关闭查询缓存:

query_cache_type=0

query_cache_size=0

2个参数都要设置

 

mysql proxy 是在最开始的连接层

handlersocket,可以绕过连接层,sql层,直接操作Innodb存储引擎所以效率非常高,后来基本上都不使用了,NOSQL流行起来了

经典的mysql体系结构图

2.jpg

  • 最前端的是各种语言与mysql相互连接的API或者是接口协议

  • 连接的pool,mysql不支持 只是用这个来表示 可以用自己开的proxy 或者是官方的proxy实现

  • SQL Interface :接收用户所有的sql指令

  • 解析器(Parser):把sql命令解析 (YACC这个语法解析器来解析sql语法)

    • 将SQL语句分解成数据结构,并将这个结构传递到后续步骤,以后SQL语句的传递和处理就是基于这个结构的。

    • 如果在分解构成中遇到错误,那么就说明这个sql语句是不合理的。

  • Optimizer查询优化器

  • 查询缓存

    • query_cache, key_bufer,  innodb_buffer

  • 再下面一层是存储引擎层-插拔式

Cache&Buffer的组成

image.png

上面的框:tmp_table_size & max_heap_table_size 线程创建分配 这个是会话级的内存结构

下面的框:全局内存,程序启动就分配,只分配一次,全局公用

PGA如果分配过高,可能会导致OOM(内存溢出)

mysql使用总内存=global buffers + thread_buffers

image.png

image.png

MySQL innodb引擎和myisam的引擎执行对比测试

http://www.itpub.net/thread-1902289-1-1.html

MySQL 利用硬件资源特点

CPU的利用特点

  • <5.1 多核心支持较弱

  • 5.1 可以利用4个核

  • 5.5 可以利用24个核

  • 5.6 可以利用64个核

  • 每个连接对应一个线程,每个并发query只能使用到一个核

内存利用特点:

  • 类似ORACLE的SGA,PGA模式,注意PGA不宜分配过大

  • 内存管理简单,有效。在高TPS,高并发环境下,可增加物理内存以减少物理IO,提高并发性能

  • 官方分支锁并发竞争比较严重,MariaDB,Percona进行优化

  • 有类似ORACLE library cache的query cache,但效过不佳,建议关闭

  • 执行计划没有缓存(类似ORACLE library cache)

  • 通常内存建议按热点数据总量的15%-20%来规划,专用单实例则可以分配物理内存的50%~70%左右

  • 类似K-V简单数据,采用memcached,Redis等NOSQL来缓存

磁盘

  • undo log的I/O特征:顺序写,随机读

  • Redo log,Binlog的I/O特性:顺序写,顺序读

  • 数据文件的I/O特性:随机写,随机读

  • OLTP业务以随机IO为主,建议加到内存,尽量合并随机IO为顺序IO

  • OLAP业务以顺序IO为主,极大内存的同时增加硬盘数量提高顺序IO性能

  • MyISAM是堆组织表(HOT),InnoDB是索引组织表(IOT)

  • InnoDB相比MyISAM更消耗磁盘空间

Mysql metadata lock(MDL)

metadata lock5.5.3 引入

当事务访问处理过程中执行DDL操作将会等到metadata lock执行完毕才能操作

如果没有访问这个表 是可以被ddl操作的

没数据的情况下可以ddl操作

在事务里不要用DDL 有隐式提交 

:会话2执行drop 操作 wait 再开会话3执行select也是操作不了的 要等会话2的drop执行完了才能查询

所以很容易把线上库卡住

解决办法:kill掉 drop

线上DB不要轻易做alter table 

在生产中做DDL操作时请冷静思考一下


演示:

begin这里只是为了模拟事务

如果事务中一个sql跑的很慢也会出现这种情况

我开启了2个会话

image.png

在会话1里申明一个显示的事务

在会话2里drop leo_copy表

image.png

就会看到这个时候drop不掉le_copy表

state是“Waiting for table metadata lock”

FLUSH TABLES WITH READ LOCK 和 LOCK TABLES比较

1、FLUSH TABLES WITH READ LOCK

这个命令是全局读锁定,执行了命令之后所有库所有表都被锁定只读。一般都是用在数据库联机备份,这个时候数据库的写操作将被阻塞,读操作顺利进行。解锁的语句也是unlock tables。

2、LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}

这个命令是表级别的锁定,可以定制锁定某一个表。例如: lock  tables test read; 不影响其他表的写操作。解锁语句也是unlock tables。

这两个语句在执行的时候都需要注意个特点,就是 隐式提交的语句。在退出mysql终端的时候都会隐式的执行unlock tables。也就是如果要让表锁定生效就必须一直保持对话。

3、MYSQL的read lock和wirte lock

read-lock:  允许其他并发的读请求,但阻塞写请求,即可以同时读,但不允许任何写。也叫共享锁

write-lock: 不允许其他并发的读和写请求,是排他的(exclusive)。也叫独占锁

MYSQL mysqldump备份实验

0. meta data lock实现(mysql 5.5后引入的)

http://blog.leokim.cn/2017/05/25/mysql-metadata-lockmdl/

1.分析muysqldump流程

2. 利用mysqldump做备份建一个从库(online不停业务)
3. 理解binary log在备份中的作用
4. 利用全备+binary log恢复到某个时间点
==========
5. 利用innobackupex 做备份及恢复 3307, 3306
6. 利用innobackupext做增备及恢复 3307, 3306
7. 利用innobackupex加binary log恢复到某个时间点

8. 表空间传输5.6, 5.5

扩展知识:

9. 关于mysql 5.5以下mysqlbinlog(第三方版本)的闪回
10. mysql binary logs格式浅析

DDL没办法在事务里保护

blob.png

/usr/local/mysql/bin/mysqldump -S /tmp/mysql_3306.sock –master-data=2 –single-transaction leokim >leokim_1_full.sql

GTID下可以不要"–master-data=2"这个参数

more leokim_1_full.sql

blob.png

blob.png

 人生就这么悲剧了,数据没了,这个时候就需要恢复

需要注意在dump的时候如果是gtid会有一个SET @@GLOBAL.GTID.PURGED 会直接报错

blob.png

mysql -S /tmp/mysql_3306.sock leo_bak<leokim_1_full.sql

 

blob.png

利用全备恢复 但是少了我们全备后添加的memcache

blob.png

在全备文件里找到master_log_pos = 858

所以我们在binlog里找到858这个位置 恢复从这个位置开始 到truncate之间的数据就可以了

blob.png

blob.png

mysqlbinlog -v --base64-output=decode-rows --start-position=858 --stop-position=1149  mybinlog.000001 > 1_bak.sql
use leokim
rename table leo to leo_bak;
rename table leo_bak.leo to leo;
select * from leo;

blob.png

mysqlbinlog --start-position=858 --stop-position=1062  mybinlog.000001 | mysql -S /tmp/mysql_3306.sock

现在看mongodb就恢复出来了

blob.png

如果开启了gtid 要reset master之后再做才行,gtid会认为自己已经做过了就不会恢复

所以恢复要找个别的地方恢复 然后再恢复到主库上 不能在主库上reset master

在测试库里回复完了单独做一次mysqldump 然后到出来放到生产库里恢复

gtid开启的话 要加上-f强制执行

或者加上–set -gtid-purged=OFF

有GTID的环境里做恢复特别要小心

binlog恢复一定要按顺序恢复不能跳着恢复

 

 

MYSQL 备份

blob.png

blob.png

blob.png

blob.png

blob.png

·  不完全备份(上面少写了)

冷备:把机器关掉 copy数据库文件

热备(hot backup):在数据是运行中,进行的备份

增倍:在上一次备份的基础上做一个增加的备份,今天相对于昨天的变更备份

不完全备份:只备份一张表两张表

blob.png

ntsqldump单进程不太完美

mydumper多进程 sql层备份

xtrabackup基本上大家都在用

在有slave的情景下为什么还要有备份?

人为误操作 在主库上truncate table 从库上也会执行truncate table

mysql 5.6引入delay replication

可以指定从库和主库延迟多长时间 比如说一小时 一小时内主库上有误操作可以不同步到从库上

sql_thread 执行同步 不应用就行了

blob.png

只备份一个表的话只有select权限就可以 如果要一致性就要有lock tables权限

涉及到存储过程和视图就要把show view 和 trigger权限都给上 要不然会报错权限不足

blob.png

造成问题:

  1. 热数据冲掉

  2. 冷数据加载 备份时间长

blob.png

–trigger=false(2个减号)

-t –no-create-info(Don't write table createion info. 不要创建schema) 

-d  不要数据只要表结构

-R存储过程

-n 不要创建库

-E  event 

-f 重置备份

建议每个分开备份 

特别对于数据文件单独放

如果数据库不超过100G 并且内存又很大 可以使用

如果已经100G 内存只有16G 就不要考虑使用mysqldump了

考虑的场景是内存和数据差不多的场景采取用 如果超过3倍以上就不要考虑了 

因为用起来太慢了

blob.png

会有一个问题 如果这个表没有id字段会报错

所以加上where条件的话 要明确这个条件和表是有内容的

mysqldump -t –where="id<10" db1 tb1

这样可以简单的从一个表里拿到一部分去做测试方便拿到子集

DDL不受事务管理 保护不了一致性

一致性快照:拿到一个数据在某一时间一致性的数据 t1时间的备份拿到t1时间的镜像

–set-gtid-purged 会带着gtid的值 表明多少gtid之前的不要了 这样一个标识

默认dump出来的代码:insert into tb1 values(),();

-c参数之后变成:insert into tb1(c1,c2,c3) values(c1,c2,c3);

会变成一个完整的格式,支持对原来表结构进行修改

-h:host

-u :用户

-P:端口号

-p:密码

blob.png

blob.png

不同版本的mysqldump变化很频繁

–replace -> replace into

blob.png

后面再演示

利用mysqldump备份有什么问题?

要注意:

1. 数据的内存的比例

2.mysqldump备份很慢,热数据冲掉冷数据加载时间过程备份时间过长

3.建议只备份数据量小的

4.Innodb表 –single-transanction可以不锁表

5.mysqldump还是单进程的(mydumper多线程并行sql层备份  https://launchpad.net/mydumper)

blob.png

还是基于sql层的备份

blob.png

blob.png

blob.png

mysql本身官方的东西太弱了

很多优秀的东西都是开源的

工具:percona-tools

备份:xtrabackup

监控:zabbix


blob.png

Xtrabackup 是类似于官方的企业备份工具 完全开源

Hot Onloine backup tool for MYSQL

图里的Memory是Innodb Buffer Pool

数据更新时 

1.把数据文件拉到内存更新 

2.把日志写到redo log

3.更新完了再把数据回写到data file里

在一个完整的事务环境保护下作了redo undo相应措施

redo 是为防止在update更新时没有完全提交 崩掉了 可以通过redo 来恢复到数据文件里

image.png

这个16K 是代表page size 可以自己定义

从data file里拿到内存的是page size的大小 这个就是操作最小单位
比如说以下示例:

    select * from user where user_id=100;

    除了会把user_id=100的page全读取到buffer pool里

    还会预读后面的内容 每次取满page size大小

    最小单位基于page size 5.6可以调整

    这个时候就体现出key value缓存的好处

    key value缓存就是一条记录缓存不是基于page的缓存

    没有预读直接获取准确值

    innodb_buffer_pool_size 是基于page的缓存

    每次操作读回来的大小是page size效率上会比key value缓存慢

blob.png

innodb crash recovery

如果更新中挂掉了 可以通过redo log恢复

100G 库 5.5引入innodb fast crash recovery 2,3分钟恢复

5.1之前要很久(1个多小时) 可以在errorlog里可以看到进度

blob.png

在内存里备份的时候先形成xtrabackup log

把数据库的任何变成以redo log的形式写入到xtrabackup log文件里

在这里面把数据文件全部copy走

任何变更都在这个文件里有了

相当于在内存挂掉之后用redo log恢复一下做一次crash recovery恢复

很快把数据文件恢复出来

Xtrabackup其实就时利用innodb的crash recovery原理

blob.png

blob.png

数据恢复是经过内存在内存里合并写入到数据文件里

对一个业务很繁忙的系统备份出来xtrabackup log很大 不要再高峰时间备份

fast recovery 的逻辑

  1. 依赖于redo log(redolog会记录哪个page变更,之后能得到一个page no)

  2. 拿到page no把数据(原始页)从备份的数据里读到内存里

  3. 拿到内存之后修改合并

  4. 持久化到数据文件

blob.png

blob.png

XtraBackup 2.4.1 GA版本发布,终于支持了MySQL 5.7的物理备份

tokudb不支持 可能会按非事务引擎来备份


blob.png

innodb/xtradb可以hot backup

myisam非事务引擎都是要加锁的

blob.png

innobackupex 是调用xtrabackup

中间2个会影响效率不建议使用

xtrabackup不会copy *.frm (表结构文件)

blob.png

ibdata里有什么数据?

1、system tablespace(系统表空间)
ibdata files包含:(共享表空间文件)
(1)、internal data dictionary:数据字典
(2)、insert buffer:插入buffer
(3)、rollback segments:回滚表空间
(3)、undo pages:回滚页
(4)、Double write buffer:写入缓冲区

(5)、undo tablespace 

参照叶的课程

mysql 5.6 引入了一个特性: undo tablespace可以独立配置

blob.png

  1. 先形成xtabackup log文件记录内存里的变更

  2. copy innodb数据文件 .ibd , ibdata1

  3. 设置读锁为了一致性

  4. copy表空间,表结构等文件

  5. 拿到binlog位置

  6. 释放锁

  7. 停掉copy 结束

全事务引擎的–no-lock

blob.png

在做这个的时候是调用xtrabackup来copy的

blob.png

/etc/my.cnf /etc/mysql/my.cnf

/usr/local/mysql/etc/my.cnf

如果不是标准安装需要制定配置文件

指定备份目录

innobackupex –defaults-file=/path/my.cnf /backup/to/path/

依赖变量:

datadir 

socket

如果当前用户连不到mysql里需要提供用户密码

–user=

–password=

–host=

–port=

–apply-log

备份完之后会形成backup-my.cnf

blob.png

数据库刚开始备份时形成xtrabackup_info

xrtabackup_binlog_info: 获得binlog位置show master status的输出

–apply-log之后会形成

xtabackup_slave_info

xtrabackup_binlog_post_innodb

一般情况下xrtabackup_binlog_info应该和xtrabackup_binlog_post_innodb 是相等的

如果不相等以xtrabackup_binlog_post_innodb 为准

xtrabackup_logfile是最早形成的

backup-my.cny有数据库的redu log大小定义

blob.png
    blob.png

blob.png

这里没有gtid比较不爽 不知道现在有没有(https://sanwen8.cn/p/22b9Mii.html)

blob.png

这是测试环境里没有写入 to_lsn和last_lsn是一样的

如果在live里写入会很多 to_lsn和last_lsn会差很大

lsn是log sql no在系统show  engine innodb status\G里面输出

blob.png

其实就是字节大小

blob.png

blob.png

ibdata1:100M:autoextend

被同事改成了1G 

已经完成初始化后,再改,然后重启能不能启动?为什么?

实际的datafile 大于1G可以起来小于1G起不来

ibdata1:10M:autoextend

改小可以起来

因为:定义的值要<=实际的文件 关键在autoextend 只要比定义值小就起不来 大就没问题

innodb_log_file_in_group :log个数

innodb_log_file_size :log大小

这2个参数关系到重新做apply log(好像是这个听的不是太清楚)的时候需要把这2个初始化出来

blob.png

innodb_log_file_size

5.5要重新导入导出重建数据库

5.6可以修改重启就可以了

untitled.bmp

blob.png

指定上一次备份的文件在哪

blob.png

拿到之后主要是找xtabackup_info 找上一次备份的last_lsn找到后把大于这个lsn的data page全部copy一遍,copy到下图位置

blob.png

得到lsn后也可以有偷懒的做法 在做增量备份之前可以指定last_lsn在哪,在这个地方直接指定一个lsn就可一直接备份增量也不用指定上个备份目录在哪,这个做法就是大于这个lsn的page全把他copy一份

这样就是简单的做了一个增量

blob.png

blob.png

恢复:

full_1

incr_1

incr_2

如果incr_1 增量坏了

那就悲剧了

blob.png

data-page, index-page

更紧凑备份:只要data-page不要index-page

恢复的时候要重建index-page

blob.png

innodb_file_per_table:独立表空间

blob.png

include-tables-file=/path/tblist.txt //指定备份哪些表

–database //指定备份哪个库

blob.png

恢复的时候要多一个-export,会多一个tb.exp

紧凑备份

好处是减少备份集,备份小一点

blob.png

紧凑备份恢复的时候要索引重建

blob.png

恢复的时间会比平常时间多好几倍时间 因为索引要重建

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

blob.png

blob.png

export之后除了之前的tb_a.frm, tb_ibd

会生成一个tb_a.cfg

然后把这个文件scp到远程空间上 或者scp到需要导入的那台机器上

导入的机器上需要创建一个同样的表结构

需要把当前表空间干掉blob.png

干掉之后如果没有表空间导进来的话就完蛋了

tb_a.ibd 表空间删掉了

把表空间import进来: alter table tb_a  import tablespace;

这个特性是MySQL 5.6引入的

blob.png

blob.png

基本每天一个全被+每天备份相应的binlog

比如:

早上4点做全备

4点前的binlog也要copy一下

通过天全备+今天的binlog 备份

可以还原到昨天的备份到今天任何一个时间点的备份

还原到今天某个时间点需要什么东西呢?

昨天凌晨4点的全量到今天凌晨4点的全量是什么呢? 是今天今天4点的binlog

重要的放到HDFS上

blob.png

MySQL分区

blob.png

SQL优化的核心:

减少I/0

把随机IO转成顺序IO

分区唯一的场景:用来记日志

blob.png

mysql hash分区 要求分区表达式必须是整数

range, list, hash

blob.png

show variables like "%partition%";

mysql 5.1 开始支持分区

blob.png

SELECT * FROM `PLUGINS` WHERE PLUGIN_NAME LIKE '%partition%'\G

mysql的分区比oracle差距很大 很弱

好处是从官方手册里直接翻译过来的,老师说不要用分区哈哈哈哈

特别不重要的地方才用分区,比如说日志

blob.png

delete from tb where add_date<'';

数据量太大删除不掉

用分区drop很方便

alter table tb drop partition p1;

blob.png

5.6种可以自动判断不用显示声明

innodb必须有主键

主键又必须在你的分区表达式里

blob.png

blob.png

range(year(add_datetime))

range columns(date(add_datetime))

partition p0 values less than ('2017-01-01'),

blob.png

blob.png

blob.png

list就是一个集合(有限的集合)

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png

子分区名字不能重复

blob.png

blob.png

blob.png

blob.png

blob.png

group_concat长度有限制 可以修改

show global variables like "%group%";

blob.png

入果只命中一个效率最高

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png 

blob.png

blob.png

blob.png

blob.png

blob.png

mysql partition没有全局索引,所以索引都在自己的ipdate里放

一个分区一个索引没有完整性

blob.png

blob.png

mysql分区没有全局索引

分区能不能达到行级锁呢?

如果要有行级锁需要针对主键或者针对唯一索引

那么这个主键或者唯一索引就有一个条件必须在分区表达式里面

range 必须by primary key 或者 unique key

如果条件能去where的主键或者unique key那么能做行级锁

如果不能基本上是去锁到一个很大的区间

分区表包括mysql的表在select期间是不能去修改表的结构的

在执行代码的过程中是锁定的

锁定表的结构

这个是由存储引擎来处理不允许更改表结构

因为这个锁是存储引擎自己来处理的 所以每个存储引擎处理的方式也不同

myisam就是全局的锁等待

innodb通过不断重试去拿锁

每个分区都是一个存储引擎的实例 他们都有自己的ibdata

blob.png

其实对锁的粒度还是挺粗的 动不动就是一个range 锁

blob.png

不能对临时表进行分区 上面ppt日志写错了

blob.png

大部分都是时间函数,Mysql就是提倡对时间类的数据进行分期的

可用,但不可以委以重任

blob.png

不要再更改sql model

MYSQL基于复制业界的一些新技术

blob.png

blob.png

blob.png

master挂了

现在要提升slave为master 要做一些同步对比

以下要熟记,是最基础的

第一: 要确认自已是同步完成的 

master_log_file == relay_master_log_file 和read_master_log_pos =exec_master_log_pos

第二: 要确认slave1和slave2是相等的

slave1.master_log_file == slave2.master_log_file || slave1.master_log_pos == slave2.master_log_pos

第三: 让slave2 change 到slave1上

slave1(在即将成为master的slave上): 上执行一个show master status;

如果是GTID的直接change过去就OK了

show processlist查看master上的slave(和此文无关)

slave2: 执行一下show slave status;

slave2 : stop slave; change master ; start slave; show slave status;

reset slave; 清掉本地的relay log , 把同步调整到起始位置

blob.png

字典表

比如说 地理信息

blob.png

blob.png

多机房同步

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png

blob.png

选择proxy:

这个proxy有没有维护了,自已能不能维护