day05-03-各种存储引擎特性

InnoDB 核心特性 (重要)

10.1 事务

事务是伴随着《交易类》业务场景出现的工作机制。

事务保证交易的“和谐”

10.1.1 事务的ACID特性

Atomicity(原子性)

原子是物质的最小构成单元,具备不可再分的特性

在一个事务工作单元中,所有标准事务语句(DML),要么全部成功执行,要么全部取消。不能出现中间状态。

Consistency(一致性)

事务发生前,中,后都应该保证数据是始终一致状态,要么全成功,反之全失败 ,MySQL的各项功能的设计,都是最重要保证一致性。

Isolated(隔离性)

MySQL 可以支持多事务并发工作的系统

某个事务工作的时候,不能受到其他事务的影响

Durability(持久性)

当事务提交(commit命令执行成功后),此次事务操作的所有数据“落盘”,都要永久保存下去。

不会因为数据实例发生故障,导致数据失效。

10.1.2 事务的生命周期(标准的事务 控制语句)

(1) 如何开启事务

begin;

(2) 标准的事务语句

DML : 
insert  
update  
delete
mysql> use world;
mysql> update city set countrycode='CHN' where id=1;
mysql> update city set countrycode='CHN' where id=2;
mysql> update city set countrycode='CHN' where id=3;

(3)事务的结束

提交:
commit;
回滚:
rollback;

10.1.3 自动提交机制(autocommit)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+

当前mysql版本特质,执行DML语句,自动执行begin,且自动commit

如果业务类型需要用到事务的话,那就需要修改默认参数

在线修改参数:
(1) 会话级别:  
mysql> set autocommit=0;
及时生效,只影响当前登录会话
(2)全局级别:
mysql> set global autocommit=0;  
断开窗口重连后生效,影响到所有新开的会话
(3)永久修改(重启生效) 
vim /etc/my.cnf 

[mysqld]

autocommit=0

### 10.1.4 隐式

提交的情况

同一个回话内,

第一个(begin)事务未提交,如果开启第二个(begin)事务,那么会触发第一个(begin)进行自动提交。

触发隐式提交的语句:

begin 
a
b
create database
导致提交的非事务语句:
DDL语句: (ALTER、CREATE 和 DROP)
DCL语句: (GRANT、REVOKE 和 SET PASSWORD)
锁定语句:(LOCK TABLES 和 UNLOCK TABLES)
导致隐式提交的语句示例:
TRUNCATE TABLE
LOAD DATA INFILE
SELECT FOR UPDATE

10.2 事务的ACID如何保证?

10.2.1 一些概念名词

redo log 重做日志

ib_logfile0~1 默认48M , 轮询使用,记录16kb数据页在data buffer pool里发生变化的过程

redo log buffer

其实就是redo内存区域,(加载redo的读和写,都会在这里)

ibd

数据页存储位置

存储 数据行 和索引

data buffer pool (简称 buffer pool,是负责ibd 读写缓冲缓存)

缓冲区池,数据页和索引页的缓冲

![image-20210310151800543](D:\data\Sync-data\simon\学习笔记\Mysql 笔记\MySql-DBA\MySQL\day05-03-各种存储引擎特性.assets\image-20210310151800543.png)

LSN (Log sequence number 日志序列号 )

LSN存在于磁盘数据页(ibd) ,redolog ,data buffer pool, redo buffer

以上区域,都会记录有各自专属的LSN号

MySQL 每次数据库启动,都会比较磁盘数据页(ibd)和redolog内的LSN,必须要求两者LSN一致数据库才能正常启动

WAL (持久化)

write ahead log

日志优先数据页,写的方式实现持久化
日志是优先于数据写入磁盘的.

脏页:

内存脏页,内存中发生了修改,没写入到磁盘之前,我们把内存页称之为脏页.

CKPT

Checkpoint,检查点,就是将脏页刷写到磁盘的动作

TXID:

事务号,InnoDB会为每一个事务生成一个事务号,伴随着整个事务.

UNDO

ibdata1,存储了事务工作过程中的回滚信息

10.2.2 事务日志-- redo 重做日志

作用?

例:

比如修改a=1

1)mysql先把a=1这个数据和LSN号(lsn=101),所在的16kb的数据页,通过IO thread线程
全部加载到 data buffer pool。

2)在buffer pool内,update改成a=2,并产生新的LSN号(比如lsn=102),然后进行commit

基于WAL(write ahead log 日志优先写的方式实现持久化)机制
此时并没有将脏页回写硬盘,而是优先写redo log

3)redo buffer内添加一条 data buffer pool内的这个数据的修改日志和对应的lsn号(lsn=102)

4)同时在redo log文件内添加一条修改记录(a=2,lsn=102)

补充: redo存储的是事务工作过程中,数据页变化。commit时会立即写入磁盘(默认)。日志落盘成功,commit才算成功

正常情况下,MySQL工作过程中,redo主要的工作是提供快速D(持久化)的功能。
当MySQL出现Crash 异常宕机时,主要提供的是前滚功能。


此时突然断电!

加电启动mysql时,mysql就会进行Crash-safe recovery ,自动故障恢复(前滚)

第一步,就是对redo log的LSN 和ibd 数据页LSN做对比检查,发现LSN不一致,
把不一致的LSN=102的记录加载到redo buffer,同时在data buffer pool加载LSN=101 那条数据的原始数据页,然后构造脏页

