从存储引擎了解MySQL

存储引擎,是MySQL的数据存取方式,不同的存储引擎对数据有着不同的管理方式,而MySQL中使用较多的两个存储引擎,或者说比较显著的两个存储引擎:MyISAM和InnoDB,对数据有着不同的管理方式,其中InnoDB目前是MySQL的默认存储引擎,进入mysql查看存储引擎如图:
在这里插入图片描述
接下来我们从这两个存储引擎来剖析一下MySQL的大部分性质。

一、索引

索引是存储在数据库底层的一种数据结构,它可以使得数据库查询的效率加倍,而MySQL的索引使用的是B+树。

1、B+树

性质:

B+树是一棵多路树,其父节点的每一个元素都会出现在子节点中,是子节点中最大或者最小的值,根节点最大的元素等同于整棵树的最大元素,所以无论以后插入多少元素,最大的元素始终要保持包含在根节点当中,而因为父节点的元素全部都出现在子节点当中,所以所有的叶子节点包含了全部的节点信息,每个叶子节点都带有指向下一个节点的指针,形成一个有序链表。
在这里插入图片描述

查询过程:

而B+树的好处主要体现在查询上,在单元素查询时,B+树向下逐层查找节点,最终匹配到叶子节点,如果是聚集索引则直接取值,如果是非聚集索引则根据地址取值。

与B-树的差别:

B+树中间的节点没有卫星数据,所以同样大小的磁盘页可以容纳更多的节点元素,这就意味着数据量相同的情况下查询IO次数会更少,再有,B+树必须查询到叶子节点,而B-树只要找到匹配元素,所以B-树的查询性能并不稳定,而B+树的查询是稳定的。而且B-树是中序遍历查询,而B+树只需要在链表上遍历即可。

2、索引的分类

聚集索引:

聚集索引是指索引在建立时会将数据同时存储在索引中,也就是说,在查找到索引时,数据也就被同步查找到了,聚集索引的差别可以和非聚集索引对比着看。

非聚集索引:

非聚集索引是指建立索引时,数据不存储到索引中,索引中仅存储数据的地址,所以当在索引中查到数据时,我们还需要按照其存储的地址去查找数据。

3、MyISAM和InnoDB的索引对比

MyISAM InnoDB
采用非聚集索引 采用聚集索引
辅助索引存储的是值的地址 辅助索引中存储的是主索引的值
支持全文索引 不支持全文索引

二、事务

事务是一组SQL语句的集合,MyISAM并不支持事务,InnoDB支持事务,针对InnoDB来看一下事务,事务有四种性质:原子性,一致性,隔离性,永久性(ACID)。

1、原子性

因为事务是一组SQL语句的集合,而事务的原子性就是指该集合要么全部执行成功,要么全部执行失败,不能出现执行一半而失败的情况。如果没有完全执行成功,则会进行回滚(ROLLBACK)。

2、一致性

事务执行的结果必须是使数据库从一个一致性状态转换到另一个一致性状态。一致性与原子性密切相关,需要将事务对应的需要操作的物理数据都更改,否则会出现问题、

3、隔离性

隔离性是四个特性中比较重要的一个,首先我们需要知道如果没有隔离性会出现什么问题:

出现的问题 出现原因
脏读 由于事务读取到了其他事务执行过程中的结果导致脏读
不可重复读 由于事务进行了修改(update)操作
幻读 由于事务进行了插入(insert)或删除(delete)操作

对可能出现的问题,数据库设置了隔离级别来消除这些问题,而对于MySQL的隔离级别有以下四个:

隔离级别 相应隔离级别下残留的问题
未提交读(READ-UNCOMMITED) 脏读、不可重复读、幻读
已提交读(READ-COMMITED) 不可重复读,幻读
可重复读(REPEATABLE-READ) 幻读
可序列化(SERIALIZABLE) 解决所有问题

InnoDB的默认隔离级别是在可重复读(REPEATABLE-READ),可以通过命令查看。
在这里插入图片描述
显而易见在第四隔离级别时可以解决所有的问题,但为何不直接使用第四隔离级别呢?因为可序列化的代价就是所有事务都会串行执行,对数据库操作的效率损害不是一般的大,所以在数据库层面会有其他的机制来保证不会出现问题。

4、永久性

永久性是指:当一个事务提交后,对数据库的影响应该是持久的,不能被改变的,接下来的任何操作和故障不应该对其执行的结果有任何影响。

三、锁机制

锁是保证数据库安全的基本工具,MyISAM引擎的锁是基于表的,而InnoDB是基于行。

1、MyISAM的读锁和写锁

MyISAM的读锁称为共享读锁,意义就是当加上一个读锁时还可以再加上读锁;而MyISAM的写锁称为独占写锁,当执行insert,delete,update操作时,会加上写锁,此时不能再加任何形式的锁。因为MyISAM的锁是表锁,所以锁的粒度会比较大。

读写锁的关系

(1)读写锁不兼容,当已有锁时另一个事务只能阻塞
(2)读锁和读锁兼容;
(3)写锁和写锁不兼容;
(4)加锁的语句:lock table test read(write)

性质

(1)读锁锁表,阻塞其他链接修改表的数据,不会阻塞其他链接查询数据
(2)写锁锁表,阻塞其他链接查询和修改数据
(3)并发效率不高,所以引入了行级锁,但不会发生死锁

2、InnoDB的读锁和写锁:

select操作不加锁,所以select操作在任何时候都会执行,且select操作在InnoDB中视为了一个事务,隔离性使得其直接可以执行不会阻塞。InnoDB的读锁称为共享锁(一般需要手动加,因为InnoDB中读操作不加锁),而InnoDB的写锁称为排它锁。因为InnoDB支持行锁,所以其锁的粒度较小

InnoDB加行锁的方式:

(1)写锁:select * from test where id=1 for update;
(2)读锁:select *from test where id=1 lock in share model;
InnoDB的以上加锁方式在;结束之后就解锁了,所以需要去掉其自动提交事务的功能:

set autocommit=0;

行锁的工作机制

InnoDB的行锁是锁定他的主索引项,当通过非索引查询数据时,索引机制不触发,行锁机制也不触发,而是触发表锁(InnoDB也支持表锁),此时查询同一张表则会阻塞;行锁的开销大于表级锁,且可能会产生死锁。

3、悲观锁和乐观锁(针对所有存储引擎),是一个概念性的锁。

悲观锁

基于悲观概念出发,认为每一项都会失败所以需要提前加锁以便于后续执行成功。每个存储引擎的锁机制都是悲观锁;

乐观锁

基于乐观概念出发,认为每一项都会成功所以在遇上问题时才加锁,一般是人为设计的。

4、意向锁和间隙锁

意向锁(针对InnoDB)

当需要向数据加锁时,先加意向锁(意向锁和意向锁不冲突),兼容的情况下才允许加锁,可能冲突时等待冲突的锁撤销后再加锁;

间隙锁

锁定的是数据间隙,不允许操作,不能在间隙中插入,也只有范围查询时才能加间隙锁。

猜你喜欢

转载自blog.csdn.net/qq_45132647/article/details/108338381