MySQL 数据库服务事务知识

news/2025/10/29 9:41:31/文章来源:https://www.cnblogs.com/zhangwencheng/p/19168425

数据库存储事务机制概念

事务(Transaction)可以更通俗的理解为交易,所以事务会伴随着交易类的业务类型出现的概念(工作模式);

现实生活中存在很多的交易行为,比如:物换物的等价交换、货币换物的等价交换、虚拟货币换物(虚拟物品)的等价交换;

因此就需要考虑如何保证现实生活中交易过程的和谐,一般会有法律、道德等方面规则进行约束;

而在数据库服务中为了保证线上交易的"和谐",便加入了"事务"工作机制

数据库存储事务机制特性

在数据库服务中引入事务机制概念,主要是为了应用事务机制的相关特性处理安全一致性问题,其中事务机制主要包含的特性有:

特性一:原子性(Atomicity)

原子性表示一个事务生命周期中的DML语句,要么全成功要么全失败,不可以出现中间状态;

语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于undo log

Begin:DML01 DML02 DML03 Commit;

特性二:一致性(Consistency)

一致性表示一个事务发生前、中、后,数据都最终保持一致,即读和写都要保证一致性;

事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障;

CR + Double write

特性三:隔离性(Isolation)

隔离性表示一个事务操作数据行的时候,不会受到其他事务的影响,主要利用锁机制来保证隔离性;

特性四:持久性(Durability)

持久性表示一旦事务进行了提交,即可永久生效(落盘)

保证事务提交后不会因为宕机等原因导致数据丢失;实现主要基于redo log

事务ACID相关知识官方说明:https://dev.mysql.com/doc/refman/8.0/en/mysql-acid.html

数据库存储事务生命周期

在运用事务机制完成相关工作任务时,对于事务使用是存在生命周期概念的,标准显示的事务生命周期控制语句有:

-- 开启事务机制
begin;
start transaction;-- 提交事务任务
commit;-- 回滚事务操作
rollback;

说明:事务生命周期中,只能使用DML语句,其中包括:select、update、delete、insert;DDL语句会隐式进行提交

事务的生命周期操作演示:

# 进行测试数据库查询数据
mysql> use world;
mysql> select * from city limit 10;# 进行测试数据库数据撤销修改
mysql> begin;
mysql> update city set population=10 where id=1;
mysql> update city set population=10 where id=2;
-- 由于是采用事务进行的修改,所以只是在内存层面进行的修改,并没有对磁盘上的数据进行修改;
mysql> select * from city limit 10;
-- 由于是采用事务进行的修改,此时看到的数据信息只是内存层面的修改信息
mysql> rollback;
-- 由于是采用事务进行的撤销,会读取undo文件信息,将事务操作撤回到事务开始前的状态
mysql> select * from city limit 10;
-- 由于是采用事务进行的修改,当撤销操作执行完,看到数据信息还是原来的;# 进行测试数据库数据永久修改
mysql> begin;
mysql> update city set population=10 where id=1;
mysql> update city set population=10 where id=2;
-- 由于是采用事务进行的修改,所以只是在内存层面进行的修改,并没有对磁盘上的数据进行修改;
mysql> select * from city limit 10;
-- 由于是采用事务进行的修改,此时看到的数据信息只是内存层面的修改信息
mysql> commit;
-- 由于是采用事务进行的提交,会加载redo文件信息,将事务内存层面的修改同步到磁盘中(完成了D特性)
mysql> select * from city limit 10;
-- 由于是采用事务进行的修改,当执行操作执行完,看到数据信息将永久保存下载;

数据库存储事务提交方式

方式一:在事务生命周期管理过程中,事务的提交机制可以采用自动提交方式(auto_commit)

事务自动提交方式作用说明:

事务自动提交表示在没有显示的使用begin语句的时候,执行DML操作语句时,会在DML操作语句前自动添加begin

并在DML操作语句执行后自动添加commit

在生产环境中,若处于频繁事务业务场景中,建议关闭autocommit自动提交功能,或者每次事务执行的时候;

都进行显示的执行begincommit

事务自动提交方式参数信息:

mysql> select @@autocommit;
+---------------------+
| @@autocommit |
+---------------------+
|                          1 |
+---------------------+
1 row in set (0.00 sec)
-- 在事务自动提交功能设置修改时,设置为1表示开启自动提交,设置为0表示关闭自动提交

事务自动提交方式参数修改:

# 临时关闭事务自动提交功能
mysql> set global autocommit=0;
-- 配置调整后,重新登录mysql数据库生效# 永久关闭事务自动提交功能
[root@xiaoQ-01 ~]# vim /etc/my.cnf
[mysqld]
autocommit=0
-- 配置调整后,重新启动mysql数据库生效

事务自动提交方式设置方式优点缺点说明:

序号 参数配置 优劣势
情况1 autocommit=0
关闭事务自动提交
优势:可以编写多个关联的DML,进行一次性提交操作,若出现异常可以回滚
符合原子特性
劣势:可能出现多个关联的DML,只是完成了部分操作,这时就可能等待状态
基于隔离特性,操作的数据表或数据行就会进入锁定状态
情况2 autocommit=1
开启事务自动提交
优势:可以出现多个关联的DML,逐行操作自动提交,就可以不用处于锁等待状态
劣势:可能出现多个关联的DML,,每执行一条就进行提交,会造成多个语句执行不符合原子性

方式二:在事务生命周期管理过程中,事务的提交机制可以采用隐式提交方式:

在进行事务操作时,需要注意操作语句必须都是DML语句,如果中间插入了DDL语句,也会造成之前的事务操作自动提交;

