MySQL
https://www.bilibili.com/video/BV1yv41187tV?t=203
一、MySQL有哪几种数据存储引擎?有什么区别?
show ENGINES
指令可以看到所有支持的数据库存储引擎。最常见就是MyISAM和InnoDB两种。
MyISAM和InnDB的区别:
1.存储文件。MyISAM和每个表有两个文件。MYD和MYISAM文件。MYD是数据文件.MYI是索引文件。而InnDB每个表只有一个文件,idb。
2.InnoDB支持事务,支持行级锁,支持外键。
3.InnoDB支持XA事务。
XA START'test'`
insert...
XA END `test`
XA PREPARE`test`
4.InnoDB支持savePoints(部分回滚的机制)
savePoints.png show ENGINES.png二、什么是脏读、幻读、不可重复读?要怎么处理?
三、事务的基本特性和隔离级别有哪些?
四、MySQL的锁有哪些?什么是间隙锁?
从锁的粒度来区分
1.行锁:加锁粒度小,但是加锁资源开销比较大。InnDB支持。
- 共享锁:读锁。多个事务可以对用一个数据共享一把锁。持有锁的事务都可以访问数据,但是只能读不能修改。
select xxx LOCK IN SHARE MODE
- 排他锁:写锁。只有一个事务能够获得排它锁,其它事务都不能获取该行的锁。InnoDB会对update\delete\insert语句自动添加排他锁。
SELECT xxx FOR UPDATE
- 自增锁:通常是针对MySQL当中的自增字段。如果有事务回滚,数据会回滚,但是自增序列不会。(自增序列可能会出现中断
2.表锁:加锁粒度大,加锁资源开销比较小。MyISAM和InnoDB都支持。
- 表共享读锁
- 表排他写锁
- 意向锁:是InnoDB自动添加的一种锁,不需要用户干预。
3.全局锁:Flush tables with read lock
。加所之后整个数据库实例都处于只读状态。所有的数据变更操作都会被挂起,一般用于全库备份的时候。
常见的锁算法:
会给4-9加锁避免幻读.png1.记录锁:锁一条具体的数据。
2.间隙锁:RR隔离级别写,会加间隙锁。锁一定的范围,而不锁具体的记录。是为了防止产生幻读。
3.Next-Key:间隙锁+右记录锁。(-xx,1](1,4](4,9](9,XX)
五、MySQL的索引结构式什么样的?聚簇索引和非聚簇索引又是什么?
聚簇索引和非聚簇索引都是使用了B+树
聚簇索引:
将数据存储和索引放到了一块,并且是按照一定的顺序组织的,找到索引也就找到了数据,数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。
非聚簇索引:
叶子节点不存储数据、存储的是数据行的地址,也就是说根据索引查找到数据行的位置再取磁盘查找数据,这个就有点类似一本书的目录,比如我们要找第三章第一节,那我们现在这个目录里面找,找到对应的页码后再去对应的页码看文章。
聚簇索引
优势:
- 查询通过聚簇索引可以直接获取数据,相比非聚簇索引需要第二次查询(非覆盖索引的情况下)效率要高
- 聚簇索引对于范围查询的效率很高,因为其数据是按照大小排列的
- 聚簇索引适合用在排序的场合,非聚簇索引不适合
劣势:
- 维护索引很昂贵,特别是插入新行或者主键被更新导致要分页(page split)的时候。建议在大量插入新行后,选在负载较低的时间段,通过OPTIMIZE TABLE优化表,因为必须被移动的行数据可能造成碎片。使用独享表空间可以弱化碎片。
- 表因为使用UUId(随机ID)作为主键,使数据存储稀疏,这就会出现聚簇索引有可能比全表扫描更慢,所以建议使用
int
的auto_increment
作为主键。
3.如果主键比较大的话,那辅助索引将会变的更大,因为辅助索引的叶子存储的是主键值;过长的主键值,会导致非叶子节点占用更多的物理空间。
InnoDB中一定有主键,主键一定是聚簇索引,不手动设置,则会使用unique索引,没有Unique索引,则会使用数据库内部的一个行的隐藏id来当作主键索引。在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问的数据总是需要二次查找,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引,辅助索引叶子节点存储的不再是行的物理位置,而是主键值。
MyISM使用的是非聚簇索引,没有聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。
如果设计到大数据量的排序、全表扫描、count之类操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的。
二叉树-->AVL树-->红黑树-->B树-->B+树
二叉树:每个节点最多只有两个子节点,左边的子节点都比当前节点小,右边的子节点都比当前节点大。
AVL树:树中任意节点的两个子树的高度差最大为1
红黑树:1.每个节点都是红色或者黑色。2.根节点都是黑色 。3.每个叶子节点都是黑色的空节点。4.红色节点的父节点必须式黑色。5.从任一节点到其每个叶子节点的所有路径都包含相同的黑色节点
B-树:1.B树的每个非叶子节点的子节点个数都 不会超过D(这个D就是B-树的阶)2.所有的叶子节点都在同一层。3.所有节点关键字都是按照递增顺序排列。
B+树:(查询比较稳定)1.非叶子节点不存出局,只进行数据索引。2.所有数据都存储在叶子节点当中。3.每个叶子节点都存有相邻叶子节点的指针。4.叶子节点按照本身关键字从小到大排序。
image.png
聚簇索引和非聚簇索引,其实只是概念:
聚簇索引就是数据和索引是在一起的。
MyISAM使用的是非聚簇索引,树的子节点上的data不是数据本身,而是数据存放的地址。InnoDB采用的是聚簇索引,树的节点上的data就是数据本身。
聚簇索引的数据物理存放顺序和索引顺序是一致的,所以一个表当中只能由一个聚簇索引,而非聚簇索引可以有多个。
InnoDB中,如果表定义了PK(主键),那PK就是聚簇索引。如果没有PK,就会找第一个非空的unique列作为聚簇索引。否则,InnoDB会创建一个隐藏的row-id作为聚簇索引。
MySQL的覆盖索引和回表
如果只需要在一颗索引树上久可以获取SQL所需的所有列,就不需要再回表查询,这样查询速度就可以更快。实现索引覆盖的最简单的方式就是将要查询的字段,全部建立到联合索引当中。
image.png
六、MySQL的集群式如何搭建的?读写分离是怎么做的?
MySQL主从集群的搭建原理:(利用Binary log同步)
MySQL通过将主节点的Binlog同步给从节点完成主从之间数据同步。
show master status
show slave status
MySQL的主从集群只会将binlog从主节点同步到从节点,而不会反过来同步。由此也就引申出了读写分离的问题。
因为要保证主从之间的数据一致,写数据的操作只能在主节点完成。而读数据的操作,可以在主节点或者从节点
(MySQL半同步复制)
MySQL半同步.png
七、谈谈如何对MySQL进行分库分表?多大数据量需要分库分表?分库分表的方式和分片策略有哪些?分库分表后,SQL语句的执行流程是怎样的?
1.什么是分库分表?
就是当表中数据量过大时,整个查询效率就会降低的非常明显。这时为了提高查询效率,就需要将一个表中的数据分散到多个数据库的多个表当中。
分库分表最常用的组件: Mycat(阿里)\ShardingSphere(京东)
2.分库分表的方式
分库分表包含分库和分表两个部分,而这两个部分统称为数据分片,其目的都是将数据拆分成不同的存储单元。
另外,从分拆的角度上,可以分为垂直分片和水平分片。垂直分片就是从业务角度将不同的表拆分到不同的库中,能够解决数据文件过大的问题,但是不能从根本上解决查询问题。水平分片就是从数据的角度将一个表中的数据拆分到不同的库或表中,这样可以从根本上解决数据量过大造成的查询效率低的问题。
有非常多的分片策略,比如 取模、按时间、按枚举......
阿里提供的开发手册当中,建议:一个表的数据量超过 500W或者数据文件超过2G,就要考虑分库分表了。
分库分表后的执行流程:
ShardingSphere执行流程.png 语法树.png 优化.png
路由引擎
数据要到哪去取
分库分表的缺点
虽然数据分片解决了性能、可用性以及单点备份恢复等问题,但是分布式的架构在获得收益的同时,也引入了非常多的新的问题。
-
事务一致性问题
原本单机数据库有很好的事务机制能够帮我们保持数据一致性。但是分库分表后,由于数据分布在不同库甚至不同服务器,不可避免会带来分布式事务问题。 -
跨节点关联查询问题
在没有分库时,我们可以很容易的进行跨表的关联查询。但是在分库后,表被分散到了不同的数据库,就无法进行关联查询了。
这时就需要将关联查询拆分成多次查询,然后将获得结果进行拼装。 -
跨节点分页、排序函数
跨节点多库进行查询时,limit分页、order by排序等问题,就变得无比复杂了。需要先在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序。
这时候非常容易出现内存崩溃的问题。 -
主键避重问题
在分库分表环境中,由于表中数据同时存在不同数据库中,主键值平时使用的自增长将无用武之地,某个分区数据库生成的ID无法保证全局唯一。因此需要单独设计全局主键,以避免跨库主键重复问题。 -
公共表处理
实际的应用场景中,参数表、数据字典等都是数据量较小,变动少,而且属于高频联合查询的依赖表。这一类表一般就需要在每个数据库中都保存一份,并且所有对公共表的操作都要分发到所有分库去执行。
image.png
image.png
归并引擎
image.png
-
垂直分片: 按照业务来对数据进行分片,又称为纵向分片。他的核心理念就是专库专用。在拆分之前一个数据库由多个数据表组成,每个表对应不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库或表中,从而将压力分散至不同的数据库或表。例如,下图将用户表和订单垂直分片到不同的数据库:
垂直分片.png -
水平分片: 又称横向分片。相对于垂直分片,它不再将数据根据业务逻辑分类而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分,例如,像下图根据主键机构分片。
水平分片.png
这种取模的策略不容易扩展
常用的分片策略有:
取余/取模:优点 均匀存放数据,缺点:扩容非常麻烦
按照范围分片:比较好扩容,数据分布不够均匀
按照时间分片:比较容易将热点数据区分出来。
按照枚举值分片:例如按地区分片
按照目标字段前缀指定进行分区:自定义业务规则分片
水平分片从理论上突破了单机数量处理的瓶颈,并且扩展相对自由,是分库分表的标准解决方案。