mysql总结知识

1,047 阅读25分钟

前序:

之前面试又被问到“聚簇索引与非聚簇索引”,现在简单总结下:

1、主键、唯一索引、聚集索引、非聚集索引

  • 定义:数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。

    聚集索引的叶子节点就是对应的数据节点,可以直接获取到对应的全部列的数据,

    **聚簇索引:**将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据

  • 定义:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。

    而非聚集索引在索引没有覆盖到对应的列的时候需要进行二次查询

    **非聚簇索引:**将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置(详解

    非聚集索引,分成普通索引,唯一索引,全文索引。

主键是建立了唯一的聚集或者非聚集索引

  • 主键是唯一的,所以创建了一个主键的同时,也就这个字段创建了一个唯一的索引

  • 主键并不一定是聚集索引

  • 聚集索引适合用于需要进行范围查找的列,因为聚集索引的叶子节点存放的是有序的数据行,查询引擎可根据WHERE中给出的范围,直接定位到两端的叶子节点,将这部分节点页的数据根据链表顺序取出即可;

本篇文章主要是整理一下mysql的基础知识 

0、一条查询语句是怎么执行的?

  • 1.通过连接器跟客户端 建立连接

  • 2.通过查询缓存查询之前是否有查询过该 sql:a有 则直接返回结果 ;b没有 则执行第三步

  • 3.通过分析器分析该 sql 的语义是否正确,包括格式,表等等;

  • 4.通过优化器优化该语句,比如选择索引,join 表的连接顺序

  • 5.验证权限,验证是否有该表的查询权限:a没有 则返回无权限的错误。b有 则执行第六步

  • 6.通过执行器调用存储引擎执行该 sql,然后返回**「执行结果」**

一、mysql的执行引擎

  • 1、innodb: 默认的存储引擎是 InnoDB ,并且也是最主流的选择

 支持事务。 
支持行级锁和表级锁,能支持更多的并发量。  查询不加锁,完全不影响查询。 
支持崩溃后恢复。

InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行

InnoDB:支持外键

DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。

  • 2、MyISAM:在 MySQL5.1 以及之前的版本,默认的存储引擎是 MyISAM ,但是目前已经不再更新

 不支持事务。 
使用表级锁,如果数据量大,一个插入操作锁定表后,其他请求都将阻塞。

select count(*) from table,MyISAM只要简单的读出保存好的行数,注意的是,当count(*)语句包含 where条件时,两种表的操作是一样的

MyISAM:不支持外键

二、索引

索引,都是实现在存储引擎层的。

1、主要有六种类型:

1、普通索引:最基本的索引,没有任何约束。 
2、唯一索引:具有唯一性约束。 3、主键索引:特殊的唯一索引,不允许有空值。
4、复合索引:将多个列组合在一起创建索引,可以覆盖多个列。 
5、外键索引:只有InnoDB类型的表才可以使用外键索引,保证数据的一致性、完整性和实现级联操作。 
6、全文索引:MySQL 自带的全文索引只能用于 InnoDB、MyISAM ,并且只能对英文进行全文检索,一般使用全文索引引擎。(常用的全文索引引擎的解决方案有 Elasticsearch) 

2、MySQL 索引的“使用”注意事项? 

索引失效原因及解决索引失效方法

- 0、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描 。 

- 1、应尽量避免在 WHERE 子句中使用 != 或 <>操作符, 否则引擎将放弃使用索引而进行全表扫描。 优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。 注意,column IS NULL 也是不可以使用索引的。 

- 2、应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描。 

- 3、应尽量避免在 WHERE 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。 

- 4、应尽量避免在 WHERE 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。 

- 5、不要在 WHERE 子句中的 = 左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。 

- 6、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。 

- 7、列类型是字符串类型,查询时一定要给值加引号,否则索引失效。

- 8、LIKE 查询,% 不能在前,因为无法使用索引。如果需要模糊匹配,可以使用全文索引。 

- 9、尽量的扩展索引,不要新建索引

- 10、复合索引遵循前缀原则。索引的最左匹配特性

3、索引结构

为了描述B-Tree,首先定义一条记录为一个二元组 [key, data] ,key 为记录的键值,对应表中的主键值,data 为一行记录中除主键外的数据。

InnoDB存储引擎就是用 B+Tree 实现其索引结构。

B+树结构中有:

  • 非叶子节点只存储键值信息,

  • 数据全部冗余到了叶子节点,

  • 而且所有叶子节点之间都有一个链指针,所以支持范围查找

  1. 在 B+Tree 中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储 key 值信息,这样可以大大加大每个节点存储的 key 值数量,降低 B+Tree 的高度。

  2. 通常在 B+Tree 上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对 B+Tree 进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

  3. 在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;

面试题1:为什么不用B树作为索引?
从 B-Tree 结构图中可以看到,每个节点中不仅包含数据的 key 值,还有 data 值。而每一个页的存储空间是有限的,如果 data 数据较大时将会导致每个节点(即一个页)能存储的 key 的数量很小,当存储的数据量很大时同样会导致 B-Tree 的深度较大,增大查询时的磁盘 I/O 次数,进而影响查询效率。在 B+Tree 中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储 key 值信息,这样可以大大加大每个节点存储的 key 值数量,降低 B+Tree 的高度。

4、B-Tree 有哪些索引类型

在 B+Tree 中,根据叶子节点的内容,索引类型分为主键索引非主键索引

innodb中的主键索引和实际数据绑定在一起,也就是说Innodb的一个表一定要有主键索引。如果一个表没有手动建立主键索引,Innodb会查看有没有唯一索引,如果有,则选用唯一索引作为主键索引;如果连唯一索引也没有,则会默认建立一个隐蔽的主键索引,这个隐形字段长度为6个字节,类型为长整形(用户不可见)。

1)主键索引:

