内网网站建设的必要性,做旅游海报的软件或是网站,深圳网站建设门户,哪个网站用户体验较好06、InnoDB引擎
6.1、逻辑存储结构 表空间#xff08;Tablespace#xff09; 表空间在MySQL中最终会生成ibd文件#xff0c;一个mysql实例可以对应多个表空间#xff0c;用于存储记录、索引等数据。 段#xff08;Segment#xff09; 段#xff0c;分为数据段#x…06、InnoDB引擎
6.1、逻辑存储结构 表空间Tablespace 表空间在MySQL中最终会生成ibd文件一个mysql实例可以对应多个表空间用于存储记录、索引等数据。 段Segment 段分为数据段Leaf node segment、索引段Non-leaf node segment、回滚段Rollback segment。 InnoDB是索引组织表数据段就是B树的叶子节点索引段即为B树的非叶子结点。 段用来管理多个Extent区. 区Extent 区表空间的单元结构每个区的大小为1M。默认情况下InnoDB存储引擎页大小为16K即一个区中一共有64个连续的页。 页Page 页是InnoDB存储引擎磁盘管理的最小单元每个页的大小默认为16KB。为了保证页的连续性InnoDB存储引擎每次从磁盘申请4-5个区。 行Row InnoDB存储引擎数据是按行进行存放的。 Trx_id每次对某条记录进行改动时都会把对应的事务id复制给trx_id隐藏列。Roll_pointer每次对某条引记录进行改动时都会把旧的版本写入到undo日志中然后这个隐藏列就相当于一个指针可以通过它来找到该记录修改前的信息。
6.2、架构
MySQL5.5版本开始默认使用InnoDB存储引擎它擅长事务处理具有崩溃恢复特性在日常开发中使用非常广泛。下面是InnoDB架构图左侧为内存结构右侧为磁盘结构。 6.2.1、内存结构
1、Buffer Pool
① 缓冲池是主内存中的一个区域里面可以缓存磁盘上经常操作的真实数据在执行增删改查操作时先操作缓冲池中的数据若缓冲池没有数据则从磁盘加载并缓存然后再以一定频率刷新到磁盘从而减少磁盘IO加快处理速度。
② 缓冲池以Page页为单位底层采用链表数据结构管理Page。根据状态将Page分为三种类型
free page空闲page未被使用。clean page被使用page数据没有被修改过。dirty page脏页被使用page数据被修改过页中数据与磁盘的数据产生了不一致。
2、Change Buffer
① 更改缓冲区针对于非唯一二级索引页在执行DML语句时如果这些数据Page没有在Buffer Pool中不会直接操作磁盘而会将数据变更存在更改缓冲区Change Buffer中在未来数据被读取时再将数据合并恢复到Buffer Pool中再将合并后的数据刷新到磁盘中。 注意 在MySQL5.x版本该缓冲区成为插入缓冲区Insert Buffer。 在MySQL8.0版本之后引入了Change Buffer。 ② Change Buffer的意义是什么
与聚集索引不同二级索引通常是非唯一的并且以相对随机的顺序插入二级索引。同样删除和更新可能会影响索引树中不相邻的二级索引页如果每一次都操作磁盘会造成大量的磁盘IO。有了Change Buffer之后我们可以在缓冲池中进行合并处理减少磁盘IO。
3、Adaptive Hash Index
① 自适应hash索引用于优化对Buffer Pool数据的查询。InnoDB存储引擎会监控对表上各索引页的查询如果观察到hash索引可以提升速度则建立hash索引称之为自适应hash索引。
② 自适应哈希索引无需人工干预是系统根据情况自动完成。
③ 参数adaptive_hash_index 4、Log Buffer
① 日志缓冲区用来保存要写入到磁盘中的log日志数据redo log、undo log默认大小为16MB日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事务增加日志缓冲区的大小可以节省磁盘I/O。
② 参数 innodb_log_buffer_size缓冲区大小 innodb_flush_log_at_trx_commit日志刷新到磁盘时机 1日志在每次事务提交时写入并刷新到磁盘0每秒将日志写入并刷新到磁盘一次2日志在每次事务提交后写入并每秒刷新到磁盘一次。 6.2.2、磁盘结构
1、System Tablespace
① 系统表空间是更改缓冲区(Change Buffer)的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的它也可能包含表和索引数据。在MySQL5.x版本中还包含InnoDB数据字典、undolog等。
② 参数innodb_data_file_path 2、File_Per_Table Tablespaces
① 每个表的文件表空间包含单个InnoDB表的数据和索引并存储在文件系统上的单个数据文件中。
② 参数innodb_file_per_table 默认是开启的。 3、General Tablespaces
①通用表空间需要通过CREATE TABLESPACE语法创建通用表空间在创建表时可以指定该表空间。
创建通用表空间
CREATE TABLESPACE 表空间名称 ADD
DATAFILE file_name
ENGINE engine_name;创建表时可以指定表空间
CREATE TABLE 表名称(...
)TABLESPACE ts_name;② 演示 创建完表空间可以新开一个标签页面cd /var/lib/mysql切换到该目录下通过ls查看是否存在myitheima.ibd文件。 4、Undo Tablespaces
撤销表空间MySQL实例在初始化时会自动创建两个默认的undo表空间初始大小16M用于存储undo日志。
默认为 5、Temporary Tablespaces
InnoDB使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。
6、Doublewrite Buffer Files
双写缓冲区InnoDB引擎将数据页从Buffer Pool刷新到磁盘前先将数据页写入双写缓冲区文件中便于系统异常时恢复数据。 7、Redo Log
重做日志是用来实现事务的持久性。该日志文件由两部分组成重做日志缓冲redo log buffer以及重做日志文件redo log file前者是在内存中后者是在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中用于在刷新脏页到磁盘时发生错误时进行数据恢复使用。
6.2.3、后台线程 1、后台线程的作用将InnoDB存储引擎缓冲池中的数据在合适的时机刷新到磁盘中的文件里。
2、后台线程有四类
① Master Thread
核心后台线程负责调度其他线程还负责将缓冲池中的数据异步刷新到磁盘中保持数据的一致性还包括脏页的刷新、合并插入缓存、undo页的回收。
② IO Thread
在InnoDB存储引擎中大量使用了AIO来处理IO请求这样可以极大地提高数据库的性能而IO Thread主要负责这些IO请求的回调。
线程类型默认个数职责Read Thread4负责读操作Write Thread4负责写操作Log Thread1负责将日志缓冲区刷新到磁盘Insert Buffer Thread1负责将写缓冲区内容刷新到磁盘
通过指令show engine innodb status;进行查看 ③ Purge Thread
主要用于回收事务以及提交了的undo log在事务提交之后undo log可能不用了就用它来回收。
④ Page Cleaner Thread
协助Master Thread刷新脏页到磁盘的线程它可以减轻Master Thread的工作压力减少阻塞。
6.3、事务管理
6.3.1、概述
1、事务
事务是一组操作的集合它是一个不可分割的工作单位事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求即这些操作要么同时成功要么同时失败。
2、事务特性
原子性Atomicity事务是不可分割的最小操作单元要么全部成功要么全部失败。一致性Consistency事务完成时必须使所有的数据都保持一致状态。隔离性Isolation数据库系统提供的隔离机制保证事务在不受外部并发操作影响的独立环境下运行。持久性Durability事务一旦提交或回滚它对数据库中的数据的改变就是永久的。
3、事务原理 原子性、一致性、持久性是由InnoDB存储引擎底层的两个日志保障的分别为redo log、undo log。
隔离性是由InnoDB存储引擎的锁机制和MVCC多版本并发控制实现的。 原子性——undo log 持久性——redo log 一致性——undo log redo log 隔离性——锁MVCC 6.3.2、redo log
1、redo log重做日志记录的是事务提交时数据页的物理修改是用来实现事务的持久性。
该日志由两部分组成重做日志缓冲redo log buffer以及重做日志文件redo log file前者是在内存中后者是在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中用于在刷新脏页到磁盘时发生错误时进行数据恢复使用。
2、原理 ① 当我们执行update操作时需要访问缓冲区看是否有此时需要的数据若没有则通过后台线程把所需的数据从磁盘中读取出来然后缓存在缓冲区中。
② 现在可以直接执行update或者delete操作直接对缓冲区的数据进行操作则缓冲区中的数据发生了变更但是磁盘中对应的数据未发生变更此时缓冲区中变更的数据页称为脏页。
③ 脏页会在一定的时机通过后台线程刷新到磁盘中从而使缓冲区与磁盘中的数据保持一致。
④ 但是脏页并不是时时刷新而是一段时间之后通过后台线程刷新到磁盘中。
⑤ 假如此时缓冲区中的脏页往磁盘中进行刷新的时候发生了错误导致了内存中脏页的数据没有刷新到磁盘中。此时事务已经提交了且已经告知用户事务提交成功了但是内存中脏页的数据没有刷新到磁盘中导致了事务的持久性未得到保障。 ⑥ 当redo log出现之后当进行增删改的之后首先将对应的数据记录在redo log buffer中在redo log buffer中会记录数据页的变化。
⑦ 当事务提交的时候会将redo log buffer中的数据页变化刷新到磁盘中持久化的保存在磁盘中。
⑧ 在过一段时间之后通过后台线程刷新脏页到磁盘中假如发生了上述⑤的情况可以通过redo log进行维护。 问为啥当事务提交的时候需要将redo log buffer中的数据页变化刷新到磁盘中而不是当事务提交的时候直接将内存中脏页刷新到磁盘中 答当事务提交的时候直接将内存中脏页刷新到磁盘中会存在严重的性能问题。当进行事务的时候通常会操作很多条记录这些记录都是随机操作我们的数据页那么此时就会涉及大量的磁盘IO。 然而当我们在操作的时候用了redo log当事务提交的时候不会直接把脏页刷新而是将redo log 文件异步刷新到磁盘中。由于它是redo log 日志文件日志文件都是追加的那么此时它就是顺序磁盘IO顺序磁盘IO速度高于随机磁盘IO。这种机制叫WALWrite-Ahead Logging。 6.3.3、undo log
1、undo log保障事务的原子性
回滚日志用于记录数据被修改前的信息作用包含两个提供回滚和MVCC多版本并发控制。
undo log和redo log记录物理日志不一样它是逻辑日志。可以认为当delete一条记录时undo log中会记录一条对应的insert记录反之依然当update一条记录时它记录一条对应相反的update记录。当执行rollback时就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。
Undo log销毁undo log在事务执行时产生事务提交时并不会立即删除undo log因为这些日志可能还用于MVCC。
Undo log存储undo log采用段的方式进行管理和记录存放在前面介绍的rollback segment回滚段中内部包含1024个undo log segment。
6.4、MVCC
6.4.1、基本概念 当前读 读取的是记录的最新版本读取时还要保证其他并发事务不能修改当前记录会对读取的记录进行加锁。 对于我们日常的操作如select ... lock in share mode共享锁select ... for update、update、insert、delete排他锁都是一种当前读。 快照读 简单的select不加锁就是快照读快照读读取的是记录数据的可见版本有可能是历史数据不加锁是非阻塞读。 Read Committed每次select都生成一个快照读。Repeatable Read开启事务后第一个select语句才是快照读的地方。Serializable快照读会退化为当前读。 MVCC 全称Multi-Version Concurrency Control多版本并发控制。指维护一个数据的多个版本使得读写操作没有冲突快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。
6.4.2、隐藏字段
1、记录中的隐藏字段
隐藏字段含义DB_TRX_ID最近修改事务ID记录插入这条记录或最后一次修改该记录的事务IDDB_ROLL_PTR回滚指针指向这条记录的上一个版本用于配合undo log指向上一个版本。DB_ROW_ID隐藏主键如果表结构没有指定主键将会生成该隐藏字段。
2、ibd2sdi xxx.ibd查看xxx.ibd文件 6.4.3、undo log
1、undo log介绍
回滚日志在insert、update、delete的时候产生的便于数据回滚的日志。
当insert的时候产生的undo log 日志只在回滚时需要在事务提交后可被立即删除。
而update、delete的时候产生的undo log 日志不仅在回滚时需要在快照读时也需要不会立即被删除。
2、undo log版本链 不同事务或相同事务对同一条记录进行修改会导致该记录的undolog生成一条记录版本链条链表的头部是最新的旧记录链表尾部是最早的旧记录。 6.4.4、readView
1、介绍
ReadView读视图是快照读SQL执行时MVCC提取数据的依据记录并维护系统当前活跃的事务未提交的id。
ReadView中包含了四个核心字段
字段含义m_ids当前活跃的事务ID集合min_trx_id最小活跃事务IDmax_trx_id预分配事务ID当前最大事务ID1因为事务ID时自增的creator_trx_idReadView创建者的事务ID
2、版本链数据访问规则
trx_id代表是当前事务ID
① trx_id creator_trx_id可以访问该版本 原因成立说明数据是当前这个事务更改的
② trx_id min_trx_id可以访问该版本 原因成立说明数据已经提交了
③ trx_id max_trx_id不可以访问该版本 原因成立说明该事务是在ReadView生成后才开启
④ min_trx_id trx_id max_trx_id如果trx_id不在m_ids中是可以访问该版本的原因成立说明数据已经提交了
3、不同的隔离级别生成ReadView的时机不同
READ COMMITTED在事务中每一次执行快照读时生成ReadView。REPEATABLE READ仅在事务中第一次执行快照读时生成ReadView后续复用该ReadView。
4、案例
① RC隔离级别下在事务中每一次执行快照读时生成ReadView。 事务5中查询id为30的记录生成ReadView当前的trx_id为4 trx_id4①②③均不符合在④中3trx_id46但4在[3,4,5]中不可以访问当前记录版本。需要回滚访问0x00003版本。trx_id3①②③均不符合在④中3trx_id36但3在[3,4,5]中不可以访问0x00003版本。需要回滚访问0x00002版本。trx_id2①不符合在②中trx_id23可以访问0x00002版本。 ② RR隔离级别下仅在事务中第一次执行快照读时生成ReadView后续复用该ReadView。 过程与①相同不同的是第二次查询复用第一次查询的ReadView。