第二部,构造脏页完成,立即出发CKPT(持久化操作),把脏页回写到ibd的数据页内,并把ibd数据页的LSN号修改成 102

这样才能保证redo log的LSN 和 ibd 数据页的LSN一致,mysql才能进行正常启动

主要功能 保证 "D"(持久性) , A (原子性)C(一致性) 也有一定得作用
(1)记录了内存数据页的变化.
(2)提供快速的持久化功能(WAL)
(3)CSR过程中实现前滚的操作(磁盘数据页和redo日志LSN一致)

redo日志位置
redo的日志文件:iblogfile0 iblogfile1

redo buffer
redo的buffer:数据页的变化信息+数据页当时的LSN号

redo的刷写策略
commit;
刷新当前事务的redo buffer到磁盘
还会顺便将一部分redo buffer中没有提交的事务日志也刷新到磁盘
MySQL : 在启动时,必须保证redo日志文件和数据文件LSN必须一致, 如果不一致就会触发CSR,最终保证一致

情况一:
我们做了一个事务,begin;update;commit.
1.在begin ,会立即分配一个TXID=tx_01.
2.update时,会将需要修改的数据页(dp_01,LSN=101),加载到data buffer中
3.DBWR线程,会进行dp_01数据页修改更新,并更新LSN=102
4.LOGBWR日志写线程,会将dp_01数据页的变化+LSN+TXID存储到redobuffer

5.执行commit时,LGWR日志写线程会将redobuffer信息写入redolog日志文件中,基于WAL原则,
在日志完全写入磁盘后,commit命令才执行成功,(会将此日志打上commit标记)
6.假如此时宕机,内存脏页没有来得及写入磁盘,内存数据全部丢失
7.MySQL再次重启时,必须要redolog和磁盘数据页的LSN是一致的.但是,此时dp_01,TXID=tx_01磁盘是LSN=101,dp_01,TXID=tx_01,redolog中LSN=102
MySQL此时无法正常启动,MySQL触发CSR.在内存追平LSN号,触发ckpt,将内存数据页更新到磁盘,从而保证磁盘数据页和redolog LSN一值.这时MySQL正常启动
以上的工作过程,我们把它称之为基于REDO的"前滚操作"

双一标准,其中之一

select @@innodb_flush_log_at_trx_commit;

默认为1
0 --每秒刷新日志到OS cache,再fsync到磁盘。(可能会丢失1秒的事务信息数据)
1 --表示每次事务提交时,会立即刷写redo buffer到磁盘,commit才成功
2 --每次事务提交,都立即刷新redo buffer到os cache,再每秒fsync到磁盘(可能会丢失1秒的事务信息数据)

![image-20210310182027617](D:\data\Sync-data\simon\学习笔记\Mysql 笔记\MySql-DBA\MySQL\day05-03-各种存储引擎特性.assets\image-20210310182027617.png)

redo buffer size 增加,可以一定程度提高数据库的并发能力,但性能方面不一定会提高。

另外

redo buffer还和OS Cache机制有关系,所以刷写策略会和innodb_flush_method参数有关系

redo 也有group commit; 可以理解为,在每次刷新已提交的redo时,顺便把未提交的事务redo(打是否提交的标记)一并刷写到磁盘


10.2.3 undo

ibdata1: undo表空间内,默认128个回滚段(slot)

(96个undo slot + 32个ibtmp1 临时表 slot)

undo记录了,用来提供事务回滚日志的一些信息,以及构建当前事务快照的一些信息

回滚日志.
作用: 在 ACID特性中,主要保证A(原子性)的特性,同时对C(一致性)I(隔离性)也有一定功效

(1)记录了数据修改之前的状态
(2)rollback 将内存的数据修改恢复到修改之前
(3)在CSR中实现未提交数据的回滚操作
(4)实现一致性快照,配合隔离级别保证MVCC,读和写的操作不会互相阻塞

undo 内修改数据页变化的信息,会记录在redo里面。也就是说,redo里面会记录属于undo的redo信息

![image-20210310202949209](D:\data\Sync-data\simon\学习笔记\Mysql 笔记\MySql-DBA\MySQL\day05-03-各种存储引擎特性.assets\image-20210310202949209.png)

整个CSR实现过程,一定是先redo前滚,再undo回滚,必须是这个顺序

1.首先从ibd文件加载数据页到buffer pool,确认LSN=001,TRX_ID=010
2.从ib_logfile读取redo事务修改信息加载到redo buffer(LSN=002,TRX_ID=010, commit标记是未提交),同时从ibdata文件读取undo快照记录加载到buffer(LSN=001,trx_id=010,commit标记是已提交)
3.通过trx_id发现是同一个事务,然后按照最新的LSN号 ,重构脏数据
4.重构脏数据完成后发现,commit标记是未提交
5.此时通过数据行尾部的DB_TRX_ID(更新事务ID) 和 DB_ROLL_PTR(回滚段指针)找到undo slot里面对应的旧版本数据行快照
6.最终进行事务回滚操作,LSN=001,undo修改操作对应的redo信息一并记录在redo里
7.此时检查数据LSN和redo lsn,确认保持一致,开启数据实例

一致性快照技术

每个事物开启时(begin),都会通过undo生成一个一致性快照。

保证了MVCC,隔离性,mysqldump的热备恢复机制

MVCC其实就是基于undo内同一数据行不同版本的快照,从而实现更高的事务并发,这么一种工作模式


posted @ 2022-11-24 20:19  oldSimon  阅读(9)  评论(0)    收藏  举报