在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

(图inndb主键索引)是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有)

2). InnoDB的辅助索引

InnoDB的所有辅助索引都引用主键作为data域。例如,下图为定义在Col3上的一个辅助索引:

总结:

  • 主键索引的叶子节点存的数据是整行数据( 即具体数据 )。在 InnoDB 里,主键索引也被称为聚集索引(clustered index)。
  • 非主键索引的叶子节点存的数据是整行数据的主键,键值是索引。在 InnoDB 里,非主键索引也被称为辅助索引(secondary index)。

当通过辅助索引来查询数据时,需要进过两步:
首先,InnoDB 存储引擎会遍历辅助索引找到主键。 
然后,再通过主键在聚集索引中找到完整的行记录数据。

面试题2、为什么主键需要是自增 ID ,又或者为什么主键需要带有时间性关联?
因为 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于 InnoDB 表,我们一般都会定义一个自增的 ID 列为主键。

三、事务

(一)、事务的特性  :指的是 ACID

  1. 原子性 Atomicity :一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
  2. 一致性 Consistency :在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
  3. 隔离性 Isolation :数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  4. 持久性 Durability :事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

(二)、事务的隔离级别

mysql隔离级别:可重复读,快照读/当前读 : mvcc/锁 

**引用:MySQL 是如何解决幻读的MySQL可重复读级别能够解决幻读吗
**

1、事务定义了四种事务隔离级别,不同数据库在实现时,产生的并发问题是不同的。

  • READ UNCOMMITTED(读未提交):事务中的修改,即使没有提交,对其他事务也都是可见的。

    会导致脏读。

  • READ COMMITTED(读已提交):事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。

    会导致不可重复读。

    这个隔离级别,也可以叫做“不可重复读”。

  • REPEATABLE READ(可重复读):一个事务按相同的查询条件读取以前检索过的数据,其他事务插入了满足其查询条件的新数据。产生幻行。

    会导致幻读。

  • SERIALIZABLE(可串行化):强制事务串行执行。

2、MySQL InnoDB 采用 MVCC 来支持高并发,实现结果如下表所示:

  • MySQL 默认的事务隔离级别为可重复读(repeatable-read) 。
  • 上图的 <X> 处,MySQL 因为其间隙锁的特性,导致其在可重复读的隔离级别下,不存在幻读问题。也就是说,上图 <X> 处,需要改成“否”!!!!
  • 有些资料说可重复读解决了幻读,实际是存在的,可以通过 SELECT xxx FROM t WHERE id = ? FOR UPDATE 的方式,获得到悲观锁,禁止其它事务操作对应的数据,从而解决幻读问题

