熠Eli头像
关注

MySQL事务详解:搞懂ACID、事务操作与四大隔离级别

MySQL事务详解:搞懂ACID、事务操作与四大隔离级别

日常开发中转账、订单扣库存、业务多步更新,几乎都离不开数据库事务。如果不使用事务,一旦中间步骤报错,就会出现数据错乱。今天结合转账案例,把MySQL事务完整梳理一遍。

一、什么是事务

事务就是把一组SQL打包成一个不可分割的整体,这一组SQL要么全部执行成功,要么全部执行失败回滚,不会出现执行一半的情况。

最经典的场景:账户转账。
张三给李四转账100元,需要执行两条SQL:

  1. 张三余额 -100
  2. 李四余额 +100
UPDATE bank_account set balance = balance - 100 where name = '张三';
UPDATE bank_account set balance = balance + 100 where name = '李四';

如果第一条执行完,数据库宕机、程序崩溃,第二条没执行。就会出现:张三钱扣了,李四钱没加上,资金凭空消失。
事务就是用来避免这种情况的,两条SQL作为事务:要么都成功,要么全部撤销,回到转账之前的状态。

建表测试SQL:

CREATE TABLE `bank_account` (
`id` bigint PRIMARY KEY AUTO_INCREMENT, 
`name` varchar(255) NOT NULL,
`balance` decimal(10, 2) NOT NULL
);
INSERT INTO bank_account(`name`, balance) VALUES('张三', 1000);
INSERT INTO bank_account(`name`, balance) VALUES('李四', 1000);

二、事务ACID四大核心特性

事务有四个标志性特性,简称 ACID,也是我们使用事务的根本原因:

  1. Atomicity 原子性
    事务是不可拆分原子单元,内部操作要么全成,要么全失败回滚。如果中途出错,全部操作撤销,仿佛什么都没发生。

  2. Consistency 一致性
    事务执行前后,数据库数据完整性不能被破坏。

转账例子:转账前后两人总金额必须始终等于2000,不会出现总额变多或者变少。数据必须符合业务预设规则。

  1. Isolation 隔离性
    数据库会同时跑很多个并发事务,隔离性保证多个事务之间互相干扰可控。多个事务同时读写同一份数据,通过隔离级别控制互相影响程度,隔离越高,并发性能越差。

  2. Durability 持久性
    事务commit提交成功之后,数据永久保存到磁盘。就算服务器宕机重启,修改的数据也不会丢失。

💡简单理解:原子性保证“要么全成要么全废”;一致性是最终业务数据正确;隔离性解决多个人同时操作数据的冲突;持久性保证提交后不会丢。

三、MySQL如何使用事务

⚠️注意:MySQL中只有InnoDB存储引擎支持事务,MyISAM不支持事务。
查看引擎:show engines;

1.基础语法

--开启事务,二选一
START TRANSACTION;
BEGIN;

--提交事务:所有修改持久化到磁盘,事务结束
COMMIT;

--回滚事务:撤销本次事务所有修改,事务结束
ROLLBACK;
✅场景1:开启事务,执行修改后回滚

执行更新,然后执行ROLLBACK,所有修改全部作废。

START TRANSACTION;
UPDATE bank_account set balance = balance - 100 where name = '张三';
UPDATE bank_account set balance = balance + 100 where name = '李四';
ROLLBACK; --撤销,张三、李四余额回到原始状态
✅场景2:开启事务,执行修改后提交
BEGIN;
UPDATE bank_account set balance = balance - 100 where name = '张三';
UPDATE bank_account set balance = balance + 100 where name = '李四';
COMMIT; --提交,修改永久生效

2.保存点 SAVEPOINT

一个事务内部,可以设置多个保存点,只回滚到某个保存点,而不是回滚整个事务。适合大事务,部分出错只撤销一部分操作。

START TRANSACTION;
UPDATE bank_account set balance = balance - 100 where name = '张三';
SAVEPOINT sp1; --设置保存点sp1
UPDATE bank_account set balance = balance -100 where name = '张三';

