首页 > 技术文章 > MySql知识点

ivy-zheng 2019-05-19 00:15 原文

MySQL 的事务特性有哪些?

  • A(原子性)事务的各步操作是不可分的,保证一系列的操作要么都完成,要么都不完成;
  • C(一致性)事务完成,数据必须处于一致的状态;
  • I(隔离性)对数据进行修改的所有并发事务彼此之间是相互隔离,这表明事务必须是独立的,不应以任何方式依赖或影响其他事务;
  • D(持久性)表示事务对数据处理结束后,对数据更改必须持久化,不管是事务成功还是回滚。事务日志都能够保持事务的永久性。

数据库如何实现 rollback回滚 的?

  • 数据库在写入数据之前是先将对数据的改动写入redo log 和 undo log,然后在操作数据,如果成功提交事务就会将操作写入磁盘;如果失败就会根据redo log 和 undo log 逆向还原到事务操作之前的状态。

如果优化数据库的数据查询,另外应用层上还能如何优化?

  • 数据库层面上:1、加索引除了主键索引,唯一索引之外,对于常用的查询字段也要加索引。查询的时候尽量使用主键索引,因为MySQL 的 InnoDB 的主键索引索引的是整行数据,而普通索引索引的是主键,会有回表操作。当然索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,需要酌情考虑。 2、优化查询语句,尽量采用确认性查询语句,减少or,in,notin,%xxx%语法的使用。
  • 应用层面上:采用缓存机制,将常用的数据进行缓存,增加访问速度;分库分表,读写分离,将数据分开读写,提升性能

SQL事务隔离的级别有哪些

  • SQL标准的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable )
  • 读未提交是指,一个事务还没提交时,它做的变更就能被别的事务看到。
  • 读提交是指,一个事务提交之后,它做的变更才会被其他事务看到。
  • 可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。未提交的更改对其他事务是不可见的
  • 串行化:对应一个记录会加读写锁,出现冲突的时候,后访问的事务必须等前一个事务执行完成才能继续执行

