MySQL数据库精研之旅第十六期:深度拆解事务核心(上)

专栏:MySQL数据库成长记

个人主页:手握风云

目录

一、什么是事务

二、事务的ACID特性

三、为什么要使用事务

四、如何使用事务

[4.1. 查看支持事务的存储引擎](#4.1. 查看支持事务的存储引擎)

[4.2. 语法](#4.2. 语法)

[4.3. 手动/自动提交事务](#4.3. 手动/自动提交事务)

[4.4. 开启一个事务,执行修改后回滚](#4.4. 开启一个事务,执行修改后回滚)

[4.5. 开启一个事务,执行修改后提交](#4.5. 开启一个事务,执行修改后提交)

[4.6. 保存点](#4.6. 保存点)


一、什么是事务

事务把一组SQL语句打包成为一个整体,在这组SQL的执行过程中,要么全部成功,要么全部失败。这组SQL语句可以是一条也可以是多条。我们拿转账举例:

sql 复制代码
create table bank_account (
  id bigint primary key auto_increment,
  `name` varchar(25) not null, -- 姓名
  balance decimal(10,2) not null -- 余额
);

insert into bank_account (`name`, balance) values ('张三',1000);
insert into bank_account (`name`, balance) values ('李四',1000);

-- 张三的余额减少100
update bank_account set balance = balance - 100 where `name` = '张三';
-- 李四的余额增加100
update bank_account set balance = balance + 100 where `name` = '李四';

张三给李四转100元,需要保证:不能出现张三的余额减少而李四的余额没有增加的情况,要么全部成功,要么全部失败;保证转账前后两人的总余额不变,转账前后数额要一致;转账后的余额结果应当保存到存储介质中,以便以后读取,对数据的修改应当落盘(保存到磁盘),持久化;在转账的处理过程中张三和李四的余额不能因其他的转账事件而受到干扰,把其他操作隔离开。

以上这四点在事务的整个执行过程中必须要得到保证,这也就是事务的ACID特性。

对于隔离性,因为不同的客户端可以同时对数据库进行操作,执行的SQL语句也有可能相同。我们对一个账户余额减少100的操作,先从数据库中把1000读出来,把余额在原来的基础上减100,最后把修改过后的值写回数据库。如果有两个客户端并行执行此操作,减少了两次,余额应该是800,由于客户端1和客户端2同时(并行)进行了对数据的修改,导致得到了一个错误的结果。

二、事务的ACID特性

事务的ACID特性指的是 Atomicity(原子性),Consistency(一致性),Isolation((隔离性)和 Durability(持久性)。

  1. Atomicity (原子性):⼀个事务中的所有操作,要么全部成功,要么全部失败,不会出现只执 ⾏了⼀半的情况,如果事务在执行过程中发⽣错误,会回滚( Rollback )到事务开始前的状 态,就像这个事务从来没有执⾏过一样。
  2. Consistency (一致性):在事务开始之前和事务结束以后,数据库的完整性不会被破坏。这表 示写⼊的数据必须完全符合所有的预设规则,包括数据的精度、关联性以及关于事务执行过程中服务器崩溃后如何恢复。
  3. Isolation (隔离性):数据库允许多个并发事务同时对数据进行读写和修改,隔离性可以防⽌多个事务并发执行时由于交叉执行而导致数据的不⼀致。事务可以指定不同的隔离级别,以权衡在不同的应用场景下数据库性能和安全。
  4. Durability (持久性):事务处理结束后,对数据的修改将永久的写入存储介质,即便系统故障 也不会丢失。如果事务一旦提交,就需要永久的保存到存储介质当中,不论数据库软件或操作系统是否崩溃,都不会对数据的安闐啡悄全造成影响(数据丢失)。

三、为什么要使用事务

事务具备的ACID特性,是我们使用事务的原因,在我们日常的业务场景中有大量的需求要用事务 来保证。支持事务的数据库能够简化我们的编程模型,不需要我们去考虑各种各样的潜在错误和并发问题,在使用事务过程中,要么提交,要么回滚,不用去考虑⽹络异常,服务器宕机等其他因素,因此我们经常接触的事务本质上是数据库对 ACID 模型的⼀个实现,是为应⽤层服务的。

主流的数据库都支持事务,如果数据库无法支持ACID特性,那么就需要程序员耗费大量精力去维护。

四、如何使用事务

4.1. 查看支持事务的存储引擎

sql 复制代码
show engines;

要使用事务那么数据库就要支持事务,从上图可以看出,MySQL支持事务的存储引擎是InnoDB。

4.2. 语法

sql 复制代码
-- 开启事务
start transaction;
-- 或
begin;

-- 事务中要执行的SQL,一条或一组

-- 提交当前事务,,并对更改持久化保存
commit;

-- 回滚当前事务,取消其更改
rollback;

-- 无论执行了commit或者rollback,事务都会结束

4.3. 手动/自动提交事务

我们之前写的单条update、insert、delete语句也都在事务中,这是因为在默认情况下,,MySQL是自动提交事务的。我们执行的每个修改操作,都会自动开启一个事务并在语句执行完成之后自动提交,发生异常时自动回滚。

sql 复制代码
-- 查看当前语句是否自动提交
show variables like 'autocommit';

如果是OFF,就需要手动commit或者rollback。

我们也可以通过下列语句设置事务自动或者手动。

sql 复制代码
-- 设置事务自动提交
set autocommit=1;
set autocommit=ON;

-- 设置事务手动提交
set autocommit=0;
set autocommit=OFF;

手动提交模式下,不用显示开启事务,执行修改操作后,提交或回滚事务时直接使用 commit或 rollback。

4.4. 开启一个事务,执行修改后回滚

sql 复制代码
start transaction;

只要手动开启一个事务,必须以commit或rollback结束,和是否自动提交没有关系。

sql 复制代码
-- 执行转账逻辑
update bank_account set balance = balance - 100 where `name` = '张三';
select * from bank_account;
sql 复制代码
update bank_account set balance = balance + 100 where `name` = '李四';
select * from bank_account;
sql 复制代码
-- 回滚之后,数据回退到最初状态
ROLLBACK;
select * from bank_account;

4.5. 开启一个事务,执行修改后提交

sql 复制代码
-- 开启一个新事务
begin;
update bank_account set balance = balance - 100 where `name` = '张三';
update bank_account set balance = balance + 100 where `name` = '李四';

select * from bank_account;
-- 提交之后,才进行永久保存
commit;

事务提交之后,无论哪个客户端查询之后,都是落盘的结果。已提交的事务不能回滚。

4.6. 保存点

如同游戏当中存档点,在事务执⾏的过程中设置保存点,回滚时指定保存点可以把数据恢复到保存点的状态。我们不光可以回滚到保存点,甚至可以回到事务的开启。

sql 复制代码
start transaction;
update bank_account set balance = balance - 100 where `name` = '张三';
update bank_account set balance = balance + 100 where `name` = '李四';
select * from bank_account;

-- 设置第一个保存点
savepoint sp1;
update bank_account set balance = balance - 100 where `name` = '张三';
update bank_account set balance = balance + 100 where `name` = '李四';
select * from bank_account;

-- 设置第二个保存点
savepoint sp2;

-- 新增一条数据
insert into bank_account values(3, '王五',5000);
sql 复制代码
rollback to sp2;
select * from bank_account;

在实际工作中,回滚使用的频率比保存点要高很多。

相关推荐
小陈工5 小时前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
0xDevNull9 小时前
MySQL数据冷热分离详解
后端·mysql
科技小花9 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸9 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain9 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希10 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神10 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员10 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java10 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿10 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb