面试总结十一:MySQL
文章目录
- 一、MySQL 基础
- 1.1 数据库三范式
- 1.2 MySQL 组成
- 1.3 MySQL 查询操作
- 1.4 MySQL 查询缓存
- 1.5 MySQL MVCC
- 1.6 MySQL 更新操作
- 二、MySQL 索引
- 2.1 MySQL 索引
- 2.2 MySQL 索引类型
- 2.3 MySQL 索引的优缺点
- 2.3.1 优点
- 2.3.2 缺点
- 2.4 MySQL 索引的数据结构
- 2.4.1 MySQL B+Tree 索引
- 2.4.2 MySQL 为什么选用 B+Tree
- 2.4.3 MySQL Hash 索引
- 2.4.4 MySQL Hash 索引缺点
- 2.5 MySQL 索引的查询速度
- 2.6 MySQL 索引的创建时机
- 2.6.1 什么情况下适合创建索引
- 2.6.2 什么情况下不适合创建索引
- 2.7 MySQL 索引的失效情况
- 2.8 MySQL 索引下推优化
- 2.9 MySQL 索引下推优化限制
- 三、MySQL 引擎
- 3.1 MySQL 存储引擎
- 3.2 InnoDB 的特性
- 3.2.1 插入缓冲(insert buffer)
- 3.2.2 二次写(double write)
- 3.2.3 预读(read ahead)
- 3.3 InnoDB与MyISAM的区别
- 四、MySQL 主从和事务
- 4.1 MySQL 主从复制
- 4.2 MySQL 主从复制流程
- 4.2.1 主节点log dump线程
- 4.2.2 从节点I/O线程
- 4.2.3 从节点SQL线程
- 4.3 MySQL 主从复制模式
- 4.3.1 异步模式
- 4.3.2 半同步模式
- 4.3.3 全同步模式
- 4.4 MySQL 事务
- 4.5 MySQL 事务的特性
- 4.6 MySQL 事务产生的问题
- 4.7 MySQL 事务的隔离级别
- 4.8 MySQL 分布式事务
- 五、MySQL 锁机制
- 5.1 MySQL 锁概述
- 5.1.1 从对数据操作的类型分
- 5.1.2 从对数据操作的粒度分
- 5.2 MySQL 锁机制
- 5.3 MySQL 内部锁
- 5.4 MySQL 间隙锁
- 5.5 MySQL 乐观锁
- 5.6 MySQL 悲观锁
- 5.7 MySQL InnoDB 引擎行锁实现
- 5.8 MySQL 死锁问题
- 5.8.1 MySQL 死锁的情况
- 5.8.2 MySQL 死锁预防方法
- 5.8.2 MySQL 死锁解决方法
- 5.9 MySQL 锁的优化
- 六、MySQL 日志
- 6.1 MySQL 日志类别
- 6.2 事务日志
- 6.3 二进制日志
- 6.4 错误日志
- 6.5 查询日志
- 6.6 慢查询日志
- 6.7 redolog 和 undolog
- 6.7.1 redolog
- 6.7.2 undolog
- 6.8 MySQL 两阶段提交
- 七、MySQL 常见问题和执行计划
- 7.1 MySQL 数据库优化
- 7.1.1 对于SQL优化简单说
- 7.2 MySQL 转换规则
- 7.3 MySQL 关联查询驱动表选择
- 7.4 MySQL 支持emoji表情
- 7.5 MySQL 如何存储IPV6
- 7.6 MySQL跨库Join的解决思路
- 7.7 MySQL CPU 飙升到500%处理
- 7.8 MySQL 执行计划
一、MySQL 基础
1.1 数据库三范式
- 所有属性都不能在分解为更基本的数据单位,每一列属性都是不可再分的,确保每一列的原子性。
- 所有非主属性都完全依赖于每一个候选关键属性,也就是说每一行的数据只能与其中一列相关,即一行数据只做一件事。
- 属性不依赖于其它非主属性,即数据不存在传递关系,每个属性都跟主键有直接关系而不是间接关系。
1.2 MySQL 组成
大体来说MySQL可以分为Server层和存储引擎层两部分。
- Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
- 存储引擎层负责数据的存储和提取,其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。
1.3 MySQL 查询操作
- 客户端先通过连接器连接到 MySQL 服务器,进行权限验证。
- 连接器权限验证通过之后,先查询是否有查询缓存,如果有缓存则直接返回缓存数据,如果没有缓存则进入分析器。
- 分析器会对查询语句进行语法分析和词法分析,判断 SQL 语法是否正确,如果查询语法错误会直接返回给客户端错误信息,如果语法正确则进入优化器。
- 优化器对查询语句进行优化处理,例索引选择等。
- 优化器执行完就进入执行器,执行器则开始执行语句进行查询比对了,直到查询到满足条件的所有数据,然后进行返回。
1.4 MySQL 查询缓存
MySQL查询缓存功能是在连接器之后发生的,它的优点是效率高,如果已经有缓存则会直接返回结果。查询缓存的缺点是失效太频繁导致缓存命中率比较低,任何更新表操作都会清空查询缓存,因此导致查询缓存非常容易失效。
1.5 MySQL MVCC
MVCC 是一种多版本并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问。在 MySQL InnoDB 引擎读已提交和可重复读隔离级别下,事务对于查询操作会访问版本链中的记录,这就使得别的事务可以修改这条记录,因为每次修改都会在版本链中记录,实现了读-写的并发执行,提升了系统的性能。
1.6 MySQL 更新操作
- 客户端通过连接器连接到 MySQL 服务器,进行权限验证。
- 连接器权限验证通过之后,执行器请求存储引擎获取数据,如果数据页在内存中就直接返回执行器,否则就从磁盘中读取并写入内存。
- 执行器获取到该行数据之后执行更新操作,并将操作后的结果写入到存储引擎中。
- 存储引擎将该行数据更新到内存中,同时将更新操作记录到redolog中,此时redolog会处于prepare状态。然后存储引擎会告知执行器执行完毕,可以随时提交事务。
- 执行器生成该操作的binlog日志并写入磁盘。
- 执行器调用存储引擎的提交事务的接口,存储引擎将刚写入的redolog更新为commit状态,更新完成。
二、MySQL 索引
2.1 MySQL 索引
索引(Index)其实是一种数据结构,能够帮助我们快速的检索数据库中的数据。
2.2 MySQL 索引类型
- 主键索引:是一种特殊的唯一索引,而且不允许出现空值。
- 唯一索引:索引列中的值必须是唯一的,索引允许出现空值,一般用来保证数据的唯一性。
- 普通索引:最基本的索引没有任何约束,普通索引列中存在相同的值。
- 联合索引:由对多个列字段按顺序共同组成一个索引,联合索引时需要注意最左前缀匹配。
- 全文索引:全文索引只能在CHAR、VARCHAR、TEXT类型字段上使用,底层使用倒排索引实现。对于大数据量的表,生成全文索引会非常消耗时间也非常消耗磁盘空间。
2.3 MySQL 索引的优缺点
2.3.1 优点
- 索引加快数据的检索速度。
- 唯一索引保证数据库表中的每一行数据的唯一性。
- 加快数据库表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
2.3.2 缺点
- 单表最多支持创建16个索引。
- 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
- 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间。
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。
2.4 MySQL 索引的数据结构
索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有Hash索引、B+Tree索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+Tree索引。
2.4.1 MySQL B+Tree 索引
- B+Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,具有 B Tree 的平衡性,并且通过顺序访问指针来提高区间查询的性能。
- 在 B+ Tree 中,一个节点中的 key 从左到右有序排列。
- B+Tree叶子节点可能存储的是整行数据,也有可能是主键的值。
- 索引的叶子节点存储了主键的值的是非主键索引,也被称之为非聚簇索引。
- 索引的叶子节点存储了整行数据的是主键索引,也被称之为聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引,如果没有唯一键,则隐式的生成一个长度为6字节的rowId键来建立聚簇索引。
2.4.2 MySQL 为什么选用 B+Tree
- 二叉树对于某些情况,可能会退化成一个有n个节点的线性链表。
- 平衡树由于维护高度平衡,有时维护平衡所付出的代价比获得的效率收益大。
- 与红黑树相比,B+Tree具有更低的树高。
- B+树的磁盘读写代价更低:由于数据都存储在叶子结点中,因此其内部节点相对较小,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。
- B+树的查询效率更加稳定:由于数据都存储在叶子结点中,所以任何关键字的查找必须从根结点到叶子结点,即关键字查询的路径长度相同,导致每一个数据的查询效率相当。
- B+树更加适合在区间查询:由于数据都存储在叶子结点中,分支结点均为索引方便扫库,只需要扫一遍叶子结点即可。
2.4.3 MySQL Hash 索引
hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据。
2.4.4 MySQL Hash 索引缺点
- hash索引不支持使用索引进行排序。
- hash索引任何时候都不能避免回表查询数据。
- hash索引进行等值查询更快,但是却无法进行范围查询。
- hash索引不支持模糊查询以及联合索引的最左前缀匹配规则。
- hash索引在有大量重复键值的情况下的效率会很低,因为存在哈希碰撞问题。
2.5 MySQL 索引的查询速度
一般情况下,聚簇索引的查询速度会更快,因为聚簇索引的叶子节点存储的是要查询的整行数据,不需要回表。而非聚簇索引的叶子节点存储的是主键的值,需要回表查询需要的数据,非聚簇索引在查询时使用覆盖索引则不需要回表查询数据。
所谓的覆盖索引指的是:一条查询语句的执行结果只需要从辅助索引中就能够取得,不必从数据表中读取,减少磁盘I/O提高效率。
2.6 MySQL 索引的创建时机
2.6.1 什么情况下适合创建索引
- 主键自动创建唯一索引。
- 频繁作为查询条件的字段。
- 查询中的统计、分组和排序字段适合创建索引。
- 查询中与其他表关联的字段,存在外键关系的字段创建索引。
- 高并发下适合创建联合索引,尽量选择区分度高的列作为索引,尽量满足索引的最左前缀匹配。
2.6.2 什么情况下不适合创建索引
- 表记录太少。
- 经常增删改的表。
- where条件中用不到的字段。
- 数据重复且平均分布的表字段。
- 频繁更新的字段不适合创建索引。
2.7 MySQL 索引的失效情况
- 满足最左前缀匹配原则。
- 正则表达式中使用索引会失效。
- 字符串不加单引号会导致索引失效。
- is not null无法使用索引,is nul是可以使用索引。
- 使用不等于(<>或者!=)时无法使用索引会导致全表扫描。
- like以通配符开头%abc会导致索引失效会变成全表扫描。
- 使用or查询会使MySQL放弃索引而全表扫描,可以使用union连接查询。
- 存储引擎不能使用索引中范围条件右边的列,例如:where id > 100 and name = xxx。
- 在索引列上做任何操作:计算、函数、自动或手动类型转换,会导致索引失效而转向全表扫描。
2.8 MySQL 索引下推优化
索引条件下推优化:指定是将与索引相关的查询条件由MySQL的Server层向下传递至存储引擎,由此减少IO次数,是对MySQL使用索引从表中检索行的情况的优化。
这种优化方式是从MySQL5.6开始支持的,MySQL会在取出索引的同时,判断是否可以进行where条件过滤,也就是将where过滤部分放在了存储引擎层,大大减少了上层SQL对记录的索取。ICP支持range、ref、eqref、refor_null类型的查询,当前支持MyISAM和InnoDB存储引擎。
2.9 MySQL 索引下推优化限制
- 触发条件不能下推。
- 引用子查询的条件不能下推。
- 需要整表扫描的情况不能下推。
- 适用于 InnoDB 引擎和 MyISAM 引擎的查询。
- 5.6版本不适用分区表查询,5.7版本后可以用于分区表查询。
- 调用存储过程的条件不能下推,存储引擎无法调用位于MySQL服务器中的存储过程。
- 对于InnDB引擎只适用于二级索引,因为InnDB的聚簇索引会将整行数据读到InnDB的缓冲区,这样一来索引条件下推的主要目的减少IO次数就失去了意义,因为数据已经在内存中了,不再需要去读取了。
三、MySQL 引擎
3.1 MySQL 存储引擎
MySQL的常用引擎有 InnoDB、MyISAM、Memory 等,从 MySQL 5.5.5 版本开始 InnoDB 就成为了默认的存储引擎。
3.2 InnoDB 的特性
- 插入缓冲(insert buffer)
- 二次写(double write)
- 预读(read ahead)
- 自适应哈希索引(ahi)
3.2.1 插入缓冲(insert buffer)
插入缓冲可以提升插入性能,只对于非聚集索引的插入和更新有效。对于每一次的操作不是写到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,如果在则直接插入,若不在则先放到缓存中,再按照一定的频率进行合并,然后再写回磁盘,这样能将多个操作合并为一个操作,减少随机IO带来性能损耗。
3.2.2 二次写(double write)
位于系统表空间的存储区域,用来缓存innodb的数据页从innodb buffer pool中flush之后并写入到数据文件之前,当操作系统或者数据库进程在数据页写磁盘的过程中崩溃,innodb可以在double write缓存中找到数据页的备份而用来执行crash恢复。数据页写入到double write缓存的动作所需要的IO消耗要小于写入到数据文件的消耗,因为此写入操作会以一次大的连续块的方式写入。
3.2.3 预读(read ahead)
InnoDB使用两种预读算法来提高I/O性能:线性预读和随机预读。线性预读着眼于将下一个extent提前读取到buffer pool中,而随机预读着眼于将当前extent中的剩余的page提前读取到buffer pool中。
注: InnoDB以64个page为一个extent。
3.3 InnoDB与MyISAM的区别
- InnoDB支持事物,而MyISAM不支持事物。
- InnoDB支持行级锁,而MyISAM支持表级锁。
- InnoDB支持外键,而MyISAM不支持外键。
- InnoDB不保存总行数,而MyISAM保存总行数。
- InnoDB(MySQL 5.6后支持全文索引)不支持全文索引,而MyISAM支持全文索引。
- InnoDB是聚簇索引,数据文件是和主键索引绑在一起的,MyISAM是非聚簇索引,索引和数据文件是分离的,索引保存的是数据文件的指针。
四、MySQL 主从和事务
4.1 MySQL 主从复制
MySQL 主从复制是指数据可以从一个主节点复制到一个或多个从节点,MySQL 主从复制具有:读写分离、数据备份、高可用HA等用途,默认采用异步复制方式。
4.2 MySQL 主从复制流程
MySQL主从复制涉及到三个线程,一个运行在主节点:log dump thread,其余两个运行在从节点:I/O thread 和 SQL thread
4.2.1 主节点log dump线程
当从节点连接主节点时,主节点会创建一个log dump线程,用于发送binlog的内容,在读取binlog中的操作时,此线程会对主节点上的binlog加锁,当读取完成后锁会被释放。日志读取期间,主节点将改变记录到二进制日志(binary log)中。
4.2.2 从节点I/O线程
当从节点上执行start slave命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的binlog,I/O线程接收到主节点发来的binlog后,将数据保存在本地的中继日志(relay log)中。
4.2.3 从节点SQL线程
SQL线程负责读取中继日志中的内容,解析成具体的操作并执行,将改变应用到自己的数据库中,最终保证主从数据的一致性。
4.3 MySQL 主从复制模式
MySQL 主从复制默认是异步的模式,数据库操作会记录在binlog中,当从节点连接主节点时,会主动从主节点获取最新的binlog文件,并把binlog中的sql relay。
4.3.1 异步模式
主节点不会主动push bin log 到从节点,这样可能会导致failover情况,从节点没有即时的更新主节点的bin log 到本地。
4.3.2 半同步模式
主节点只需要接收到其中一台从节点的返回信息,就会commit,否则需要等待直到超时时间然后切换成异步模式再提交。半同步模式不是mysql内置的,从mysql 5.5开始集成,需要master 和slave 安装插件开启半同步模式。
4.3.3 全同步模式
指主节点和从节点全部执行了commit并确认才会向客户端返回成功。
4.4 MySQL 事务
事务(Transaction)是并发控制的基本单位,是一个操作序列,由一步或几步数据库操作组成,这些操作要么全部执行,要么全部不执行。
4.5 MySQL 事务的特性
ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)。
- 原子性(Atomicity),要么全部执行,要么全部不执行
- 一致性(Consistency),事务的执行使数据库从一种正确状态转化为另一种正确状态。
- 隔离性(Isolation),在事务正确提交之前,不允许把该事务对数据的任何改变提供给其他事务。
- 持久性(Durability),事务提交后,其结果永久保存在数据库中。
4.6 MySQL 事务产生的问题
- 脏读:A事务读取到了B事务未提交的内容,而B事务后面进行了回滚操作。
- 不可重复读:当A事务能读取B事务已经提交的部分,在A事务内的两次查询结果不一样,因为在此期间B事务进行了提交操作(修改)。
- 幻读:A事务在读取某一范围的数据行时,B事务在此期间删除或新增了一条数据,造成A事务出现幻觉(新增或删除)。
4.7 MySQL 事务的隔离级别
- read uncommitted (读未提交):最低级别,任何情况都无法保证。
- read committed (读已提交):可避免脏读的发生。
- repeatable read (可重复读):可避免脏读、不可重复读的发生。
- serializable (串行化):可避免脏读、不可重复读、幻读的发生。
隔离级别最高的是serializable级别,最低的是read uncommitted级别。隔离级别越高,执行效率就越低。MySQL InnoDB 存储引擎默认使用可重复读级别。
4.8 MySQL 分布式事务
InnoDB存储引擎提供了对XA事务的支持,并通过XA事务来支持分布式事务的实现。分布式事务指的是允许多个独立的事务资源参与到一个全局的事务中。事务资源通常是关系型数据库系统,但也可以是其他类型的资源。在使用分布式事务时,InnoDB存储引擎的事务隔离级别必须设置为Serializable。
五、MySQL 锁机制
5.1 MySQL 锁概述
MySQL数据库不同的存储引擎支持不同的锁机制,例如:MyISAM引擎支持表级锁,InnoDB引擎既支持行级锁和表级锁,默认情况下是采用行级锁。
5.1.1 从对数据操作的类型分
- 共享锁:又称读锁,只允许读操作。针对同一份数据,多个读操作可以同时进行而不会互相影响。
- 排它锁:又称写锁,允许读操作和写操作,获取排他锁的事务可以更新数据。
5.1.2 从对数据操作的粒度分
- 表级锁:开销小加锁快,不会出现死锁,锁定粒度大,发生锁冲突的概率高,并发度低。
- 行级锁:开销大加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率低,并发度高。
- 页面锁:开销和加锁时间界于表锁和行锁之间,会出现死锁,锁定粒度界于表锁和行锁之间,并发度一般。
5.2 MySQL 锁机制
InnoDB默认的修改数据语句:update、delete、insert 都会自动给涉及到的数据加上排他锁,select 语句默认不会加任何锁类型,如果加排他锁可以使用 select …for update 语句,加共享锁可以使用 select … lock in share mode 语句。
5.3 MySQL 内部锁
为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁
- 意向共享锁:事务在给一个数据行加共享锁前必须先取得该表的IS锁。
- 意向排他锁:事务在给一个数据行加排他锁前必须先取得该表的IX锁。
5.4 MySQL 间隙锁
使用范围条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的数据记录的索引项加锁。对于键值在条件范围内但并不存在的记录叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁 (next-key-lock)。
5.5 MySQL 乐观锁
乐观锁认为并发并不是每时每刻都在发生,可以通过在数据行加版本的方式来实现,只在提交操作时检查是否违反数据完整性。
5.6 MySQL 悲观锁
悲观锁认为并发是每时每刻都在发生的,因此为了防止并发,在更新数据之前,需要把数据先锁定起来,其他的任务如果想要更新当前数据,需要等待当前的任务完成,通过这样的方式,悲观锁实现了更新数据的串行化,即每个更新语句之间是串联的执行的。
5.7 MySQL InnoDB 引擎行锁实现
- InnoDB行锁是通过给索引项加锁来实现的,InnoDB这种行锁实现特点意味着,只有通过索引条件检索数据,InnoDB才使用行级锁,否则InnoDB将使用表锁。
- 由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。
- 当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,InnoDB会使用行锁来对数据加锁,如果MySQL认为全表扫描效率更高,这种时InnoDB将使用表锁而不是行锁。
5.8 MySQL 死锁问题
5.8.1 MySQL 死锁的情况
- 索引失效引起全表扫描容易产生死锁。
- 事务之间对资源访问顺序的交替可能会产生死锁。
- 并发修改同一记录可能产生死锁。
5.8.2 MySQL 死锁预防方法
- 合理的使用乐观锁和悲观锁。
- 保持事务简短并在一个批处理中。
- 什么锁就做什么事,禁止共享锁上升独占锁。
- 尽量按照相同的顺序进行处理,避免同时锁定多个资源,必须同时锁定多个资源时,要保证在任何事务的执行顺序。
5.8.2 MySQL 死锁解决方法
# 查看分析死锁日志,然后 kill 掉对应的进程
show engine innodb status# 查看在锁的事务,然后 kill 掉对应的进程
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;#查询是否锁表,然后查询进程,然后 kill 掉对应的进程
SHOW OPEN TABLES WHERE In_use > 0;
5.9 MySQL 锁的优化
- 避免读写锁混淆。
- 避免加锁的时间过长。
- 避免间隙锁引起的危害。
- 隔离级别越高锁成本越高。
- 索引失效会引起行锁变表锁。
- 不要三心二意,锁住哪行,就改哪行。
六、MySQL 日志
6.1 MySQL 日志类别
- 事务日志:重做日志redo和回滚日志undo。
- 中继日志(relay log):主从复制使用的日志。
- 二进制日志(bin log):记录所有更改数据的语句。
- 错误日志(error log):记录mysql服务的启停和运行时的正确和错误信息。
- 查询日志(general log):记录mysql服务建立的客户端连接和执行的语句。
- 慢查询日志(slow log):记录所有执行时间超过long_query_time的所有查询或不使用索引的查询。
6.2 事务日志
事务日志是 InnoDB 特有的日志,可以提高事务的执行效率。使用事务日志在修改数据时,只需要修改其内存拷贝即可,然后再把修改行为记录到事务日志中,不用每次都将修改的数据本身持久到磁盘。
事务日志采用追加的方式,因此写日志的操作是磁盘上一小块区域内的顺序I/O,所以事务日志的记录会更快,事务日志持久以后,内存中被修改的数据在后台可以慢慢的刷回到磁盘。
6.3 二进制日志
二进制日志也叫作变更日志,主要用于记录修改数据或有可能引起数据改变的MySQL语句,并且记录了语句发生时间、执行时长、操作的数据等等,通过二进制日志可以查询MySQL数据库中进行了哪些变化。一般大小体积上限为1G。
6.4 错误日志
在MySQL数据库中,错误日志功能是默认开启的,而且无法被关闭。默认情况,错误日志存储在MySQL数据库的数据文件中。
错误日志记录信息:服务器启动关闭信息、运行错误信息、时间调度器运行一个事件时产生的信息、在服务器上启动进程产生的信息。
6.5 查询日志
默认情况,查询日志是关闭的,因为查询日志会记录用户所有的操作,其中还包括增删改查等信息,如果在高并发的环境下会产生大量的信息,导致不必要的磁盘IO,会影响mysql的性能。
6.6 慢查询日志
慢查询日志是用来记录执行时间超过指定时间的查询语句。通过慢查询日志,可以查找出哪些查询语句的执行效率很低,以便进行优化。
6.7 redolog 和 undolog
redolog支持事务的持久性,undolog支持事务的隔离性。
6.7.1 redolog
redolog记录的是新数据的备份,在事务提交前只要将redolog持久化即可,不需要将数据持久化,当系统崩溃时,可以根据redolog的内容,将所有数据恢复到最新的状态。
6.7.2 undolog
undolog用于存放数据被修改前的值,用于实现事务的原子性,在InnoDB存储引擎中,还用undolog来实现多版本并发控制(简称:MVCC)。
在操作任何数据之前,会首先将数据备份到undolog,然后进行数据的更新操作,如果操作出现了错误或者用户执行了rollback语句,系统可以利用undolog中的备份将数据恢复到事务开始之前的状态。
6.8 MySQL 两阶段提交
为了保证redolog和binlog的状态一致性,MySQL采用两阶段提交,也就是将redolog的写入操作分成了两个步骤:prepare和commit:
- 将更新操作记录到redolog中,此时redolog会处于prepare状态。
- 执行器生成该操作的binlog日志并写入磁盘。
- 执行器调用存储引擎的提交事务的接口,存储引擎将刚写入的redolog更新为commit状态。
七、MySQL 常见问题和执行计划
7.1 MySQL 数据库优化
- 高:从SQL优化、索引优化入手,优化慢SQL、利用好索引,是重中之重;
- 中:SQL优化之后,是对数据表结构设计、横纵分表分库,对数据量级的处理;
- 低:通过修改数据库系统配置,最大化里用服务器内存等资源;
- 低:通过以上方式还不行,那就是服务器资源瓶颈了,加机器。
优化成本:硬件 > 系统配置 > 数据库表结构 > SQL及索引。
优化效果:硬件 < 系统配置 < 数据库表结构 < SQL及索引。
7.1.1 对于SQL优化简单说
- 最大化利用索引:使用覆盖索引,避免回表
- 尽可能避免全表扫描:避免索引失效
- 减少无效数据的查询:避免 select * 操作
7.2 MySQL 转换规则
在 MySQL 数据库中,字符串和数字做比较的话,是将字符串转换成数字,无法转换成数字的字符串都被转换成0来处理了。
7.3 MySQL 关联查询驱动表选择
- 如果从语句方面考虑,这两个表谁放前面都一样,优化器会调整顺序选择合适的驱动表。
- 如果从优化器实现考虑,每次在树搜索里面做一次查找都是log(n),所以对比的是100log(10000)和10000log(100)哪个小,显然是前者,所以结论应该是让小表驱动大表。
7.4 MySQL 支持emoji表情
MySQL数据库的默认字符集UTF-8,只能存储3个字节的数据。标准的emoji表情是4个字节,插入字符集为UTF-8的数据库会报错。如果要支持emoji表情,则需要更换字符集为UTF-8mb4。
7.5 MySQL 如何存储IPV6
- mysql5.6开始,可以直接使用inet6_aton()函数来转换。
- 直接保存字符串,可读性最好但浪费了不少的存储空间。
- 将IPV6转换为long数组后再存储,节约了存储空间但可读性较差。
7.6 MySQL跨库Join的解决思路
- 字段冗余:这是一种典型的反范式设计,通常是为了性能来避免 join 查询。
- 系统层组装:在系统层面,通过调用不同模块的组件或者服务,获取到数据并进行字段拼装。
- 全局表:有可能系统中所有模块都可能会依赖到的一些表。为了避免跨库 join 查询,我们可以将这 类表在其他每个数据库中均保存一份。
- MySQL跨库如何保证事务的一致性:微服务的解决方案引入了消息队列来进行处理。
7.7 MySQL CPU 飙升到500%处理
- 多实例的服务器,先top查看是那一个进程,哪个端口占用CPU多
- show processlist 查看是否由于大量并发,锁引起的负载问题。
- 查看慢查询日志,找出执行时间长的sql,explain分析sql是否使用索引进行优化。
- 查看是否缓存失效引起,查看buffer命中率。
7.8 MySQL 执行计划
id
select查询的序列号,表示查询中执行顺序,id相同时执行顺序由上至下,id不同时值越大优先级越高越先被执行。
select_type
查询的类型,主要是用于区别普通查询、联合查询、子查询等的复杂查询。
- SIMPLE:简单的 select 查询,查询中不包含子查询或者UNION。
- PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为Primary。
- SUBQUERY:在SELECT或WHERE列表中包含了子查询。
- DERIVED:在FROM列表中包含的子查询被标记为衍生,MySQL会递归执行这些子查询。
- 把结果放在临时表里:
- DEPENDENT SUBQUERY:在SELECT或WHERE列表中包含了子查询,子查询基于外层
- UNCACHEABLE SUBQUREY:无法被缓存的子查询。
- UNION RESULT:从UNION表获取结果的SELECT。
- UNION:若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子 查询中,外层SELECT将被标记为:DERIVED。
table:显示这一行的数据来源于哪张表。
type
显示查询使用了何种类型,从最好到最差依次是:system > const > eq_ref > ref > range > index > ALL。
- system:表只有一行记录,属于const类型的特列。
- const:表示通过索引一次就找到了,例如使用主键索引或唯一索引。
- eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,例如使用主键索引或唯一索引。
- ref:非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,返回所有匹配某个单独值的行。
- range:只检索给定范围的行,使用一个索引来选择行,例如where语句中出现了between、<、>、in等条件。
- index:index与ALL区别为index类型只遍历索引树,这通常比ALL快,因为索引文件通常比数据文件小。
- all:全表扫描,将遍历全表以找到匹配的行。
- index_merge:在查询过程中需要多个索引组合使用,通常出现在有 or 的关键字的sql中。
- ref_or_null:对于某个字段既需要关联条件,也需要null值得情况下,查询优化器会选择用ref_or_null连接查询。
- index_subquery:利用索引来关联子查询,不再全表扫描。
- unique_subquery:该联接类型类似于index_subquery。
possible_keys:哪些索引可以被使用。
key:哪些索引实际被使用。
key_len:表示索引中使用的索引长度。
ref:显示索引的哪一列被使用了,如果可能的话,最好是一个常数。
rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。
filtered:指返回结果的行占需要读到的行(rows列的值)的百分比,越大越好。
Extra
- Using index:表示相应的查询操作中使用了覆盖索引,避免回表操作。
- Using where:表示使用了where过滤。
- Using join buffer:使用了连接缓存。
- Using filesort:说明mysql会对数据使用一个外部的索引排序,不是按照表内的索引顺序进行读取。
- Using temporary:使了用临时表保存中间结果,mysql在对查询结果排序时使用临时表,常见于分组查询 group by。
- impossible where:where子句的值总是false,不能用来获取任何元素。
- select tables optimized away:不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。
- distinct:优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作。
面试总结十一:MySQL相关推荐
- 去BAT面试完的Mysql面试题总结(55道)
转载自 去BAT面试完的Mysql面试题总结(55道,带完整答案) 55道互联网大公司的经典面试题,全部答对月薪5W+没问题. 1.一张表里面有ID自增主键,当insert了17条记录之后,删除了第 ...
- 面试被问mysql扩展性设计相关的点,你知道该如何回答吗
面试被问mysql扩展性设计相关的点,你知道该如何回答吗 什么是扩展性 横向扩展(Scale Out) 和纵向扩展(Scale Up)区别 横向扩展 纵向扩展 事务相关性最小化原则 解决方案 敲黑板. ...
- 面试被问Mysql没答上来?阿里P5:总结了55道常见面试题,收藏一波
转载自 面试被问Mysql没答上来?阿里P5:总结了55道常见面试题,收藏一波 正文开始前,分享阿里 P8 高级架构师吐血总结的 <Java 核心知识体系&面试资料.pdf>, ...
- 面试常问MySQL性能优化问题
面试常问MySQL性能优化问题 知识综述: [1] MySQL中锁的种类: 常见的表锁和行锁,也有Metadata Lock等等,表锁是对一整张表加锁,分为读锁和写锁,因为是锁住整张表,所以会导致并发 ...
- 面试官:MySQL 表设计要注意什么?
点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 来自公众号:孤独烟 引言 大家应该知道烟哥最近要(tiao 咳咳咳),嗯,不可描述! 随手讲其 ...
- mysql 事务值被改变_面试被问MySQL 事务的实现原理,怎么破?
Java面试笔试面经.Java技术每天学习一点 作者:小小木的博客 来源:https://www.cnblogs.com/wyc1994666/ 开篇 相信大家都用过事务以及了解他的特点,如原子性(A ...
- mysql幻读和不可重复读的区别_面试官:MySQL的可重复读级别能解决幻读吗
Java面试笔试面经.Java技术每天学习一点 Java面试 关注不迷路 作者:宁愿. 来源:https://juejin.im/post/5c9040e95188252d92095a9e 引言 之前 ...
- Java面试技巧之MySQL问题梳理
据不完全调查,作为数据库中的主流选择MySQL的薪资待遇正在逐年增加,很多Java程序员在面试过程中也会被问及MySQL相关知识.接下来小千就给大家分析一下常见的MySQL面试内容. 1.通用模块. ...
- 有感:仅在面试时攻克 MySQL 还不够
开春了,面试的人也多.最近跟一位面试官聊天,他说了一位应届生的故事,让我印象还挺深刻的. 是名计算机专业的研究生,面试时,讲起 MySQL 数据库的相关知识,非常熟悉有条理,大家对他的期望值特别高.但 ...
最新文章
- 百度地图轨迹开发,如何绘制带有箭头的折线
- 贪心算法很简单:跳跃游戏
- python属性_深入理解python对象及属性
- 【转载】asp.net中弹出确认窗口(confirm),实现删除确认的功能
- SpringBoot 配置文件说明
- [51Nod 1035 最长的循环节] 循环小数的性质
- VR和AR的联系和区别
- MySQL Workbench中PK,NN,UQ,BIN,UN,ZF,AI,G字段类型标识说明
- MYSQL 列转行方法
- 基于高光谱成像技术结合卷积神经网络的马铃薯病害检测
- 腾冲樱花谷原生态旅游景区公园网站制作完成
- PLSQL无法粘贴复制
- 【docker】基于dockerfile编写LNMP
- python动态图形_用python生成地球运动的动态模拟动态图
- 【13】2016.12.13 周二--《小结2016》
- 辛辛苦苦写了一个产品,如何获取种子用户?
- h5页面loading丝滑小妙招,vue+vant
- template模板的使用及文章详情跳转
- 人脸识别智能门禁,引领智慧社区价值创新
- 因果推断系列13----倾向得分
热门文章
- 基于PHP+MySQL的大学生求职招聘网站
- UnityShader学习笔记:Caustic水纹焦散与鱼群制作水族馆
- android 黑白色主题、滤镜效果(公祭日、追悼日)
- php转换java工具_6款程序员必备的开源中文汉字拼音转换及处理工具 (PHP Java .net)...
- 十个优质编程网站,程序员们赶紧看过来!
- JavaScript (mp3、mp4、jpg、doc、txt、rar)单个、多文件批量下载
- 电话机器人API接口-空号识别-座席WEBAPI
- 模型量化 pytorch2onnx
- 微信小程序解密失败的可能原因
- GCC 9.4 编译error: catching polymorphic type ‘class std::bad_alloc’ by value [-Werror=catch-value=]