一条SQL查询语句是如何执行的

  • MySQL可以分为Server层和存储引擎层两部分。Server`层包括连接器、查询缓存、分析器、优化器、执行器等。存储引擎层负责数据的存储和提取
  • sql执行时,第一步,你会先连接到这个数据库上,这时候接待你的就是连接器。连接器负责跟客户端建立连接、获取权限、维持和管理连接。
  • 连接建立完成后,你就可以执行select语句了。执行逻辑就会来到第二步:查询缓存,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以key-value对的形式,被直接缓存在内存中。如果你的查询能够直接在这个缓存中找到key,那么这个value就会被直接返回给客户端。如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。
  • 如果没有命中查询缓存,就要开始真正执行语句了,分析器先会做“词法分析”,词法分析完后就要做“语法分析”。判断SQL语句是否满足MySQL语法
  • 经过了分析器,MySQL就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。
  • MySQL通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
  • 至此,这个整个语句就执行完成了。一条查询语句的执行过程一般是经过连接器、分析器、优化器、执行器等功能模块,最后到达存储引擎。

mysql 事务隔离的实现??

  • 在MySQL中,实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。
  • 不同时刻启动的事务会有不同的read-view,同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)

索引的常见模型

  • 哈希表:一种以key-value 存储数据的结构,哈希的思路是把值放在数组里,用一个哈希函数把key换算成一个确定的位置,然后把value放在数组的这个位置。哈希冲突的处理办法是使用链表。哈希表适用只有等值查询的场景
  • 有序数组:按顺序存储。查询用二分法就可以快速查询,时间复杂度是:O(log(N))。查询效率高,更新效率低(涉及到移位)。在等值查询和范围查询场景中的性能就都非常优秀。有序数组索引只适用于静态存储引擎。
  • 二叉搜索树:每个节点的左儿子小于父节点,右儿子大于父节点。查询时间复杂度O(log(N)),更新时间复杂度O(log(N))。数据库存储大多不适用二叉树,因为树高过高,会适用N叉树

InnoDB 的索引模型

  • InnoDB使用了B+树索引模型,所有数据都是存储在B+树中的。每一个索引在InnoDB里面对应一棵B+树。
  • 索引类型分为主键索引和非主键索引。主键索引的叶子节点存的是整行数据。在InnoDB里,主键索引也被称为聚簇索引。非主键索引的叶子节点内容是主键的值。在InnoDB里,非主键索引也被称为二级索引

主键索引和普通索引的查询有什么区别?

  • 如果语句是select * from T where ID=500,即主键查询方式,则只需要搜索ID这棵B+树;
  • 如果语句是select * from T where k=5,即普通索引查询方式,则需要先搜索k索引树,得到ID的值为500,再到ID索引树搜索一次。这个过程称为回表。
  • 基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询

索引维护

  • B+树为了维护索引有序性,在插入新值的时候需要做必要的维护。涉及到数据的移动和数据页的增加和删减
  • 一个数据页满了,按照B+Tree算法,新增加一个数据页,叫做页分裂,会导致性能下降。空间利用率降低大概50%。当相邻的两个数据页利用率很低的时候会做数据页合并,合并的过程是分裂过程的逆过程。

什么是覆盖索引,联合索引,最左前缀和索引下推

  • 覆盖索引是指,索引上的信息足够满足查询请求,不需要再回到主键索引上去取数据。不用回表操作,直接返回结果,减少IO磁盘读写读取正行数据
  • 最左前缀:联合索引的最左N个字段,也可以是字符串索引的最左 M 个字符
  • 联合索引:根据创建联合索引的顺序,以最左原则进行where检索,比如(age,name)以age=1 或 age= 1 and name=‘张三’可以使用索引,单以name=‘张三’ 不会使用索引。考虑到存储空间的问题,还请根据业务需求,将查找频繁的数据进行靠左创建索引。
  • 索引下推:like ‘hello%’and age >10 检索,MySQL5.6版本之前,会对匹配的数据进行回表查询。5.6版本后,会先过滤掉age<10的数据,再进行回表查询,减少回表率,提升检索速度

索引优化注意点

  • 如果对字段做了函数计算,就用不上索引了,这是MySQL的规定。对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。需要注意的是,优化器并不是要放弃使用这个索引,而是需要走全索引扫描
  • 隐式类型转换,比如一个索引字段是字符串类型的数字,传入值时传入的事int类型的值,这时因为有数据类型转换,就需要走全索引扫描
  • 隐式字符编码转换。如果有两个表的字符集不同,一个是utf8,一个是utf8mb4,所以做表连接查询的时候用不上关联字段的索引。字符集不同只是条件之一,连接过程中要求在被驱动表的索引字段上加函数操作,是直接导致对被驱动表做全表扫描的原因

垂直分片

  • 按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。 在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将压力分散至不同的数据库。
  • 垂直分片往往需要对架构和设计进行调整。通常来讲,是来不及应对互联网业务需求快速变化的;而且,它也并无法真正的解决单点瓶颈。 垂直拆分可以缓解数据量和访问量带来的问题,但无法根治。如果垂直拆分之后,表中的数据量依然超过单节点所能承载的阈值,则需要水平分片来进一步处理。

水平分片

水平分片又称为横向拆分。 相对于垂直分片,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分。例如:根据主键分片,偶数主键的记录放入0库(或表),奇数主键的记录。水平分片从理论上突破了单机数据量处理的瓶颈,并且扩展相对自由,是分库分表的标准解决方案。

本地事务

  • 在不开启任何分布式事务管理器的前提下,让每个数据节点各自管理自己的事务。 它们之间没有协调以及通信的能力,也并不互相知晓其他数据节点事务的成功与否。 本地事务在性能方面无任何损耗,但在强一致性以及最终一致性方面则力不从心

XA强一致事务

  • XA协议最早的分布式事务模型是由X/Open国际联盟提出的X/Open Distributed Transaction Processing(DTP)模型,简称XA协议。
  • 基于XA协议实现的分布式事务对业务侵入很小。 它最大的优势就是对使用方透明,用户可以像使用本地事务一样使用基于XA协议的分布式事务。 XA协议能够严格保障事务ACID特性。
  • 严格保障事务ACID特性是一把双刃剑。 事务执行在过程中需要将所需资源全部锁定,它更加适用于执行时间确定的短事务。 对于长事务来说,整个事务进行期间对数据的独占,将导致对热点数据依赖的业务系统并发性能衰退明显。 因此,在高并发的性能至上场景中,基于XA协议的分布式事务并不是最佳选择。

柔性事务

如果将实现了ACID的事务要素的事务称为刚性事务的话,那么基于BASE事务要素的事务则称为柔性事务。BASE是基本可用、柔性状态和最终一致性这三个要素的缩写。

  • 基本可用(BasicallyAvailable)保证分布式事务参与方不一定同时在线。
  • 柔性状态(Soft state)则允许系统状态更新有一定的延时,这个延时对客户来说不一定能够察觉。
  • 而最终一致性(Eventuallyconsistent)通常是通过消息可达的方式保证系统的最终一致性。
  • 在ACID事务中对隔离性的要求很高,在事务执行过程中,必须将所有的资源锁定。 柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。通过放宽对强一致性要求,来换取系统吞吐量的提升。

一条 SQL 语句执行得很慢的原因有哪些?

  • 针对偶尔很慢的情况,可能是数据库在刷新脏页。当要插入或更新数据时数据库会在内存中把对应字段的数据更新了,但是并不会马上同步持久化到磁盘中去,而是写入到redo-log日记中去,等到空闲的时候,在最新的数据同步到磁盘中去。
  • 当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”
  • 刷脏页有下面4种场景:redolog写满了,内存不够用了,MySQL 认为系统“空闲”的时候,MySQL 正常关闭的时候
  • 执行的这条语句,刚好这条语句涉及到的表,别人在用,并且加锁了,我们拿不到锁,只能慢慢等待别人释放锁了。或者,表没有加锁,但要使用到的某个一行被加锁了
  • 如果在数据量一样大的情况下,这条SQL语句每次都执行的这么慢,可能就是字段没有索引,字段有索引,但却没有用索引,函数操作导致没有用上索引,数据库自己选错索引了

推荐阅读