ROLLBACK TO sp1; --回滚到sp1,只撤销后面那一次扣钱,第一次扣钱还保留
COMMIT;

3.自动提交 autocommit

MySQL默认自动提交(autocommit=ON)。每执行一条DML(update/insert/delete)语句,就自动提交事务。

查看自动提交状态:

show variables like 'autocommit';
  • autocommit=ON:自动提交,单条语句执行完直接落盘
  • autocommit=OFF:关闭自动提交,修改需要手动执行commit才生效

重点提醒:只要用BEGIN / START TRANSACTION显式开启事务,就必须手动commit/rollback,不受autocommit配置影响。已经commit的事务,无法回滚

四、事务隔离级别:解决并发带来的问题

多个事务同时读写同一份数据,会产生脏读、不可重复读、幻读。MySQL InnoDB提供4种隔离级别,安全程度越高,并发性能越低

隔离级别脏读不可重复读幻读说明
READ UNCOMMITTED(读未提交)会发生会发生会发生最低隔离,几乎不使用
READ COMMITTED(读已提交)解决会发生会发生很多数据库默认级别
REPEATABLE READ(可重复读)InnoDB默认解决解决大部分解决(Next‑Key锁)MySQL默认
SERIALIZABLE(串行化)解决解决解决全部串行执行,性能最差

1. READ UNCOMMITTED 读未提交 → 脏读

脏读:一个事务读到另一个事务还没有提交的数据。

事务A修改数据还没commit,事务B直接读到这个未提交数据;如果A后面rollback回滚了,B读到的数据就是虚假无效的数据。
业务中几乎不用这个隔离级别。

2. READ COMMITTED 读已提交 → 不可重复读

不可重复读:同一个事务内,同一条SQL查询,前后两次返回结果不一样。

事务A开启,第一次查询王五余额2000;
事务B修改王五余额并commit;
事务A再次查询,王五余额变成1000。
同一个事务,同样查询,结果前后不一致,这就是不可重复读。

重点:不可重复读针对同一条数据内容被修改

###3. REPEATABLE READ 可重复读(MySQL默认)
同一个事务中,多次查询,读取到的都是事务启动那一刻的数据快照,别的事务提交修改,本事务看不到,解决不可重复读。

但会出现幻读

幻读:同一个事务,两次范围查询,第二次多出来别的事务新插入/删除的数据。

InnoDB通过**Next‑Key锁(临键锁)**在REPEATABLE READ级别下解决了大部分幻读场景。

###4. SERIALIZABLE 串行化
最高隔离级别,所有事务强制排队串行执行,完全杜绝脏读、不可重复读、幻读。但是并发能力差,吞吐量很低,一般业务很少用。

设置&查看隔离级别

--查看全局隔离级别
SELECT @@GLOBAL.transaction_isolation;
--查看当前会话隔离级别
SELECT @@SESSION.transaction_isolation;

--设置会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
--设置全局隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

InnoDB的隔离级别底层依靠 锁机制 + MVCC多版本并发控制实现。

五、开发实践小结

  1. 只要业务有多步DML需要保证全部成功/失败,一定要使用事务,比如转账、下单扣库存、多表联动更新。
  2. 使用事务必须用InnoDB引擎。
  3. MySQL默认隔离级别是REPEATABLE READ,绝大多数业务场景够用,不要随便改成读未提交。
  4. 事务不要写太大,尽量缩短事务执行时间,大事务容易锁等待、死锁、数据库性能下降。
  5. 记住三个现象区分:
    • 脏读:读到别人没提交的数据
    • 不可重复读:别人修改提交,我同事务读同一条数据前后变了
    • 幻读:别人插入/删除提交,我范围查询多/少了行

本文适合Java后端、MySQL入门同学理解事务底层逻辑,后续可以继续深入学习MVCC、临键锁、行锁表锁。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2501_93786094/article/details/163860724

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--