一、背景
mysql是后端开发最常用的数据库,本篇记录常用的mysql后端知识,意在更好在后端工程中使用mysql,并不在于探究mysql的实现;为达成熟练使用的目标,我们需要熟悉mysql相关知识如下;
二、相关知识点
2.1 执行流程
一条SQL的执行主要包括以下几个步骤:
- mysql client向连接器发起连接,连接时会进行身份认证,权限认证;
- 随后 client向后端发起SQL查询,连接器先验证查询的缓存中是否存在相同查询,若存在直接返回;(要求身份相同,否则产生数据越权)
- SQL经过分析器,将SQL转化成逻辑计划,并验证计划的有效性;
- 逻辑计划,经过优化器,优化后SQL,执行效率更高(主要有RBO和CBO)
- 优化后的执行计划交给执行器,执行器结合底层引擎;
- 若是DML语句,底层引擎会先操作的数据加载入内存,修改row的值,更新redo log
- 执行引擎 写binlog
- 提交事务
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通过回滚链的方式来进行实现
长事务表示系统中存在很老的事务视图。由于视图链中的数据都有可能会被访问到,所以在事务提交之前,事务长链需要被保留;
2.4.1 锁
mysql的锁根据锁住的资源不同可以分为,表锁和行锁,通常DDL都会增加表锁;Innodb才支持行锁;
mysql死锁的处理方式:超时处理,主动检测
2.4.2 幻读
下图分别记录了幻读产生条件,简单来说幻读就是在同一个事务中,使用相同filter,查看到了不相同的结果视图
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会根据数据量和索引请的情况优先选择使用索引排序,之后根据内存情况,是否载入整个row(全字段排序),否则之后会多一次回表(rowId排序);
2.5.3 mysql join
- Index Nested-Loop Join
- Block Nested-Loop Join
如上图所示,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如何保证主备一致
-
mysql的binlog具有statement和row格式,在binlog使用row格式的时候,binlog记录的是根据主键ID操作记录,可避免主备更新删除不一致的问题;
-
切换策略