(三)、事务的传播机制

  • REQUIRED(默认):支持使用当前事务,如果当前事务不存在,创建一个新事务。

  • SUPPORTS:支持使用当前事务,如果当前事务不存在,则不使用事务。

  • MANDATORY:中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。

  • REQUIRES_NEW:创建一个新事务,如果当前事务存在,把当前事务挂起。

  • NOT_SUPPORTED:无事务执行,如果当前事务存在,把当前事务挂起。

  • NEVER:无事务执行,如果当前有事务则抛出Exception。

  • NESTED:嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样。

(四)、分布式事务

  1. 二段提交协议、三段提交协议

  2. 分布式事务 (总结)

四、mysql锁机制

1、MySQL 的共享锁和排他锁,就是读锁和写锁。

2、表锁与行锁:由执行引擎决定

使用行锁或者表锁都是使用的悲观锁:SELECT ...... FOR UPDATE;

当查询有明确主键时使用的是行锁;查询无明确主键时使用表锁

  • 表锁:系统开销最小,会锁定整张表,MyIsam 使用表锁。
  • 行锁:最大程度的支持并发处理,但是也带来了最大的锁开销,InnoDB 使用行锁。

3、悲观锁与乐观锁

  • 乐观锁:可以读,不能写

  • 悲观锁:不能读写,就是上面看到的共享锁和排他锁

乐观锁与悲观锁的实现机制?

  • 悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。如:SELECT xxx FROM t WHERE id = ? FOR UPDATE 的方式

  • 乐观锁,大多是基于数据版本( Version )记录机制实现:乐观锁,实际就是通过版本号,从而实现 CAS 原子性更新。

4、死锁

参考:死锁部分show engine innodb status解读

死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。简单的说,进程 A 等待进程 B 释放他的资源,B 又等待 A 释放他的资源,这样就互相等待就形成死锁。

下列方法有助于最大限度地降低死锁:

  • 设置获得锁的超时时间。 通过超时,至少保证最差情况下,可以有退出的口子。

  • 按同一顺序访问对象。 这个是最重要的方式。

  • 避免事务中的用户交互。

  • 保持事务简短并在一个批处理中。

  • 使用低隔离级别。

  • 使用绑定连接。

面试题:MySQL 中InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?

 InnoDB 是基于索引来完成行锁。

例如:SELECT * FROM tab_with_index WHERE id = 1 FOR UPDATE 
FOR UPDATE 可以根据条件来完成行锁锁定,并且 id 是有索引键的列;如果 id 不是索引键,那么 InnoDB 将完成表锁,并发将无从谈起。

-------------------------------------------------------------------------

所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,

表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB.
死锁的关键在于**:两个(或以上)的Session加锁的顺序不一致。**

那么对应的解决死锁问题的关键就是:让不同的session加锁有次序

例1

对于这个问题的改进很简单,直接把所有分配到的借款人直接一次锁住就行了。

Select * from xxx where id in (xx,xx,xx) for update

在in里面的列表值mysql是会自动从小到大排序,加锁也是一条条从小到大加的锁

例2

对于这种死锁的解决办法是:

insert into t3(xx,xx) on duplicate key update `xx`='XX';

用mysql特有的语法来解决此问题。因为insert语句对于主键来说,插入的行不管有没有存在,都会只有行锁。

五、MySQL 查询执行顺序

(1)     SELECT
(2)     DISTINCT <select_list>
(3)     FROM <left_table>
(4)     <join_type> JOIN <right_table>
(5)     ON <join_condition>
(6)     WHERE <where_condition>
(7)     GROUP BY <group_by_list>
(8)     HAVING <having_condition>
(9)     ORDER BY <order_by_condition>
(10)    LIMIT <limit_number>

六、当前读与快照读

1、概念

当前读和快照读。顾名思义,当前读就是读的是当前时刻已提交的数据,快照读就是读的是快照生成时候的数据。

这里概念理解要抛开读出跟写入的物理概念、读写分离的概念等等。这里的读包含了SELECTUPDATEINSERT等语句中的处理逻辑。

2、区分

当前读:当前时刻。执行语句的时刻,库里(磁盘+buffer)是什么样子就是什么样子。

快照读:快照的生成时间根据隔离级别的不同而有所不同。