begin; DML1; DML2; DDL1; COMMIT; DML3; COMMIT;
-- 这种情况出现会破坏原本事务的原子性

隐式自动提交方式语句:

在出现隐式自动提交时,可能导致提交的非事务语句有:

序号 语句类型 涉及命令
01 DDL语句类型 alter、create、drop
02 DCL语句类型 grant、revoke、set password
03 锁定语句类型 lock tables、unlock tables
04 其他语句类型 truncate table、load data infile、select for update

说明:在多个数据库会话窗口中,A窗口的所有事务性DML操作,不会受到B窗口的非事务语句影响,同一会话窗口会有影响;

隐式自动回滚情况分析:

  • 情况一:在事务操作过程中,会话窗口自动关闭了,会进行隐式自动回滚;
  • 情况二:在事务操作过程中,数据库服务被停止了,会进行隐式自动回滚;
  • 情况三:在事务操作过程中,出现事务冲突死锁了,会进行隐式自动回滚;

数据库存储事务隔离级别

数据库事务隔离级别主要作用是实现事务工作期间,数据库操作读的隔离特性,所谓读的操作就是将数据页可以调取到内存;

然后可以读取数据页中相应数据行的能力,并且不同事务之间的数据页读操作相互隔离;

可以简单理解为:一个事务在对数据页中数据行做更新操作时,在没有更新提交前,另一个事务此时是不能读取数据页中数据行内容的;

对于数据库存储事务隔离级别包括4种,可以通过操作命令查看获取当前使用的隔离级别:

mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation  |
+---------------------------------+
| REPEATABLE-READ              |
+---------------------------------+
1 row in set (0.00 sec)

常用的事务隔离级别类型:

类型一:RU(READ-UNCOMMITTED 表示读未提交)

可以读取到事务未提交的数据,隔离性差,会出现脏读(当前内存读),不可重复读,幻读问题;

类型二:RC(READ-COMMITTED 表示读已提交)可用

可以读取到事务已提交的数据,隔离性一般,不会出现脏读问题,但是会出现不可重复读,幻读问题;

类型三:RR(REPEATABLE-READ 表示可重复读)默认

可以防止脏读(当前内存读),防止不可重复读问题,防止会出现的幻读问题,但是并发能力较差;

会使用next lock锁进制,来防止幻读问题,但是引入锁进制后,锁的代价会比较高,比较耗费CPU资源,占用系统性能;

类型四:SR(SERIALIZABLE 可串行化)

隔离性比较高,可以实现串行化读取数据,但是事务的并发度就没有了;

这是事务的最高级别,在每条读的数据上,加上锁,使之不可能相互冲突

事务隔离级别官方链接:https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html

常用的事务隔离级别名词:

在解释分析说明相应的隔离级别名词前,需要对数据库事务隔离级别进行调整,以及关闭自动提交功能:

# 设置事务隔离级别
mysql> set global transaction_isolation='READ-UNCOMMITTED';
mysql> set global transaction_isolation='READ-COMMITTED';
mysql> set global transaction_isolation='REPEATABLE-READ';# 查看事务隔离级别
mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation |
+---------------------------------+
| READ-UNCOMMITTED         |
+---------------------------------+
mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation  |
+---------------------------------+
| READ-COMMITTED               |
+---------------------------------+
mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation |
+---------------------------------+
| REPEATABLE-READ             |
+---------------------------------+# 临时关闭自动提交功能:
mysql> set global autocommit=0;
mysql> select @@autocommit;
+---------------------+
| @@autocommit |
+---------------------+
|                          0 |
+---------------------+

创建隔离级别测试数据表:

mysql> use mydb
mysql> create table t1 (id int not null primary key auto_increment,a int not null,b varchar(20) not null,c varchar(20) not null
) charset=utf8mb4 engine=innodb;mysql> begin;
mysql> insert into t1(a,b,c)
values
(5,'a','aa'),
(7,'c','ab'),
(10,'d','ae'),
(13,'g','ag'),
(14,'h','at'),
(16,'i','au'),
(20,'j','av'),
(22,'k','aw'),
(25,'l','ax'),
(27,'o','ay'),
(31,'p','az'),
(50,'x','aze'),
(60,'y','azb');
mysql> commit;
-- 确认两个SQL会话窗口,即不同的事务查看的数据是否一致的;
  • 名词解读分析一:脏读

脏读主要表示在一个事务窗口中,没有数据修改提交操作前,另一个事务就可以看到内存中数据页的修改;

简单理解:在一个事务窗口中,可以读取到别人没有提交的数据信息;

利用隔离级别RU解读:

# 设置事务隔离级别
mysql> set global transaction_isolation='READ-UNCOMMITTED';
mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation |
+---------------------------------+
| READ-UNCOMMITTED         |
+---------------------------------+
mysql> set global autocommit=0;
mysql> select @@autocommit;
-- 重新开启两个SQL会话窗口# 数据库A会话窗口操作
mysql> begin;
mysql> update t1 set a=10 where id=1;
-- 只是在内存层面进行数据页中数据修改
mysql> rollback;
-- 进行事务回滚操作# 数据库B会话窗口操作
mysql> begin;
mysql> select * from t1 where id=1;
+----+----+---+----+
| id   | a   | b  | c   |
+----+----+---+----+
|  1   | 10 | a  | aa |
+----+----+---+----+
1 row in set (0.01 sec)
-- 在A会话窗口没提交的事务修改,被B会话窗口查询到了
mysql> select * from t1 where id=1;
+----+----+---+----+
| id   | a   | b  | c   |
+----+----+---+----+
|  1   | 5   | a  | aa |
+----+----+---+----+
1 row in set (0.01 sec)
-- 在A会话窗口进行回滚后,在B窗口查询的数据又恢复了
  • 名词解读分析二:不可重复读

