定义
用于持久化存储数据,管理数据,是一个关系型数据库
存储引擎
- MyISAM
- innodb
- …
现在大多数场景是以innodb存储引擎为主,下面介绍主要以innodb存储引擎的mysql进行介绍
数据结构
B+
数据类型
- 数值型
- 浮点型
- 日期/时间
- 字符串
索引
定义
为了更加有效率的查找数据,对于查找某个字段设定有序的数据结构进行存储
索引分类
-
聚簇索引(主键索引)
根据相应算法找到叶子节点,包含该索引值,该节点包含该行数据
图例:
-
非聚簇索引
根据相应算法找到叶子节点,包含该索引值,拿到该节点的地址,去进行回表查询
数据结构区别
-
二叉树
瓶颈:遇到字段自增的情况,会出现树的高度过高,减少查询的效率
图例:
-
红黑树
-
B树
-
B+树
b树与b+树区别:
1)由于B树每个节点都有data区域,占用空间大
2)B树没有B+树区间查询效率高,因为B+树叶子节点都是有指针相连
事务
事务性质(ACID)
- 原子性
指事务不可分割,要么全部成功,要么全部失败,不可能存在部分成功或部分失败的情况。如果执行某一条语句失败后,将会触发之前所有执行过的语句的回滚,因此靠的是undo log。 - 一致性
在事务执行前后,数据的完整性没有遭到破坏。一致性是mysql追求的最终目标,需要数据库层面与应用层面同时来维护。需要先满足原子性、隔离性与持久性,同时也需要应用层面做保障,即在应用层面对数据进行检验 - 隔离性
事务之前是隔离的,并发执行的事务之间不存在互相影响,mysql通过锁以及MVCC来保证隔离性 - 持久性
事务一旦提交,那么对数据的操作就是永久性的,即使接下来数据库宕机也不会有影响。mysql是通过redo log来实现宕机恢复的,而binlog主要是用来误删恢复与主从复制的
隔离级别
- 读未提交
读了一些事务未提交的脏数据 - 读已提交
这层隔离级别,就解决了脏读问题,但是还是会出现一些问题,就是多次读出的数据出现不一致的情况,这种情况称为不可重复读 - 可重复读
解决了不可重复读,但是数据也会出现新增,这种情况称为幻读 - 串行化
串行化解决以上情况
事务实现原理
mysql为了实现以上隔离级别,提出了基于锁的并发控制与MVCC
在于锁的并发控制,读写冲突,会使用诸如记录锁、间隙锁与临键锁等锁来实现数据的并发安全,因此读写性能不高,主要是针对当前读
在MVCC中,读写不冲突,记录每一行的多个版本,来避免在多个事务之间的竞争。以空间换时间的思路,极大地提高了读写性能
主要是针对快照对,也就是select语句
- mvcc(多版本并发控制)
结合undo事务链与一致性视图实现mvcc
1)undo事务链
每一个事务对该行改动时,都会生成一个undo log,用于保存之前的版本,之后再将新版本的roll_pointer指向刚才生成的undo
log。 因此roll_pointer可以将这些不同版本的undo log串联起来,形成undo log版本链
2)一致性视图
m_ids
在创建ReadView的那一刻,mysql中所有未提交的事务id集合。min_trx_id
m_ids中的最小值max_trx_id
mysql即将为下一个事务分配的事务id,并不是m_ids中的最大值。creator_trx_id
即创建此ReadView的事务id那么事务在执行快照读时,可以通过以下的规则来确定undo log版本链上的哪个版本数据可见。
如果当前undo
log的版本的trx_id<min_trx_id,说明该版本对应的事务在生成ReadView之前就已经提交了,因此是可见的。如果当前undo log的版本的trx_id≥max_trx_id,说明该版本对应的事务在生成ReadView之后才开始的,因此是不可见的。
如果当前undo
log的版本的trx_id∈[min_trx_id,max_trx_id),如果在这个范围里,还要判断trx_id是否在m_ids中:在m_ids中,说明版本对应的事务未提交,因此是不可见的。 不在m_ids中,说明版本对应的事务已经提交,因此是可见的。
如果当前undo log的版本的trx_id=creator_trxt_id,说明事务正在访问自己修改的数据,因此是可见的。
当undo
log版本链表的头结点数据被判定为不可见时,则利用roll_pointer找到上一个版本,再进行判断。如果整个链表中都没有找到可见的数据,则代表当前的查询找不到数据
锁
- 表锁
粒度大,并发性低 - 行锁
粒度小,并发度高。
优化
- 索引失效
1)函数
2)‘%’
3) 不等于
4)联合索引 不正确使用
explan 分析 - 大量数据
1)多级缓存
2)读写分离
3)分库分表