先复习下隔离级别:

  •   读未提交。一个事务还没提交时,它做的变更就能被别的事务看到。
      读提交。一个事务提交之后,它做的变更会被其他事务看到
      可重复读。一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。未提交的数据对其他事务不可见
      串行化。对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行
    
  • **在读未提交隔离级别下,快照是什么时候生成的?**没有快照,因为不需要怎么读都最新的。不管是否提交

  • **在读已提交隔离级别下,快照是什么时候生成的?**SQL语句开始执行的时候。

  • **在可重复读隔离级别下,快照是什么时候生成的?**事务开始的时候

3、怎么知道执行的语句是当前读还是快照读

当前读:

1. select语句加锁:

# 共享锁 select a from t where id = 1 lock in share mode;                               # 排他锁 select a from t where id = 1 for update;

2. update、 delete , insert语句 是当前读: update t set a = a + 1;

快照读:

1.在默认隔离级别下,select 语句默认是快照读 : select a from t where id = 1

2.快照读: 通过undo和MVCC实现

陆、间隙锁

InnoDB支持几种不同的行级锁: 

  • 行锁(Record Lock): 对索引记录加锁。 
  • 间隙锁(Gap Lock): 锁住整个区间,包括区间里具体的索引记录,不存在的空闲空间(可是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引记录之后的空间)。 
  • next-key锁: 行锁和间隙锁组合起来。

Gap Lock的唯一目的就是阻止其他事务插入到间隙中(间隙锁是在可重复读隔离级别下才生效

1、加锁规则:

  • 加锁基本单位next-key lock,next-key lock = 间隙锁 + 行锁,前开后闭
  • 查询过程中访问到的对象都要加锁
  • 索引等值查询,给唯一索引加锁时,next-key lock会退化为行锁
  • 索引等值查询,向右遍历时且最后一个值不满足查询条件,next-key lock会退化为间隙锁
  • 索引上的范围查询会访问到不满足条件的第一个值为止

2、什么是间隙锁

当我们采用范围条件查询数据时,InnoDB 会对这个范围内的数据进行加锁。比如有 id 为:1、3、5、7 的 4 条数据,我们查找 1-7 范围的数据。那么 1-7 都会被加上锁。2、4、6 也在 1-7 的范围中,但是不存在这些数据记录,这些 2、4、6 就被称为间隙。

3、间隙锁的危害

范围查找时,会把整个范围的数据全部锁定住,即便这个范围内不存在的一些数据,也会被无辜的锁定住,比如我要在 1、3、5、7 中插入 2,这个时候 1-7 都被锁定住了,根本无法插入 2。在某些场景下会对性能产生很大的影响

在可重复读的情况下,快照读可以避免幻读,在当前读的情况下需要加上间隙锁。

MVCC 在读已提交(Read Committed)和可重复读(Repeatable Read)隔离级别下起作用
MVCC 的实现是基于ReadView版本链以及Undo日志实现的。

七、什么是 MVCC

面试题:innodb的隔离级别是根据mvcc实现的

多版本并发控制(MVCC),是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。 这样在读操作不用阻塞写操作,写操作不用阻塞读操作的同时,避免了脏读和不可重复读。

在innodb引擎层面,新的解决方案(解决加锁后读写性能问题),叫做mcvv,mvcc可以做到读写不阻塞。

**原理:****它的实现原理主要是:版本链,**undo日志 **,**Read View 来实现的

1、版本链:

数据库中的每行数据,除了我们肉眼看见的数据,还有几个隐藏字段分别是db_trx_id、db_roll_pointer、db_row_id。

  1.  1、db_trx_id      6 byte,最近修改(修改/插入)事务ID
     2、db_roll_pointer(版本链关键)7byte,指向这条记录的上一个版本(存储于rollback segment里)
     3、db_row_id      6byte,隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以db_row_id产生一个聚簇索引。
     4、实际还有一个删除flag隐藏字段, 记录被更新或删除并不代表真的删除,而是删除flag变了
    

如上图,db_row_id是数据库默认为该行记录生成的唯一隐式主键db_trx_id是当前操作该记录的事务ID,而db_roll_pointer是一个回滚指针,用于配合undo日志,指向上一个旧版本

每次对数据库记录进行改动,都会记录一条undo日志,每条undo日志也都有一个roll_pointer属性(INSERT操作对应的undo日志没有该属性,因为该记录并没有更早的版本),可以将这些undo日志都连起来,串成一个链表。

2、undo日志

Undo log 主要用于记录数据被修改之前的日志,在表信息修改之前先会把数据拷贝到undo log里。当事务进行回滚时可以通过undo log 里的日志进行数据还原

3、Read View(读视图)

事务进行快照读操作的时候生产的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照

记录并维护系统当前活跃事务的ID(没有commit,当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以越新的事务,ID值越大),是系统中当前不应该被本事务看到的其他事务id列表

Read View主要是用来做**可见性**判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。

4、MVCC和事务隔离级别

上面所讲的Read View用于支持RC(Read Committed,读提交)和RR(Repeatable Read,可重复读)隔离级别实现

RR、RC生成时机

  •   RC隔离级别下,是每个快照读都会生成并获取最新的Read View
  •   RR隔离级别下,则同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View,
      之后的查询就不会重复生成了,所以一个事务的查询结果每次都是一样的。
    

解决幻读问题

  • 快照读:通过MVCC来进行控制的,不用加锁。按照MVCC中规定的“语法”进行增删改查等操作,以避免幻读。

  • 当前读:通过next-key锁(行锁+间隙锁)来解决问题的。

RC、RR级别下的InnoDB快照读区别

  • 即RR级别下,快照读生成Read View时,Read View会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见

  • 而在RC级别下的,事务中,每次快照读都会新生成一个快照和Read View, 这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因

摘自:链接:juejin.cn/post/687104…

八、MySQL SQL 优化

见下一篇

九、mysql主从同步

参考:Mysql主从同步的实现原理MySQL主从同步的机制mysql主从同步实现读写分离

1、MySQL主从同步的作用

  • 1、可以作为一种备份机制,相当于热备份

  • 2、可以用来做读写分离,均衡数据库负载

  • 3、容错,高可用。Failover(失败切换)/High Availability

2、主从同步复制有以下几种方式:

(1)同步复制,master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回。

(2)异步复制,master只需要完成自己的数据库操作即可,至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。

(3)半同步复制,master只保证slaves中的一个操作成功,就返回,其他slave不管。这个功能,是由google为MYSQL引入的。

3、MySQL主从同步的机制

MYSQL主从同步是在MySQL主从复制(Master-Slave Replication)基础上实现的,通过设置在Master MySQL上的binlog(使其处于打开状态),Slave MySQL上通过一个I/O线程从Master MySQL上读取binlog,然后传输到Slave MySQL的中继日志中,然后Slave MySQL的SQL线程从中继日志中读取中继日志,然后应用到Slave MySQL的数据库中。这样实现了主从数据同步功能。

十、数据库崩溃时事务的恢复机制

数据库崩溃时事务的恢复机制

Undo Log是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用了Undo Log来实现多版本并发控制(简称:MVCC)。

Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到UndoLog。然后进行数据的修改,如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。

之所以能同时保证原子性和持久化,是因为以下特点:

更新数据前记录Undo log。为了保证持久性,必须将数据在事务提交前写到磁盘。只要事务成功提交,数据必然已经持久化。Undo log必须先于数据持久化到磁盘,那么不管数据是否保存到磁盘发生了错误或者执行回滚操作,都能利用Undo log中的备份将数据恢复到事务开始之前的状态。

缺陷:每个事务提交前将数据和Undo Log写入磁盘,这样会导致大量的磁盘IO,因此性能很低。

Redo Log

原理和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交前,只要将Redo Log进行持久化即可,不需要将数据持久化。如果系统崩溃,虽然数据没有持久化,但是Redo Log已经持久化。系统可以根据Redo Log的内容将所有数据恢复到最新的状态。

十一、数据库的三范式,反范式

十二、buffer pool 是做什么的

主要引用

buffer pool 是一块内存区域,为了**「提高数据库的性能」**,当数据库操作数据的时候,把硬盘上的数据加载到 buffer pool,不直接和硬盘打交道,操作的是 buffer pool 里面的数据,数据库的增删改查都是在 buffer pool 上进行

buffer pool 里面缓存的数据内容也是一个个数据页

十三、写缓存

写缓冲(change buffer)

参考:

1、www.cnblogs.com/nullzx/p/87…

2、blog.csdn.net/bigtree\_37…

3、svip.iocoder.cn/MySQL/Inter…