不可重复读表示在一个事务中,利用相同的语句多次查询,获取的数据信息是不同的;

利用隔离级别RU解读:

# 数据库B会话窗口操作
mysql> begin;
mysql> select * from t1 where id=1;
+----+----+---+----+
| id   | a   | b  | c   |
+----+----+---+----+
|  1   | 10 | a  | aa |
+----+----+---+----+
1 row in set (0.01 sec)
-- 在B会话事务窗口进行数据第一次查询看到数据信息:a=10
mysql> select * from t1 where id=1;
+----+----+---+----+
| id   | a   | b  | c   |
+----+----+---+----+
|  1   | 5   | a  | aa |
+----+----+---+----+
1 row in set (0.01 sec)
-- 在B会话事务窗口进行数据第二次查询看到数据信息:a=5

利用隔离级别RC解读:

# 设置事务隔离级别
mysql> set global transaction_isolation='READ-COMMITTED';
mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation |
+---------------------------------+
| READ-COMMITTED              |
+---------------------------------+
mysql> set global autocommit=0;
mysql> select @@autocommit;
-- 重新开启两个SQL会话窗口# 数据库A会话窗口操作
mysql> use mydb;
mysql> begin;
mysql> select * from t1 where id=1;
+----+---+---+----+
| id   | a  | b  | c  |
+----+---+---+----+
|  1   | 5  | a  | aa |
+----+---+---+----+
1 row in set (0.00 sec)
-- A窗口事务查询信息 = B窗口事务查询信息
mysql> update t1 set a=10 where id=1;
-- A窗口事务进行修改
mysql> commit;
-- A窗口事务进行提交# 数据库B会话窗口操作
mysql> use mydb;
mysql> begin;
mysql> select * from t1 where id=1;
+----+---+---+----+
| id   | a  | b  | c  |
+----+---+---+----+
|  1   | 5  | a  | aa |
+----+---+---+----+
1 row in set (0.00 sec)
-- A窗口事务查询信息 = B窗口事务查询信息
mysql> select * from t1 where id=1;
+----+---+---+----+
| id   | a  | b  | c  |
+----+---+---+----+
|  1   | 5  | a  | aa |
+----+---+---+----+
1 row in set (0.00 sec)
-- B窗口事务查询信息,不能看到A窗口事务未提交的数据变化,避免了脏数据问题;
mysql> select * from t1 where id=1;
+----+---+---+----+
| id   | a  | b  | c  |
+----+---+---+----+
|  1   | 10 | a  | aa |
+----+---+---+----+
1 row in set (0.00 sec)
-- A窗口事务提交之后,B窗口事务查询信息和之前不同了

利用隔离级别RR解读:

# 设置事务隔离级别
mysql> set global transaction_isolation='REPEATABLE-READ';
mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation |
+---------------------------------+
| REPEATABLE-READ              |
+---------------------------------+
mysql> set global autocommit=0;
mysql> select @@autocommit;
-- 重新开启两个SQL会话窗口# 数据库A会话窗口操作
mysql> use mydb;
mysql> begin;
mysql> select * from t1;
-- 确认初始数据信息
mysql> update t1 set a=10 where id=1;
-- A窗口事务进行修改
mysql> commit;
-- A窗口事务进行提交# 数据库B会话窗口操作
mysql> use mydb;
mysql> begin;
mysql> select * from t1;
-- 确认初始数据信息
mysql> select * from t1 where id=1;
+----+---+---+----+
| id   | a  | b  | c  |
+----+---+---+----+
|  1   | 5  | a  | aa |
+----+---+---+----+
1 row in set (0.00 sec)
-- B窗口事务查询信息,不能看到A窗口事务未提交的数据变化,避免了脏数据问题;
mysql> select * from t1 where id=1;
+----+---+---+----+
| id   | a  | b  | c  |
+----+---+---+----+
|  1   | 5  | a  | aa |
+----+---+---+----+
1 row in set (0.00 sec)
-- A窗口事务提交之后,B窗口事务查询信息和之前是相同的;
-- 在RR级别状态下,同一窗口的事务生命周期下,每次读取相同数据信息是一样,避免了不可重复读问题
mysql> commit;
mysql> select * from t1 where id=1;
-- 在RR级别状态下,同一窗口的事务生命周期结束后,看到的数据信息就是修改的了
  • 名词解读分析三:幻读

利用隔离级别RC解读:

