导图社区 MySql数据库
MySql数据库思维导,包括MySql架构、存储引擎、索引分类和结构、主从复制、分库列表、锁机等内容。
编辑于2021-12-14 00:08:09MySql数据库
Mysql架构
连接层
连接管理、授权认证、相关的安全方案
服务层
查询解析、分析、优化、缓存以及所有的内置函数
引擎层
数据中的存储与提取,通过api与存储引擎进行通信
存储层
数据存储层,将数据存储在文件系统只上,并完成与存储引擎的交互
整体流程
1.客户端请求
2.连接器(验证用户身份,给予权限)
3.查询缓存
4.分析器(sql的词法分析和语法分析)
5.优化器(选择最优的执行方案)
6.执行器(先查看用户执行权限,再去引擎提供的接口查询)
7.引擎层获取数据
存储引擎
常见存储引擎
InnoDB,MyISAM,Memory,NDB
MyISAM和InnoDB对比
主外键支持
innodb
支持
myISAM
事务
innodb
支持
myISAM
行表锁
innodb
行锁
myISAM
表锁
缓存
innodb
缓存数据和索引,对内存要求较高,而内存大小对性能有决定行的影响
myISAM
只缓存索引
表空间
innodb
大
myISAM
小
关注点
innodb
事务
myISAM
性能
索引
分类
数据结构角度
B+树索引
Hash索引
Full-Text全文索引
R-tree索引
从物理存储角度
聚集索引
非聚集索引,也叫辅助索引
从逻辑角度
主键索引
普通索引或者单列索引
多列索引(联合索引)
唯一索引和非唯一索引
索引空间
索引结构
B-Tree
与B+树核心区别:每一层都可以数据data值
B+Tree
1.非叶子节点只存储键值信息
2.叶子节点都有链指针
3.数据都记录在叶子节点
特点:
每个节点支撑更多的键值信息,减少遍历节点数量(即磁盘数量)
更方便支撑 范围查找
MyISAM主键索引与辅助索引的结构
索引与数据分开,叶子节点放的是数据记录的地址
结构无区别,只是主键索引不能重复
InnoDb的主键索引和辅助索引的结构
主键索引
数据和索引放在一起,要一个主键
为啥推荐自增主键 而非UUID
字符串长度比整形消耗更多存储
查找时,整数型运算速度更快
自增的整数索引在磁盘是连续存储的,数据也是按页存储的,范围查找比较好
新增或插入数据,自增整数意味着尾部插入,不会破坏左侧子树的结构
辅助索引
Hash索引
进行Hash计算
目前memory、NDB数据库支撑
全文索引
解决效率较低下的like 模糊匹配操作
多个字段组合索引一次性全模糊
将字段分割成多个字段在进行索引
R-Tree空间索引
主要用于解决地理空间的索引
问题
为啥Mysql用B+树做索引而B树
B树在节点上挂数据,导致每个节点能够存储的索引数量不够大,就会导致查询多层节点,磁盘IO次数变多
B+在最底层的节点增加指针链表,范围查找
为啥不用Hash方式
使用等值查询场景
不适合范围查找
哪些情况需要创建索引
主键自动创建唯一索引
频繁作为查找条件的字段
外键关系建立索引
联合索引优先于单件索引
排序字段
统计或分组字段
哪些情况不需要创建索引
表记录太少
经常增删改的表
数据重复且分布均匀的表字段
频繁更新的字段不适合创建索引
where条件用不到的字段
Mysql高效索引
覆盖索引
不需要回表
所有需要的字段都在索引中有
查询
count(*),count(1),count(列名)区别
执行效果
count(*)包含所有行,不会忽略列为null
count(1)同count(*)
count(列名),只包含那一列,会忽略列为null时
执行效率
列名为主键时,count(列名)快于 count(1)
列名不为主键时,count(1) 快于count(列名)
in 和exists的区别
执行效果
exsits
对外表用loop逐条查询,返回记录行,有时,则条件为真
in
多个Or条件的叠加
效率
如果两个表大小相当,则一样
如子查询的表大,则用exists
如果子查询的表小,则用in
union 和union all的区别
union会按照字段的顺序进行排序,union all不会排序
union会对数据进行去重
事务
acid
a:原子性:整个事务中的所有操作要么全部成功全部失败
C:一致性:事务前和事务后,数据的完整性约束没有被破坏
I:隔离性:一个事务的执行不能其他事务干扰
D:持久性:事务完成后,事务中所有变更就持久的保存在数据之中,并不会被回滚
并发事务处理带来的问题
丢失更新
同时修改一行,最开始的事务的更新被覆盖了
脏读
事务A读到事务B回滚的变更
不可重复读
事务A多次读取数据的值不一样,主要体验在事务B的提交前后
幻读
读取多行时,增加了几行数据,第二次读会读到上次不存在的记录
解决办法
丢失更新
应该完全避免
需要应用程序对需要更新的数据加锁
脏读、不可重复读、幻读
是数据库事务隔离的机制解决
加锁
MVCC
事务隔离级别
读未提交
可以读取未提交的数据,会产生脏读、不可重复、幻读
读提交
可以读取已经提交的数据,可以解决脏读,不能解决 不可重复读、幻读问题
可重复读
对同一字段多次读取结果是一致的,可解决不可重复读问题,解决不了幻读
串行化
所有事务依次逐个执行,都防的住,效率太低
MVCC多版本并发控制
每行都事务版本号
只在读提交、可重复读两个隔离级别工作
select
只查版本早于当前事务版本的数据,通过redo日志回溯
insert、update
保存当前的系统版本号为行版本号
事务日志
目的
减少提交事务时的开销,无需每次提交事务都刷新脏块到磁盘
因为数据对应到磁盘的位置是随机,提交事务是随机IO
日志将随机IO变成顺序IO,只要日志持久化到磁盘后,即使断电后,也通过重放日志也可以得到数据,也就持久化
write ahead logging
预写日志
后台线程智能的刷新这些变更到数据文件,可以批量组合写入,使得数据写入更顺序
步骤
先将数据修改写到内存中,然后生成一条事务日志
事务日志是追加的方式,因此是顺序IO,写到磁盘,相对随机IO会快很多
事务日志持久化后,内存中被修改的数据可以慢慢刷到磁盘中
数据崩溃时,可以通过事务日志恢复事务的数据
事务的实现
事务的原子性、一致性、持久性都是通过事务日志来实现的
redo log
物理日志
undo log
逻辑日志
Mysql对分布式事务的支持
三个角色
应用AP
资源管理RM
事务管理TM
两阶段提交
所有的事务节点开始准备,告诉事务管理器ready
告诉每个节点commit 还是ready,如果一个节点失败,就需要全局的节点全部rollback
Mysql锁机制
分类
按照数据操作类型分类
读锁
写锁
按数据粒度分
表锁
开销小,加锁快,不会出现死锁;粒度大,冲突效率最高,并发低
行锁
页锁
MyIsam表锁
表共享锁
表独占锁
写锁的优先级更高,会优先给写锁队列中的请求
InnoDb行锁
共享锁
排它锁
两种意向锁-表锁
意向共享锁
意向排他锁
乐观与悲观锁
一般业务version来实现乐观锁
悲观锁由数据自己实现的
innodb三种行锁的算法
记录锁
单行记录加锁,对修改、删除单项有效
select * from t where id =1 for update
间隙锁
使用范围条件时,对索引项之间的间隙加锁,防止插入幻影行
next-key locks
记录锁+间隙锁
解决幻读问题
死锁
两个或多个事务在同一资源上互相占用
检测死锁
死锁恢复
外部锁的死锁检测
死锁影响性能
MyIsam避免死锁
总是一次获得sql需要的所有锁
innodb 避免死锁
如果要更新记录,先申请排他锁,在申请共享锁
如果修改多个表,以相同的顺序加锁
如果先select ...lokn in share mode获得行读锁后,再如果要更新要对该记录进行更新操作,则可能造成死锁
改变事务的隔离级别
MySQL调优
常见瓶颈
cpu:数据装入内存或磁盘读取的时候
IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时间
服务器硬件的性能瓶颈:top,free,iostat,vmstat
常见原因分析
sql写得烂
索引失效
关联查询太多join
服务器调优参数及各个参数设置
慢sql
连接池慢
常见调优手段
explain
查了多少行,走什么索引
慢查询日志
性能优化
索引优化
全值匹配
最佳走匹配法则
不在索引上做函数计算
存储引擎不能使用索引中范围条件右边的列
覆盖索引
like 使用左匹配
字符串不加单引号索引失效
少用or
<>,not in 不会用索引
一般性建议
单建索引尽量选过滤性好的索引
联合索引,讲过滤性好的放在左边
联合索引可以进来包含多个字段的索引
尽量通过分析统计信息和调整query的写法来选择合适的索引
查询优化
小表驱动大表
针对链表
orderby
尽量使用index排序,不要触发filesort
group by
添加索引
数据类型优化
更小的更好
如整形好于字符串
简单就好
char 好于varchar
尽量避免null
分库分表
能干嘛
逻辑数据分割
提高单一的读写速度
提高分区的范围查找的速度
分库分表的难题
数据操作维度问题
跨库联合查询的问题
跨库事务问题
主从复制
三个步骤
master 写bin log日志
slave 将master的bin log 日志拷贝到它的中继日志
salve重做中继日志的事件
基本原则
每个slave只有一个master
每个master可以有多个slave
复制最大的问题
延时
其他的问题
百万级别以上的数据如何删除
先删除索引
再删除无用的百万数据
再重建索引
避免万一删除中断的回滚