Mysql 常用知识

152 阅读5分钟

一、背景

mysql是后端开发最常用的数据库,本篇记录常用的mysql后端知识,意在更好在后端工程中使用mysql,并不在于探究mysql的实现;为达成熟练使用的目标,我们需要熟悉mysql相关知识如下;

二、相关知识点

2.1 执行流程

mysql执行流程.png 一条SQL的执行主要包括以下几个步骤:

  1. mysql client向连接器发起连接,连接时会进行身份认证,权限认证;
  2. 随后 client向后端发起SQL查询,连接器先验证查询的缓存中是否存在相同查询,若存在直接返回;(要求身份相同,否则产生数据越权)
  3. SQL经过分析器,将SQL转化成逻辑计划,并验证计划的有效性;
  4. 逻辑计划,经过优化器,优化后SQL,执行效率更高(主要有RBO和CBO)
  5. 优化后的执行计划交给执行器,执行器结合底层引擎;
  6. 若是DML语句,底层引擎会先操作的数据加载入内存,修改row的值,更新redo log
  7. 执行引擎 写binlog
  8. 提交事务

2.2 索引

索引类型

  • hash索引:主要应用于等值查询场景,查询速度快,O(1)
  • B+树索引:可以满足范围查询,O(logn)
  • Bimap索引:应用有限枚举类型的字段,等值查询,O(1)

自增索引好处

  • 主键索引使用B+树,插入新数据时保证不会产生页分裂,导致写放大
  • 自增索引通常会更短,查询时性能更好

覆盖索引

  • 使用覆盖索引在查询时命中索引,直接从索引中获取需要的数据(索引下推),可以避免回表操作,也就是Mysql Server多一次向存储引擎获取数据详情

最左前缀原则

  • 联合索引是由多个字段拼接而成,只有在左边字段命中的情况下,后边的字段才会有意义

聚簇索引和非聚簇索引

  • 数据文件本身就是按B+Tree组织的一个索引结构是聚簇索引,比如innodb的主键索引
  • 另外生成索引文件,叶子节点保存指向record地址;其他的索引

2.3 存储

2.3.1 DELTE数据过程

innodb使用B+树组织保存的数据,B+树是平衡的,平均每一次的查询是Olog(N);Delete命令其实只是把记录的位置,或者数据页标记为了“可复用”,但磁盘文件的大小是不会变;
经过大量的删改的表,可能存在很多空洞,去掉这些空洞,需要重建表;

2.4 事务

事务是AICD四个特性中的隔离性,描述多个线程同时操作数据库,产生行为,期望在保持尽量高的并发情况下,各个线程的操作相互不影响;Mysql通过回滚链的方式来进行实现 mysql 事务实现机制.png 长事务表示系统中存在很老的事务视图。由于视图链中的数据都有可能会被访问到,所以在事务提交之前,事务长链需要被保留;

2.4.1 锁

mysql的锁根据锁住的资源不同可以分为,表锁和行锁,通常DDL都会增加表锁;Innodb才支持行锁;
mysql死锁的处理方式:超时处理,主动检测

2.4.2 幻读

下图分别记录了幻读产生条件,简单来说幻读就是在同一个事务中,使用相同filter,查看到了不相同的结果视图 幻读造成死锁.png

2.5 优化

2.5.1 mysql对count(*)的优化

  • count(id) InnoDB引擎会遍历整张表,把每一行的id值都取出来,返回给server层。server层拿到id后,判断是不可能为空的,就按行累加
  • count(1) InnoDB引擎遍历整张表,但不取值。server层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。单看这两个用法的差别的话,你能对比出来,count(1)执行得要比count(主键id)快。因为从引擎返回id会涉及到解析数据行,以及拷贝字段值的操作。
  • count(*) 也不取值,按行累加

2.5.2 mysql对order by的优化

mysql排序流程.png 如果是索引已经排好顺序,就更加简单,直接回表取数即可; mysql会根据数据量和索引请的情况优先选择使用索引排序,之后根据内存情况,是否载入整个row(全字段排序),否则之后会多一次回表(rowId排序);

2.5.3 mysql join

  • Index Nested-Loop Join
  • Block Nested-Loop Join mysql Join流程.png 如上图所示,Index Nested-Loop Join效率会比普通的Block Nested-Loop Join效率高很多;但即使是使用Block-Nested-Loop Join,我们也期望小表去转大表,这样可以降低整体Row的扫描次数;

2.5.4 查询慢例子

索引字段增加函数,导致计划无法优化命中索引,比如t_modified有索引页不会用到;

select count(*) from tradelog where month(t_modified)=7; 

隐式类型转换,如下sql中, 若字段traceid类型是varchar(32),那么则不会触发索引

select * from tradelog where tradeid=110717;

2.6 mysql集群

2.6.1 mysql如何保证主备一致

  1. mysql的binlog具有statement和row格式,在binlog使用row格式的时候,binlog记录的是根据主键ID操作记录,可避免主备更新删除不一致的问题;

  2. 切换策略

mysql主备切换流程.png