# 设置事务隔离级别
mysql> set global transaction_isolation='READ-COMMITTED';
mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation |
+---------------------------------+
| READ-COMMITTED              |
+---------------------------------+
mysql> set global autocommit=0;
mysql> select @@autocommit;
-- 重新开启两个SQL会话窗口# 数据库A会话窗口操作(重新进入)
mysql> use mydb;
mysql> select * from t1;
+----+----+---+-----+
| id | a  | b | c   |
+----+----+---+-----+
|  1 | 10 | a | aa  |
|  2 |  7 | c | ab  |
|  3 | 10 | d | ae  |
|  4 | 13 | g | ag  |
|  5 | 14 | h | at  |
|  6 | 16 | i | au  |
|  7 | 20 | j | av  |
|  8 | 22 | k | aw  |
|  9 | 25 | l | ax  |
| 10 | 27 | o | ay  |
| 11 | 31 | p | az  |
| 12 | 50 | x | aze |
| 13 | 60 | y | azb |
+----+----+---+-----+
13 rows in set (0.00 sec)
-- 查看获取A窗口表中数据
mysql> alter table t1 add index idx(a);
-- 在A窗口中,添加t1表的a列为索引信息
mysql> begin;
-- 在A窗口和B窗口中,同时做开始事务操作;
mysql> update t1 set a=20 where a<20;
-- 在A窗口中,将a<20的信息均调整为20
mysql> commit;
-- 在A窗口中,进行事务提交操作,是在B窗口事务没有提交前
mysql> mysql> select * from t1;
-- 在A窗口中,查看数据信息,希望看到的a是没有小于20的,但是结果看到了a存在等于10的(即出现了幻读)# 数据库B会话窗口操作(重新进入)
mysql> use mydb;
mysql> select * from t1;
+----+----+---+-----+
| id | a  | b | c   |
+----+----+---+-----+
|  1 | 10 | a | aa  |
|  2 |  7 | c | ab  |
|  3 | 10 | d | ae  |
|  4 | 13 | g | ag  |
|  5 | 14 | h | at  |
|  6 | 16 | i | au  |
|  7 | 20 | j | av  |
|  8 | 22 | k | aw  |
|  9 | 25 | l | ax  |
| 10 | 27 | o | ay  |
| 11 | 31 | p | az  |
| 12 | 50 | x | aze |
| 13 | 60 | y | azb |
+----+----+---+-----+
13 rows in set (0.00 sec)
-- 查看获取B窗口表中数据
mysql> begin;
mysql> insert into t1(a,b,c) values(10,'A','B')
-- 在B窗口中,插入一条新的数据信息 a=10 
mysql> commit;
-- 在B窗口中,进行事务提交操作

利用隔离级别RR解读:

# 设置事务隔离级别
mysql> set global transaction_isolation='REPEATABLE-READ';
mysql> select @@transaction_isolation;
+---------------------------------+
| @@transaction_isolation |
+---------------------------------+
| REPEATABLE-READ              |
+---------------------------------+
mysql> set global autocommit=0;
mysql> select @@autocommit;
-- 重新开启两个SQL会话窗口# 数据库A会话窗口操作
mysql> use mydb;
mysql> select * from t1;
-- 查看获取A窗口表中数据
mysql> alter table t1 add index idx(a);
-- 在A窗口中,添加t1表的a列为索引信息
mysql> begin;
mysql> update t1 set a=20 where a>20;
-- 在A窗口中,将a>20的信息均调整为20# 数据库B会话窗口操作
mysql> use mydb;
mysql> select * from t1;
-- 查看获取B窗口表中数据
mysql> begin;
mysql> insert into t1(a,b,c) values(30,'sss','bbb');
-- 在B窗口中,插入一条新的数据信息 a=30,但是语句执行时会被阻塞,没有反应;
mysql> show processlist;
-- 在C窗口中,查看数据库连接会话信息,insert语句在执行,等待语句超时(默认超时时间是50s)
-- 因为此时在RR机制下,创建了行级锁(阻塞修改)+间隙锁(阻塞区域间信息插入)=next lock
-- 区域间隙锁 < 左闭右开(可用临界值)  ;  区域间隙锁 > 左开右闭(不可用临界值)

事务隔离机制知识点补充:

提到事务肯定不陌生,和数据库打交道的时候,总是会用到事务。

最经典的例子就是转账,你要给朋友小王转 100 块钱,而此时你的银行卡只有 100 块钱。

转账过程具体到程序里会有一系列的操作,比如查询余额、做加减法、更新余额等,这些操作必须保证是一体的;

不然等程序查完之后,还没做减法之前,你这100块钱,完全可以借着这个时间差再查一次,然后再给另外一个朋友转账,

如果银行这么整,不就乱了么?这时就要用到“事务”这个概念了。

简单来说,事务就是要保证一组数据库操作,要么全部成功,要么全部失败。

在 MySQL 中,事务支持是在引擎层实现的。MySQL 是一个支持多引擎的系统,但并不是所有的引擎都支持事务。

比如 MySQL 原生的 MyISAM 引擎就不支持事务,这也是 MyISAM 被 InnoDB 取代的重要原因之一。

下面将会以 InnoDB 为例,剖析 MySQL 在事务支持方面的特定实现,并基于原理给出相应的实践建议,希望这些案例能加深你对 MySQL 事务原理的理解。

隔离性与隔离级别

提到事务,肯定会想到 ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性),

我们就来说说其中 I,也就是“隔离性”。

当数据库上有多个事务同时执行的时候,就可能出现以下问题:

  • 脏读(dirty read)
  • 不可重复读(non-repeatable read)
  • 幻读(phantom read)

为了解决这些问题,就有了“隔离级别”的概念。在谈隔离级别之前,首先要知道,隔离得越严实,效率就会越低。

因此很多时候,都要在二者之间寻找一个平衡点。SQL 标准的事务隔离级别包括:

隔离级别 英文描述 解释说明
读未提交 RU-read uncommitted 一个事务还没提交时,它做的变更就能被别的事务看到。
读提交 RC-read committed 一个事务提交之后,它做的变更才会被其他事务看到。
可重复读 RR-repeatable read 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。
当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。
串行化 serializable 顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。
当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

其中“读提交”和“可重复读”比较难理解,所以我用一个例子说明这几种隔离级别。

假设数据表 T 中只有一列,其中一行的值为 1,下面是按照时间顺序执行两个事务的行为。

mysql> create table T(c int) engine=InnoDB;
mysql> insert into T(c) values(1);

两个事务操作行为:

事务行为顺序 事务A 事务B
01 启动事务;查询得到值1 启动事务
02 查询得到值1
03 将1改为2
04 查询得到值v1
05 提交事务B
06 查询得到值v2
07 提交事务A
08 查询得到值v3

