MySql
MySql介绍
- MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
MySql的存储引擎
-
InnoDB
- InnoDB 是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键。
- InnoDB的主要特性:
- 支持事务;
- 灾难恢复性好;
- 为处理巨大数据量的最大性能设计(并发性较好);
- 实现了缓冲管理,不仅能缓冲索引也能缓冲数据,并且会自动创建散列索引以加快数据的获取;
- 支持外键完整性约束。存储表中的数据时,每张表的存储都按逐渐顺序存放,如果没有显示在表定义时指定主键,InnoDB会为每一行生成一个6B的ROWID,并以此作为主键。
- 被用在众多需要高性能的大型数据库站点上
-
MyISAM
-
MyISAM 基于 ISAM 的存储引擎,并对其进行扩展。它是在Web、数据存储和其他应用 环境下最常使用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事务(即select和insert较方便)。在 MySQL5.5.5 之前的版本中,MyISAM 是默认的存储引擎。
-
使用 MyISAM 引擎创建数据库,将产生3个文件。文件的名字以表的名字开始,扩展名指出文件类型:frm 文件存储表定义,数据文件的扩展名为 .MYD(MYData),索引文件的扩展名是 .MYI(MYIndex)。
-
MyISAM 主要特性有:
- 不支持事务;
- 使用表级锁,并发性差;
- 主机宕机后,MyISAM表易损坏,灾难恢复性不佳;
- 可以配合锁,实现操作系统下的复制备份、迁移;
- 只缓存索引,数据的缓存是利用操作系统缓冲区来实现的。可能引发过多的系统调用且效率不佳;
- 数据紧凑存储,因此可获得更小的索引和更快的全表扫描性能;
- 可以把数据文件和索引文件放在不同目录。
-
MySql事务处理
- 事务: 事务就是一组原子性的SQL查询,或者说是一个独立的工作单元。 事务内的语句,要么全部执行成功,要么全部执行失败。
事务的四大特性:
- 原子性:一个事务被视作不可分割的最小工作单元,要么全部成功,要么全部失败回滚。例子:先存入200元,后转账100元,由于网络波动转账失败,然而存入和转账被视为一个事务中的两个动作,转账失败了,因此全部回滚,存入动作也被取消。
- 一致性:数据库总是从一个一致性状态转换到另一个一致性状态。通俗一点讲就是数据不发生改变。例子:A账户里有300元,B账户里有200元。此时数据总量为500元,当事务开启,A向B转账100元,事务提交。此时A:200元,B:300元。总量仍为500元。
- 隔离性:通常来讲,一个事务所做的修改,在其成功提交之前,其他事务是不可见的。简单来说:A账户原有200元,事务一开始后对A账户取出100元,此时事务一未提交,而事务二开启,事务二在查询A账户时,应为A取出钱的100元。
- 持久性:一旦事务提交,则其所做的修改就会永久保存在数据库中。
事务并发时出现的问题
- 脏读:例子:两个并发执行的事务,事务A在读取事务时,由于另一个线程开启事务B修改了数据,而导致事务A读取了未提交的错误数据,这就是脏读。
- 不可重复读:从字面上来讲,两次读取结果不一致。 例子:事务A正在读取账户,第一次读取到账户为余额1000元,此时另一个线程开启事务B,取出了1000元,提交事务B,此时事务A再次读取账户时,只剩0元,与此前读取的数据不一致,此为不可重复读。
- 幻读:事务两次读取结果不一致。不同的是不可重复读查询的是同⼀条数据,而幻读则是针对批量的数据,或者说不可重复读是A读取了B的更新数据,幻读是A读取了B的新增数据。 例子:(为区别不可重复读,此例子不用银行账户)事务A读取今日学习计划为:学习mysql,学习java。此时事务B新增了一个计划为:学习算法。提交事务B。事务A重新读取学习计划变成了:学习mysql,学习java,学习算法。多了一条学习算法,这就是幻读。
隔离级别
为了解决事务并发时出现的问题,mysql提供了一些隔离级别的设置,可以在数据读取时,提高数据的准确性。
- READ UNCOMMITTED(读未提交)
字面上来讲,当一个事务在操作时,在他提交前,其他事务可以读取到其修改的数据。此级别会产生脏读。 - READ COMMITTED(读已提交)
一个事务提交前,对其他事务是不可见的。即账户A有100元,事务一取出100元,未提交时事务二读取账户A时,读到的结果是100元。此级别可能会产生不可重复读。 - REPEATABLE READ(可重复读)
事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容。此隔离级别也是mysql默认的隔离级别。但可能会出现幻读。 - SERIALIZABLE(可串行化 几乎不用)
SERIALIZABLE 是最高的隔离级别。它通过强制事务串⾏执⾏,避免了前⾯说的幻读的问题。
SERIALIZABLE 会在读取的每⼀⾏数据上都加锁,所以可能导致⼤量的超时和锁争⽤的问题,实际中很少使⽤。
索引
索引就像是书的目录,帮助查找数据内容,提高查询速度。但是索引也是一个文件,需要占物理空间。
- 索引是按照特定数据结构把数据表中的数据放在索引文件中,一遍快速查找;
- 索引存在磁盘中,会占据物理空间。
索引的种类
- 主键索引:MySql中主键必须唯一且不能有空值,因此主键上的索引也是唯一索引。
- 唯一索引:索引必须唯一,唯一索引中允许有空值出现。
- 普通索引。
- 组合索引。 index(A,B,C)
存储引擎中索引的实现
- MySql中,索引是在存储引擎中实现的。
- 不同的存储引擎可能支持不同的索引类型。
- 不同的存储引擎对同一种索引可能有不同的实现方式。
InnoDB存储引擎中的索引
首先,MySql的索引一般是由B+树来实现的,InnoDB中B+树叶子节点存储的信息时键值+数据。
MyISAM索引实现
MyISAM的叶子节点中存储的是键值+地址,然后根据地址去查找对应的数据。
分库分表
关系型数据库本身⽐较容易成为系统瓶颈,单机存储容量、连接数、处理能⼒都有限。当单表的数据量
达到1000W或100G以后,由于查询维度较多,即使添加从库、优化索引,做很多操作时性能仍下降严
重。此时就要考虑对其进⾏切分了,切分的⽬的就在于减少数据库的负担,缩短查询时间。
数据库切分的核心内容无非就是数据切分,以及切分后对数据的定位、整合。将数据切分到多个数据库中,使得单一数据库的数据量变小,缓解单一数据库的压力,从而提高数据库性能。
数据切分根据切分类型,可以分为两种方式:垂直切分和水平切分
垂直切分
- 垂直分库
垂直分库就是根据业务的耦合性,将关联度低的不同表存储在不同数据库。按业务类型进行划分。
- 垂直分表
垂直分表是根据数据库表中“列”进行拆分,某个表的字段过多,可以新建一张拓展表,将不经常用的字段或长度较大的字段拆分到拓展表中。将“大表”拆成“小表”,更便于开发维护,避免跨页问题。- 垂直切分的优点:
- 解决业务系统层⾯的耦合,业务清晰, 与微服务的治理类似,也能对不同业务的数据进⾏分级管理、维护、监控、扩展等;
- ⾼并发场景下,垂直切分⼀定程度的提升IO、数据库连接数、单机硬件资源的瓶颈。
- 缺点:
- 部分表⽆法join,只能通过接⼝聚合⽅式解决,提升了开发的复杂度;
- 分布式事务处理复杂;
- 依然存在单表数据量过大的问题(需要⽔平切分)。
- 垂直切分的优点: