Mysql进阶-InnoDB引擎

Mysql支持多种存储引擎。这里记录最常用的InnoDB存储引擎

逻辑存储结构

  • 表空间:一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。(在电脑上就是那个后缀为idb文件)在Mysql8.0之前,记录文件使用.MYD 后缀,索引文件使用.MYI 后缀,表结构使用.frm 后缀。在Mysql8.0之后,表的记录、索引、表结构都存储在同一个 .ibd 文件中。
    Mysql进阶-InnoDB引擎_第1张图片

  • 段:分为数据段、索引段、回滚段,InnoDB是索引组织表,数据段就是B+树的叶子节点,索引段即为B+树的非叶子节点。段用来管理多个区。

  • 区:表空间的单元结构,每个区的大小为1M。默认情况下,InnoDB存储引擎页大小为16K,即一个区中一共有64个连续的页。

  • 页:是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。为了保证页的连续性,InnoDb存储引擎每次从磁盘申请4-5个区。

  • 行:InnocentDB存储数据是按行进行存放的。

Trx_id:每次对某条记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。
Rollpointer:每次对某条引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。

事务的原理

概念:是一组操作的集合,是不可分割的整体,事务会将所有操作一起向系统提交或撤销。这些操作要么同时成功,要么同时失败。

特性

  • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
  • 隔离性(lsolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

Mysql进阶-InnoDB引擎_第2张图片

  事务的原子性、一致性、持久性的实现原理都是基于redo logundo log这两个日志来实现的。
  事务的隔离性是依托于锁和 MVCC来实现的。

redo log

redo log(重做日志): 它保证了事务的持久性

记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。
该日志文件由两部分组成︰

  1. 重做日志缓冲(redo log buffer):在内存中。
  2. 重做日志文件(redo log file) :在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用。
    Mysql进阶-InnoDB引擎_第3张图片

  如果我们没有重做日志,当将内存中的脏数据刷新到磁盘中时,出现错误。那么就会出现数据的丢失(因为事务已经提交了)
Mysql进阶-InnoDB引擎_第4张图片
  有了重做日志后,提交事务之后,我们会将数据页的变化保存到 redolog buffer。然后将日志刷新到磁盘中,用于在刷新脏数据页到磁盘,发生错误的时候,进行数据恢复使用。

undo log

undo log(回滚日志):用于实现事务的原子性

用于记录数据被修改前的信息,作用包含两个:

  1. 提供回滚。
  2. MVCC(多版本并发控制)。

undo log和redo log记录物理日志不一样,它是逻辑日志

例子:
	可以认为当delete一条记录的,Undo log中会记录一条对应的insert记录,(就是说,我事务中删除了一个记录,那么当我回滚的时候,需要将其恢复过来,就得使用一个insert语句将其插入)反之亦然,
	当update一条记录时,它记录一条对应相反的update记录(update是记录两个操作,一个是删除更改的数据,插入原有的数据)。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

Undo log销毁:
  undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC。
具体的是:

  1. 当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。
  2. 而update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读(普通select)时也需要,不会立即被删除。

Undo log存储:
  undo log采用段的方式进行管理和记录,存放在前面介绍的 rollback segment 回滚段中,内部包含1024个undo logsegment。

MVCC

  全称 Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。

当前读

  读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select ... lock in share mode(共享锁),select .. for update、update、insert、delete(排他锁)都是一种当前读。(在使用锁的场景下,都是当前读)

快照读

  简单的select(不加锁)就是快照读,快照读读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。

  • Read Committed:每次select,都生成一个快照读。
  • Repeatable Read:开启事务后第一个select语句才是快照读的地方。
  • Serializable:快照读会退化为当前读。

例子:(mysql默认隔离级别下,RR)
Mysql进阶-InnoDB引擎_第5张图片
  例子中,在RR隔离级别下,我们只有事务都提交之后,才能看到他们各自修改的数据。也就是说,在他们自己的事务中,是快照读。

三个隐式字段

在创建表的时候,InnoDB引擎会给我们表添加三个隐藏字段:

  • DB_TRX_ID:最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。
  • DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。
  • DB_ROw_ID:隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。

如何查看这个隐藏的字段?
  在var/lib/mysql/数据库名称目录下的找到对应表的ibd文件,使用ibd2sdi 表名.ibd就可以查看到每个字段,包括隐藏的字段。

undo log版本链

Mysql进阶-InnoDB引擎_第6张图片
  不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。

read view

作用:
  是快照读SQL执行时MVCC提取数据的依据(判断当前事务读取的是undo log版本链中的哪一条数据),他记录并维护系统当前活跃的事务id。

ReadView的四个核心字段:

  • m_ids:当前活跃的事务ID集合
  • min_trx_id:最小活跃事务ID
  • max_trx_id:预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)
  • creator_trx_id:ReadView创建者的事务ID

版本链数据访问规则:
Mysql进阶-InnoDB引擎_第7张图片

不同的隔离级别,生成ReadView的时机不同:

  • READ COMMITTED:在事务中每一次执行快照读时生成ReadView。
  • REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。

Mysql进阶-InnoDB引擎_第8张图片
Mysql进阶-InnoDB引擎_第9张图片

  这里我强烈推荐一位大佬的文章:看一遍就理解:MVCC原理详解,看里边的例子就很容易的理解MVCC的工作原理。


如果文章中有描述不准确或者错误的地方,还望指正。您可以留言或者私信我。
最后希望大家多多 关注+点赞+收藏^_^,你们的鼓励是我不断前进的动力!!!
感谢感谢~~~

你可能感兴趣的:(Mysql,mysql,数据库,java)