在不同的隔离级别下,事务 A 会有哪些不同的返回结果,也就是图里面 V1、V2、V3 的返回值分别是什么。

  • 若隔离级别是“读未提交”:

则 V1 的值就是 2,事务 B 虽然还没有提交,但是结果已经被 A 看到了。因此,V2、V3 也都是 2。

  • 若隔离级别是“读提交”:

则 V1 是 1,V2 的值是 2,事务 B 的更新在提交后才能被 A 看到。所以, V3 的值也是 2。

  • 若隔离级别是“可重复读”:

则 V1、V2 是 1,V3 是 2,之所以 V2 还是 1,遵循的就是这个要求:事务在执行期间看到的数据前后必须是一致的。

  • 若隔离级别是“串行化”:

则在事务 B 执行“将 1 改成 2”的时候,会被锁住。直到事务 A 提交后,事务 B 才可以继续执行。

所以从 A 的角度看, V1、V2 值是 1,V3 的值是 2。

数据库存储事务工作流程

根据存储事务的工作流程原理,来了解如何保证事务的ACID特性,利用了MySQL数据库的哪些工作机制;

事务工作流程名字解释:

  • 名词解释一:redo log-Disk

表示重做日志,当出现异常情况,内存中数据直接写入磁盘失败时,可以通过重启数据库服务,读取此文件修复数据信息;

文件存储表项为:ib_logfile0~N 默认48M,轮询使用

  • 名词解释二:redo log buffer-mem

表示重做日志生成缓冲区,相当于redo log的内存区域。redo log文件与redo log buffer是有IO关系的;

事务修改提交后:redo log buffer -> redo log,表示写入数据到redo log;

事务操作恢复时:redo log -> redo log buffer,表示读取数据从redo log;

  • 名词解释三:tablespace file-disk

表示存储表数据行和索引等信息的文件,含有表空间所有数据文件;ibd

  • 名词解释四:Innodb buffer pool-mem

表示数据缓冲区,主要用于缓冲事务要处理的数据和索引信息,tablespace文件与buffer pool是有IO关系的;

  • 名词解释五:LSN

表示日志序列号,在buffer pool中有数据页信息的变化就会记录到redo log buffer中,主要记录变化了多少字节量;

利用LSN记录相应数据页的变化量(LSN+变化字节量),也可以理解为记录的是日志量的变化;

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

  • 名词解释六:WAL(Write Ahead Log)

表示redo日志生成记录优先于数据页写入到磁盘的过程,并且是支持预写入机制(group commit)的;

  • 名词解释七:Dirty page

表示在内存进行修改的数据页,在redo buffer中会记录数据页的数据量的变化,此时在数据页还未最终写入到磁盘中时;

就称之为脏页,所以一般所谓的脏读就是读取脏页的数据页信息;

  • 名词解释八:CheckPoint

表示为检查点,就是将脏页刷写到磁盘的动作;

  • 名词解释九:DB_TRX_ID(6字节)

表示为事务ID号,InnoDB会为每一个事务生成一个事务号(由事务管理器管理TM),伴随着整个事务生命周期

其中事务ID号码信息,在redo和undo日志文件中都会有相应的标识;

  • 名词解释十:DB_ROLL_PTR(7字节)

表示回滚指针,在rollback时会使用undo日志回滚已修改的数据,DB_ROLL_PTR会指向此次事务的回滚业务点;

从而找到undo上的相应的日志信息;

数据库名词解释官方参考:https://dev.mysql.com/doc/refman/8.0/en/glossary.html

事务工作流程具体解读:

简单事务情况举例:

mysql> begin;
mysql> update t1 set A=2 where A=1;
mysql> commit;

事务工作流程一:redo log 重做日志如何应用

  • 用户发起update操作事务语句,将磁盘数据页(page100,A=1,LSN=1000)加载到内存(buffer_pool)缓冲区;

  • 将在内存中发生数据页修改操作(A=1改为A=2),形成数据页脏页,更改中数据页的变化会记录到redo buffer中;

    加入1000个字节日志信息,LSN=1000+1000=2000;

  • 当执行事务提交操作的时候,基于WAL机制,等到redo buffer中的日志完全落盘到ib_logfileN-redo log中,即commit正式完成;

  • 此时ib_logfileN中记录了一条日志,内容为:page100数据页变化+LSN=2000

简单理解:记录内存数据页变化日志+undo(DB_TRX_ID,DB_ROLL_PTR),通过LSN和数据页建立关系

特殊情景分析:当此时,redo落盘了,数据页没有落盘,出现宕机情况了;

  • MySQL CR(自动故障恢复)工作模式,启动数据库时,自动检查redo的LSN和数据页LSN;
  • 如果发现redo LSN > 数据页的LSN,加载原始数据页+变化redo指定内存,使用redo重构脏页(前滚);
  • 如果确认此次事务已经提交(commit标签),立即触发CKPT(checkpoint)动作,将脏页刷写到磁盘上;

知识点补充:

MySQL有一种机制,批量刷写redo的机制:会在A事务commit时,顺便将redo buffer中的未提交的redo日志也一并刷到磁盘;

为了区分不同状态的redo,日志记录时会标记是否commit;

redo保证了ACID哪些特性:

主要保证了D的特性,另外A C也有间接关联;

Redo Log日志文件生成流程:

1668703457452

Redo Log日志文件应用流程:

1668703613790

说明:利用redo Log重做日志功能可以保证事务的D特性,基于可以丢内存数据,但是不可以丢操作事务日志的原则;

存储引擎读写磁盘数据页IO信息:

mysql> select @@innodb_read_io_threads;
+------------------------------------+
| @@innodb_read_io_threads |
+------------------------------------+
|                                                4 |
+------------------------------------+
1 row in set (0.00 sec)
-- 接收SQL层处理信息传达到存储引擎层的读IO配置信息;mysql> select @@innodb_write_io_threads;
+------------------------------------+
| @@innodb_write_io_threads |
+------------------------------------+
|                                                 4 |
+------------------------------------+
1 row in set (0.00 sec)
-- 接收SQL层处理信息传导到存储引擎层的写IO配置信息

存储引擎序号号码信息查看:

mysql> show engine innodb status\G
Log sequence number                   105377511
-- redo buffer中的SN号码信息
Log flushed up to                           105377511
-- redo buffer刷新到磁盘上的SN号码信息
Last checkpoint at                         105377511
-- 磁盘数据页的SN号码信息

存储引擎redo buffer落盘的机制策略:****

mysql> select @@innodb_flush_log_at_trx_commit;
+-----------------------------------------------+
| @@innodb_flush_log_at_trx_commit |
+-----------------------------------------------+
|                                                               1 |
+-----------------------------------------------+
1 row in set (0.00 sec)
-- 表示数据库配置与安全有关的两个双一配置
-- 当数值为1:表示每次事务提交就立刻进行redo buffer刷新落盘,若落盘不成功,则commit命令操作也不会成功;默认
-- 当数值为0:表示日志缓存信息写入磁盘是按照每秒种进行一次操作,未刷新日志的事务可能会在崩溃中丢失;不安全
-- 当数值为2:表示在事务提交后先生成日志缓存信息,然后再按照每秒钟进行一次写入磁盘操作;不安全
-- 参考官方链接:https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html

事务工作流程二:undo log 回滚日志如何应用

  • 事务发生数据页修改之前,会申请一个undo事务操作,保存了事务回滚日志(逆向操作的逻辑日志)
  • undo写完之后,事务修改数据页头部(会记录DB_TRX_ID+DB+ROLL_PTR),这个信息也会被记录在redo Log中

简单理解:记录数据修改的前镜像(逆向操作),数据页和undo通过DB_TRX_ID,DB_ROLL_PTR建立关系

特殊情景分析01:

当执行rollback命令时,根据数据页的DB_TRX_ID+DB+ROLL_PTR信息,找到undo日志并进行回滚;

特殊情景分析02:

mysql> begin;
mysql> update t1 set A=2 where A=1;
-- 此时宕机了

假设:undo 有;redo 没有

  • 启动数据库时,检查redo和数据页的LSN号码,发现是一致的;
  • 所以不需要进行redo的前滚,此时也不需要回滚。undo信息直接被标记为可覆盖状态;

假设:undo 有;redo 也有(没有commit标签)

  • MySQL CR(自动故障恢复)工作模式,启动数据库时,自动检查redo的LSN和数据页LSN;
  • 如果发现redo LSN>数据页的LSN。随即加载原始数据页+变化redo Log日志信息到相应内存位置,使用redo重构脏页(前滚);
  • 如果确认此次事务没有commit标记,立即触发回滚操作,根据DB_TRX_ID+DB_ROLL_PTR信息,找到undo回滚日志,实现回滚;

以上流程被称之为InnoDB的核心特性:自动故障恢复(CR),会先前滚再回滚,先应用redo再应用undo;

undo保证了ACID哪些特性:

主要保证事务的A的特性,同时C和I的特性也有关系;

undo Log日志文件生成流程:

1668741592412

undo Log日志文件应用流程:

1668741660424

说明:利用undo Log重做日志功能可以保证事务的A特性,基于先进行数据页前滚操作恢复脏页,在进行回滚操作恢复操作前事务;

事务工作流程三:事务中的C特性如何保证

InnoDB crash recovery:数据库意外宕机时刻,通过redo前滚+undo回滚保证数据的最终一致;

InnoDB doubewrite buffer:默认存储在ibdataN中,解决数据页写入不完整;DWB一共2M,分两次。每次1M写入;

redo日志只能恢复好的数据页的内容,但是不能恢复已经有异常的数据页内容;

可以参考官方资料:https://dev.mysql.com/doc/refman/8.0/en/mysql-acid.html

DWB文件信息生成流程:

1668751315005

DWB文件信息应用流程:

1668751396397

事务工作流程四:事务中的I特性如何保证

主要对数据库服务并发访问资源的保护,在并发事务工作期间,防止事务与事务之间的资源争抢(相互影响);

  • 保证读隔离性

方式一:利用隔离级别保证

序号 隔离级别 简单回顾
01 RU 有可能会出现脏读、不可重复读、幻读
02 RC 有可能会出现不可重复读,幻读
03 RR 有可能会出现幻读(99.9%的读异常问题配合锁机制都可以处理)
04 SR(SE) 采用事务串行工作机制

方式二:利用MVCC机制隔离(只能保证读的隔离)

MVCC(multi-version-concurrent-control)即多版本并发控制,是一种并发控制的方法;

可以类别成Git进行并发处理的机制,其实就是每个事务在发生更新的过程中,维护发生更新事务的各个版本;

各个事务版本通过undo的日志(前镜像)实现快照的技术(read view),从而可以保存多个事务版本;

对于隔离级别而言,只有RC和RR级别可以使用到MVCC机制的,实现一种快照读机制,而RU和SR级别是不会使用到MVCC机制的;

  • RC:应用MVCC的快照读机制,是基于语句级别的;(不可重复读 ture)

在事务期间,执行每个查询语句的时候,都会检查MVCC版本(快照列表),获取最新的已提交事务的快照;

  • RR:应用MVCC的快照读机制,是基于事务级别的;(不可重复读 false)

在事务期间,执行首条查询语句的时候,就会生成MVCC版本(相应快照),将会一直读取此快照数据信息,直到事务生命周期结束;

以上的RR隔离级别利用MVCC的快照读机制,又称为一致性快照读;

==================================================================================================

MVCC进行多版本控制时,会应用的两种锁机制:乐观锁/悲观锁

每个事务操作都要经历两个阶段:

  • 读阶段--应用乐观锁:

MVCC利用乐观锁机制,实现非锁定读取,借助快照技术(read view)

# 进行操作事务处理过程(trx1)
> begin;
> DML01 语句
-- 在做第一次事务操作的时候,当前事务获取系统最新的 rv1 版本快照
> DML02 语句
-- 在做下一次事务操作的时候,生成新的事务系统查询的 rv2 版本快照
> select 
-- 此时查询的是 rv2快照数据信息
> commit
-- rv2 快照数据被提交,成为系统最新的快照

RC隔离级别快照应用:

trx-01:rv1  -> rv2  -> commit;
trx-02:rv1  -> rv1  -> rv2

RR隔离级别快照应用:

trx-01:第一个查询时,生成global consitence snapshot RV-CS1(10:00),一直伴随着事务生命周期结束
trx-02:第一个查询时,生成global consitence snapshot RV-CS2(10:01),一直伴随着事务生命周期结束
  • 写阶段--应用悲观锁:

即对于写操作,是不能进行并发操作的;

MVCC技术总结:

01 mvcc采用乐观锁机制,实现非锁定读取;

02 在RC级别下,事务中可以立即读取到其它事务提交过的readview数据快照信息;

03 在RR级别下,事务中从第一次查询开始,生成一个一致性readview,直到事务结束

==================================================================================================

  • 保证写隔离性

方式一:利用隔离级别保证

在应用不同隔离级别时也会有不同的锁机制

  • RC:具有记录锁机制;
  • RR:具有间隙锁机制+下一键锁机制(next lock) 表锁

方式二:利用锁进制隔离(保护并发访问资源)

类型 锁机制 简述说明
内存资源锁 latch(闩锁) 主要是保护内存资源;rwlock(读写锁)、mutex(只读锁)
避免不同程序争用相同地址区域内存资源)
元数据锁 MDL 主要是保护元数据资源,限制DDL操作;metadata lock
表级别锁 table_lock 主要是保护整个数据表资源;
命令方式锁表 lock table t1 read;
工具方式锁表 利用mysqldump、XBK(PBK)进行备份非InnoDB数据时,将触发FTWRL全局锁表;
行锁升级为表锁 比如做数据更新操作时,没有设置索引条件信息,就会出现全表扫描,出现表锁;
行级别锁 row_lock InnoDB默认锁粒度,加锁方式都是在索引上加锁的;
record lock 记录锁,在聚簇索引锁定,在RC级别只有record lock
gap lock 间隙锁,在辅助索引间隙加锁,在RR级别存在,防止幻读;
next look 下一键锁,即GAP+Record,在RR级别存在,防止幻读;

从功能应用方面进行锁分类:了解

  • IS:表示意向读锁或查询锁,可以在表上进行加锁做提示(select * from t1 lock in shared mode);
  • S:表示读锁或查询锁,现在基本上没有自动设置了,除非手工进行设置锁定(lock table t1 read);
  • IX:表示意向写锁或排他锁,可以在表上进行加锁做提示(select * from t1 for update)
  • X:表示写锁或排他锁,限制其他人的指定操作行为;

官方参考资料链接:https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/949506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年比较好的拼接包边自动化篷布设备优质厂家推荐榜单

2025年比较好的拼接包边自动化篷布设备优质厂家推荐榜单 随着工业自动化的快速发展,篷布生产行业对高效、精准的拼接包边自动化设备需求日益增长。2025年,市场上涌现出一批技术领先、服务优质的篷布设备制造商,为行…

2025年靠谱的FD7B25ADM比例阀实力厂家TOP推荐榜

2025年靠谱的FD7B25ADM比例阀实力厂家TOP推荐榜 在工业自动化与流体控制领域,FD7B25ADM比例阀作为关键执行元件,其性能与可靠性直接影响设备运行效率与稳定性。随着智能制造与精密加工需求的增长,市场对高精度、长…

2025年10月进度管理工具推荐:实战口碑榜横向对比

进入2025年第四季度,企业预算锁定与年度复盘同步启动,进度管理工具成为研发、交付、市场等多部门协同的“硬需求”。用户常见场景有三:一是信创替代窗口期,需把Jira、Confluence数据平滑迁回国产平台;二是多项目并…

2025年靠谱的电子地磅厂家最新TOP排行榜

2025年靠谱的电子地磅厂家最新TOP排行榜 在工业称重领域,电子地磅是至关重要的计量设备,广泛应用于物流、矿山、化工、冶金等行业。选择一家技术可靠、售后完善的电子地磅厂家,不仅能提高生产效率,还能降低长期维…

2025 年超高分子量聚乙烯板厂家最新推荐榜,技术实力与市场口碑深度解析抗静电,耐高温,白色,阻燃,高分子超高分子量聚乙烯板公司推荐

引言 超高分子量聚乙烯板作为运输、化工、煤矿等领域的关键材料,其质量直接影响工业生产效率与安全。据塑料加工工业协会 2024 年度测评数据显示,国内该类产品合格率仅 78%,35% 的采购纠纷源于性能虚标与定制能力不…

基于MATLAB的fmincon函数实现非线性优化并提取迭代参数变化

