一小时总结 -- MySql 知识(一)

一小时总结 – MySql 知识(一)

数据库知识是开发和面试必须掌握的知识,只有了解数据库的脾性才能更好的使用它。

在众多数据库软件里面,Oracle 的性能最强悍,目前基本上还没有 Oracle 一体机跑不动的应用(如果有只能说明你的体量太大或者使用太烂)。MySql 作为免费开源的代表基本上是大中小企业的首选。也是面试和应用中应该掌握的重点。

以下内容为默记整理内容,如存在表述错误表述不准确欢迎指正。

要点:

  • 原理性知识:
    • 整体:MySql 的体系结构;
      • 线程模型:线程连接池;
      • 内存模式:缓冲区;
      • 网络模型:reactor 模型;
      • 文件模型:B+树、binlog 及重做日志
      • 高可用:主从复制、binlog 及重做日志;
    • 扩展原理:MySql 引擎对比;
    • 效能原理:MySql 的索引结构和存储;
    • 实现原理:MySql InnoDB 如何实现事务;
      • InnoDB MVVC 的原理和实现;
      • InnoDB 锁相关知识;
  • 应用性知识:
    • explain 的用法和关注点;
    • 慢查询的查询思路;
    • sql 优化原则;
    • 如何选择合适的存储引擎;

原理性知识

整体:MySql 的体系结构

MySql 整体可分为三层:

  • 连接层:最上层,实现连接管理;
  • ??中间层??:MySql 本身实现的查询缓存、sql 解析、sql 优化器,中间层调用底层存储引擎层的 Api 实现 sql 的执行和优化;
  • 存储引擎层:最底层,可以以插件形式实现 MySql 的文件存储和数据查询;

线程模型:线程池

MySql 采用多线程实现,其内部运行了多个线程,采用统一线程池管理,每个连接的查询发送到 mysql 后,有一个独立线程负责此次 sql 的执行。

内存模型:缓冲区

MySql 采用内存缓冲区的方式提升应用效率,为了降低磁盘 IO 次数,MySql 尽量把热点数据缓存到内存中。

  • 写缓冲:当有数据发生修改后,MySql 采用写缓冲的方式先操作内存数据,待合适时机再将数据修改写入到物理磁盘;
  • IO 合并:MySql 中的很多 IO 为逻辑 IO,逻辑 IO 可能操作的是缓存数据,待合适时机多个逻辑 IO 会被合并为一个物理 IO 进行一次性操作。

网络模型:Reactor 模型

MySql 的网络连接和驱动采用 Reactor 模型管理连接,仅当数据准备充分后再分配线程。

文件模型:B+树、binlog 及重做日志

为了充分利用磁盘特性,尤其是 HDD 磁盘的磁头移动特性,MySql 采用:

  • 使用 矮胖 的 B+ 树作为索引的存储和实现结构,相比 AVL 树 B+ 树有更低的树高度,能有效的减少磁盘 IO 次数,而相对 B 树,B+ 树的搜索效率更稳定,叶子节点的链表指针让范围查询变得更容易和高效,更能充分利用磁盘连续读和操作系统 page cache 特性。
  • binlog 及重做日志:为了尽量减少磁盘 IO,MySql 将数据写入内存缓冲带来的风险是机器掉电带来的数据丢失风险,因此 MySql 设计了 binlog 和重做日志。binlog 和重做日志在设计上采用单文件追加的方式具有更高的刷盘效率。

高可用:主从复制、binlog 及重做日志

MySql 的高可用提现在两个方面:

  • 单机掉电的情况下:可保证的数据一致性;
  • 提供集群容灾策略:主从复制策略,并提供主从数据一致性保证;

单机掉电:

  • 在内存模型中,MySql 为了提升操作效率大部分操作的是内存缓冲数据,为了保证掉电后缓冲数据丢失带来的数据丢失风险,mysql 建立了 binlog 和重做日志机制(InnoDB 机制);
  • binlog 机制:binlog 记录了所有的 sql 操作(select 不记录),利用 binlong 可实现主从复制和宕机重启后的数据恢复。
  • 重做日志:innodb 实现的日志,分为 redo log 和 undo log,redo log ,redo log 记录了尚未刷新到磁盘的数据变化,undo log 记录了事务执行过程产生的事务日志可实现数据回滚。

扩展原理:MySql 引擎对比

MySql 的存储引擎机制让 MySql 本身不 care 数据如何被存储和索引。存储引擎机制让 MySql 可适用多种适用场景:

  • ISAM 和 MyISAM:早期 MySql 官方默认的存储引擎,最早引擎叫 ISAM 后面改名叫 MyISAM,ISAM 是一种算法。MyISAM 引擎的实现简单不支持事务,仅支持表锁但是其数据存储的空间效率高。适合
  • InnoDB:MySql 5.6 后官方默认的引擎,InnoDB 引擎支持事务并扩展实现了行级锁。适合绝大部分 OLTP 应用(增删改查比较均衡的场景)
  • 其他引擎:NDB 等,有些将数据以列方式组织存储,有些将数据全部放到内存中提升效率各有自己的目标应用场景。

效能原理:MySql 的索引结构和存储

基础原理

