1.什么是数据库存储引擎?
MySQL中的数据用各种不同的技术存储在文件(或者内存)中。存储引擎是针对文件的一种存取控制机制,通过使用不同的存储方式、索引技巧、锁机制最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能。
2.数据库的事务
数据库中一组原子性的SQL语句的集合,彼此之间状态一致,具有A(原子性)C(一致性)I(隔离性)D(持久性)特性。
3.事务ACID特性:
- 原子性(Atomicity):数据库事务是一个整体,其中的SQL操作要么全部提交成功,要么全部失败回滚,不可分割。
- 一致性(Consistency):事务总是从一个一致状态转换到另一个一致状态。
- 隔离性(Isolation):事务彼此之间互不影响,一个事物在提交之前,对其他事务是不可见的。
- 持久性(Durability):一个事物一旦提交成功,它所做的修改就会永久性的存储在数据库中。
4.MySQL 4种隔离级别
- 未提交读:一个事物在提交之前,对其他事物是可见的。即其他事务可以读取未提交的数据。存在“脏读”(读到了脏数据)问题。
- 已提交读:一个事务在提交之前,对其他事物是不可见的。解决“脏读”问题,但存在“不可重复读”(两次查询得到的结果可能不同,即可能存在查询的间隙,有事务提交了修改)问题。
- 可重复读:在同一事务中多次读取的数据是一致的。解决了“脏读”和“不可重复读”问题,但存在“幻读”(在事务两次查询的间隙,有其他事务又插入或者删除了新的记录)。----------------------------MySQL的默认隔离级别。
- 可串行化:强制事务串行化执行,即一个事物一个事物挨着执行,可以解决上述的所有问题。
5.锁及粒度
- 共享锁/读锁:互不阻塞,优先级低
- 排他锁/写锁:阻塞其他锁,优先级高,即确保在一个事物写入时不受其他事务的影响。
- 锁粒度:锁定的数据量越少(粒度越小),并发程度越高,但相应的加锁、检测锁、释放锁用的系统开销也随之增大。
- 锁策略:锁开销与数据安全性之间的平衡
- 表锁:锁住整张表,读锁互不影响,写锁阻塞其他所有读写锁(同一张表),开销最小。
- 行级锁:对每一行数据(记录)加锁,开销大,并发程度高。
6.索引
(1)概念:数据库索引就是一种加快海量数据查询的关键技术,对数据库表列进行增加恰当索引,可以快速的找到匹配的记录行数,相比于默认的全表扫描,可以大大加快查找的速度。
(2)索引分类:索引分为聚簇索引和非聚簇索引两种
聚簇索引:表数据按照索引的顺序来存储的,也就是说索引项的顺序与表中记录的物理顺序一致。对于聚簇索引,叶子结点即存储了真实的数据行,不再有另外单独的数据页。 在一张表上最多只能创建一个聚簇索引,因为真实数据的物理顺序只能有一种。
非聚簇索引:表数据存储顺序与索引顺序无关。对于非聚簇索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针,其行数量与数据表行数据量一致。
(3)为什么要创建索引?
- 创建索引可以大大提高系统的性能。
- 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
- 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
- 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
- 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
- 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?因为,增加索引也有许多不利的方面。
- 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
- 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
(4)在哪建索引?
索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引:
- 在经常需要搜索的列上,可以加快搜索的速度;
- 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
- 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
- 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
- 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
(5)对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:
- 对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
- 对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
- 对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少,不利于使用索引。
- 当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改操作远远多于检索操作时,不应该创建索引。
(6)索引实现方法:一般分为B+树索引和哈希索引。
- B+树索引:在B-tree上改进得到,其分支节点均为key值,叶子结点是key-data键值对。叶子结点前后相连且有序。
- 哈希索引:通过对key进行hash而将记录存储在不同的bucket中,可以做到常数时间的查找,但要注意哈希冲突(链地址法、线性探测、二次探测、公共溢出区)。默认无序。
(7)为什么有了B+树索引还要hash索引?
- B+树默认有序,hash默认无序,所以哈希索引无法用于排序。
- 哈希索引O(1)在速度上毋庸置疑要快于B+树近似O(log n)
- 哈希索引只能进行等值查询,而B+树索引可以进行等值、部分前缀、范围查询
- 底层实现结构不同:B+树是非线性结构、hash桶是线性结构
- 对于某些场景如热点页/活跃查询页,需要借助哈希索引来实现快速查询
7.MySQL存储引擎InnoDB与MyISAM对比
- InnoDB最为通用/推荐的一种引擎 ,MyISAM是默认的存储引擎
- InnoDB存储文件有两个:.frm(表的定义文件) 、.idb(数据文件) ;MyISAM的存储文件有三个:.frm(表的定义文件)、.MYD(数据文件)、MYI(索引文件)
- InnoDB索引和数据结合,是聚簇索引;MyISAM中的索引和数据分别存在不同的文件,是非聚簇索引。
- InnoDB支持事务,MyISAM不支持
- InnoDB支持外键,MyISAM不支持
- InnoDB支持行级锁、表锁 ,MyISAM只支持表锁
- InnoDB支持MVCC, MyISAM不支持
- InnoDB不支持全文索引,MyISAM支持
- InnoDB支持B+树和哈希索引,MyISAM只支持B+树索引
- InnoDB是原始数据存储,占用空间大,MyISAM实现了前缀压缩技术,占用空间小,但会影响查找
- InnoDB一定会建立索引,存在主键,建立主键索引;没有主键存在唯一键,建立唯一键索引;没有主键也没有唯一键,添加一个6个字节的隐藏字段(自增长方式),以该字段建立隐藏字段。
8.MVCC
(1)什么是MVCC,解决什么问题?
MVCC是一种多版本并发控制机制。锁机制可以控制并发操作,但是其系统开销较大,而MVCC可以在大多数情况下代替行级锁,使用MVCC,能降低其系统开销。
人们一般把基于锁的并发控制机制称成为悲观机制,而把MVCC机制称为乐观机制。这是因为锁机制是一种预防性的,读会阻塞写,写也会阻塞读,当锁定粒度较大,时间较长时并发性能就不会太好;而MVCC是一种后验性的,读不阻塞写,写也不阻塞读,等到提交的时候才检验是否有冲突,由于没有锁,所以读写不会相互阻塞,从而大大提升了并发性能。
(2)MVCC实现
MVCC是通过保存数据在某个时间点的快照来实现的. 不同存储引擎的MVCC. 不同存储引擎的MVCC实现是不同的,典型的有乐观并发控制和悲观并发控制.
我们通过InnoDB的MVCC实现来分析MVCC使怎样进行并发控制的. InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列分别保存了这个行的创建时间,一个保存的是行的过期时间。这里存储的并不是实际的时间值,而是系统版本号(可以理解为事务的ID),每开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID.这样一来,INSERT 时加上开始版本号,UPDATE/DELETE时加上过期版本号,这样一来在SELETE时,就只访问开始系统版本号小于当前的事务的版本号、过期时间要么未定义要么在当前版本号之后的记录,这样就可以保证:访问的记录是在本事务开始前就存在而且在本事务期间没有过期(被删除或被修改过的)。可以避免脏读、不可重复读、幻读的问题。