一、原理与流程 1. 算法框架 初始化 \(x_0\) while 未收敛: 计算搜索方向 \(d_k\) 线搜索确定步长 \(α_k\) ​ \(x_{k+1}=x_k+α_kd_k\) // 记录迭代参数 ​ 检查收敛条件 end 二、代码实现 1. 目标函数定义 %…

2025年口碑好的数码印花激光切割机厂家最新推荐排行榜

2025年口碑好的数码印花激光切割机厂家最新推荐排行榜在当今数字化制造时代,数码印花激光切割机已成为纺织、广告、工艺品等行业不可或缺的高效生产工具。随着技术的不断进步和市场需求的日益增长,选择一家可靠的激光…

2025年评价高的双功能阻尼隐藏轨最新TOP厂家排名

2025年评价高的双功能阻尼隐藏轨最新TOP厂家排名 行业概述 双功能阻尼隐藏轨作为现代家具五金的核心部件,凭借其静音缓冲、空间优化和耐用性等优势,已成为高端家具市场的标配。2025年行业数据显示,具备“阻尼+反…

2025年知名的微波真空干燥设备实力厂家TOP推荐榜

2025年知名的微波真空干燥设备实力厂家TOP推荐榜 在工业干燥领域,微波真空干燥设备凭借其高效节能、低温干燥、环保等优势,成为制药、食品、化工等行业的关键设备。随着技术迭代,具备核心研发能力、稳定生产实力及…

2025 年无缝钢管源头厂家最新推荐榜:技术创新、行业适配与服务保障全景对比测评报告高压锅炉无缝钢管/方形无缝钢管/无缝钢管圆改方/镀锌无缝钢管厂家推荐

引言 为助力客户精准筛选优质无缝钢管源头厂家,本次榜单结合钢结构协会钢管分会 2025 年度行业测评数据编制。测评采用 “三维九项” 评估体系,从技术实力(工艺先进性、研发能力、检测设备)、产品适配性(品类覆盖…

2025年热门的南京发电机售后厂家选购指南与推荐

2025年热门的南京发电机售后厂家选购指南与推荐 开篇介绍 随着工业化和城市化的快速发展,发电机作为重要的备用电源设备,在建筑工地、数据中心、医院、工厂等领域发挥着不可替代的作用。南京作为华东地区的重要经济…

2025年知名的游乐设备PC管最新TOP厂家排名

2025年知名的游乐设备PC管最新TOP厂家排名 在游乐设备制造领域,PC管(聚碳酸酯管)因其高强度、耐高温、抗冲击和优异的透光性成为核心材料之一。无论是主题公园的灯光装饰、游乐设施的防护结构,还是水上游乐设备的…

[题解]AtCoder Beginner Contest 429(ABC429) C~F

这次的题解超迟到了。 C - Odd One Subsequence 用一个桶记录 \(i\) 出现的次数 \(c_i\)。 则构造三元组相当于从一个桶中任选 \(2\) 个,再从另一个桶中选 \(1\) 个。 所以答案即为: \[\sum_i \binom{c_i}{2}\times …

2025年靠谱的电动丝杆升降机优质厂家推荐榜单

2025年靠谱的电动丝杆升降机优质厂家推荐榜单在工业自动化领域,电动丝杆升降机作为重要的线性运动执行元件,广泛应用于物料搬运、生产线调整、医疗设备、舞台机械等多个领域。随着中国制造业的持续升级,对高精度、高…

2025年热门的进口品牌针式铰链用户口碑最好的厂家榜

2025年热门的进口品牌针式铰链用户口碑最好的厂家榜 随着家居五金行业的快速发展,针式铰链因其高承重、耐用性强、安装便捷等优势,逐渐成为高端定制家居的首选配件。2025年,进口品牌针式铰链市场竞争激烈,消费者对…

ChatGPT Atlas浏览器发布:为何这款AI浏览器可能无人问津

本文分析了OpenAI新推出的ChatGPT Atlas浏览器面临的多重挑战,包括功能重叠、数据隐私担忧、平台局限性以及实际应用效果等问题,探讨了这款AI浏览器可能难以获得用户青睐的原因。OpenAI刚刚登台发布了ChatGPT Atlas,…

2025年10月工装装修公司推荐:口碑榜对比指南

把办公室从“能用”变成“好用”,把实验室从“合规”变成“高效”,把酒店从“开业”变成“常满”,这是多数企业业主在2025年寻找工装装修公司时的真实诉求。政策层面,《“十四五”建筑业发展规划》继续强调绿色建造…

2025年热门的伸铝箔四方袋厂家最新权威推荐排行榜

2025年热门的伸铝箔四方袋厂家最新权威推荐排行榜 随着工业包装需求的不断升级,伸铝箔四方袋因其优异的防潮、防静电、耐高温等特性,成为电子、食品、医药等行业的重要包装选择。为帮助用户快速锁定优质供应商,本文…

2025年靠谱的排烟防火阀厂家实力及用户口碑排行榜

2025年靠谱的排烟防火阀厂家实力及用户口碑排行榜 在建筑消防系统中,排烟防火阀是保障人员安全疏散和防止火势蔓延的关键设备。选择一家技术实力强、产品质量可靠、售后服务完善的排烟防火阀厂家至关重要。本文基于2…

2025年上海实木全屋定制机构权威推荐榜单:全屋定制装修/全屋定制加盟/全屋定制源头厂家精选

上海实木全屋定制市场正以每年超18%的速度增长,2025年市场规模预计突破1.5万亿元。 在当前消费升级与家居产业绿色转型的背景下,上海实木全屋定制行业迎来新一轮发展契机。据行业数据显示,中国定制家居市场规模2025…