MySql 的文件分为两类:

  • 表定义文件:这类文件 MySql 本身实现了相关文件的存储;
  • 表数据文件:这类文件 MySql 交给存储引擎去实现相关数据的存储;

索引文件基本上由存储引擎来实现,所有存储引擎基本上使用 B+ 树

MyISAM 的实现

MyISAM 的存储和索引实现比较简单,

  • 表数据:表数据按插入行顺序存储在表文件中;
  • 索引:MyISAM 的索引使用 B+ 树实现,叶子节点存储了行的物理文件指针,通过此指针可以定位到具体行数据。

InnoDB 的实现

InnoDB 的表被称为索引组织表,表数据和索引数据存放在一起;

  • 表数据:表数据按行组织,作为主键索引的叶子节点存放,具体数据表还分为:区、页、端 等;
  • 索引:采用 B+ 树实现,主键索引的叶子节点存储了行数据,非主键索引的叶子节点存储了主键值,因此非主键索引查询非索引值要进行回表操作。

实现原理:MySql InnoDB 如何实现事务

InnoDB 引擎支持 4 级事务,MyISAM 是不支持事务的。InnoDB 采用下面的技术实现了事务的 ACID 特性。

  • 重做日志:采用 redo log 和 undo log 的方式保证事务的一致性和持久性。
  • MVVC 和行锁:实现了事务的隔离性;

为了提升事务的并发效率,InnoDB 采用 MVVC 技术提供了 非锁定读一致性写 的特性。

MVVC 技术

  • MVVC:多版本并发控制技术,简单理解是某行并发操作数据在同一个时刻可能存在多个快照版本,根据事务的隔离级别,InnoDB 会确定此事务可见的数据快照版本。
  • 实现:同时真的维护多个快照版本数据是难以实现的,因此 InnoDB 采用在每行上添加三个字段的方式来实现:创建号、删除号、undo 指针。
  • 快照数据的确定:每个事务都会被分配一个事务 id,事务 id 是严格自增的,在可重复读级别下,某个行在某个事务中是否可见,是通过比较当前事务 id 和行数据的创建号、删除号来决定的,具体确定策略;
    • 行可见:行的删除号 == null && 行的创建号 <= 当前事务号;
    • 新增行:行的创建号 = 当前事务号 && 行的删除号 = null;
    • 删除行:行的删除号 = 当前事务号;
  • 历史版本:如果某个事务并发的修改了其中一行,那么此行的历史版本通过 undo 指针可以从 undo 日志中找到。

  • 行锁:锁定某一行,加了行锁后,其他并发事务会被阻塞;
  • 间隙锁:锁定某一个范围,加了范围锁后,其他并发事务在此范围内操作数据都会被阻塞,间隙锁是一个开区间锁;
  • next key 锁:行锁 + 间隙锁,是一个左闭右开的锁;
  • InnoDB 在读已提交的隔离级别下:加行锁;
  • InnoDB 在可重复读的隔离级别下:加 next key lock;

应用性知识

explain 的用法和关注点;

explain 用来分析 sql 的查询计划,本身 explain 用法比较复杂,实际应用中要关注的点很多,但是很多点要关联起来看,一般来说,某个 SQL 的效率可以通过下面几个点来关注:

  • keys:是否走了索引;
  • extra:是否有 using file sorted 和 using temporary;
  • rows:查询出来的数据是否过大;

慢查询的查询思路

慢查询并不一定等于慢 sql,慢查询先要定位是否是慢 sql:

  • 是否慢 sql:查看 mysql 的慢 sql 日志,如果慢 sql 的阈值不理想可调整阈值后再观察;
  • 如果慢 sql 日志出现了记录,则分析相关 sql,如果没有则问题查询方向要改为关注 mysql 连接层和网络状况。

mysql 连接层和网络状态

  • 先确认 mysql 的压力:是否连接过载很大,导致大部分应用连接没有及时获得 thread 陷入了等待,结合 top 等命令查询;
  • 排除 mysql 的压力,确认网络状况是否良好,可以使用 tcpdump 抓包,确定是否有 tcp 重传或者网络抖动带来的网络大面积延迟。通过 trace 等命令确定某个网关路由是否有问题,通过 ping 、telnet 来确认业务主机和 mysql 的网卡是否有问题。

慢 sql 确定

慢 sql 的主要确认方式是通过 explain 来分析 sql 效率,并结合 sql 优化原则来优化自己的 sql 达到理想执行效率。

sql 优化原则

  • 尽量做到索引覆盖:做到索引覆盖则可以避免 mysql 的回表操作;
  • 减少不必要的字段查询:可以缩小数据包增强网络传输效率;
  • 查询要走索引:走索引则可以快速过滤不必要的数据,减少全表扫描,减少数据的 IO 次数,具体做法:
    • 避免索引字段为 null 的查询;
    • 做到最左前缀匹配,尽量去除 like ‘%a%’ 的查询;
    • 用 exist 替代 in 操作,尤其是 in 的值过多的情况;
  • 使用预编译语句:预编译语句不仅能避免 sql 注入还可以加快查询效率,避免每次的 sql 解析,还能充分帮助数据库命中查询缓存。

如何选择合适的存储引擎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章