Skip to content

Mysql 事务

事务简介

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或者撤销操作请求.

这些操作要么同时成功,要么同时失败

举例

张三给李四转账 1000 块,张三银行账户的钱减少 1000,而李四银行账户的钱要增加 1000.这一组操作就必须在一个事务的范围内,要么都成功,要么都失败

正常情况:转账这个操作要分成以下三步完成.三步完成后,张三减少 1000,而李四增加 1000,转账成功

  • 查询张三账户余额

  • 张三账户减少 1000

  • 李四账户增加 1000

异常情况

转账这个操作,也是分为三步来完成.如果在第三步报错了,这样就导致张三减少 1000 块,而李四账户并没有增加 1000 块,这样就不对了.这种情况,就需要事务来保证要么都成功,要么都失败

警告

默认 Mysql 的事务是自动提交的,也就是说当执行完一条 DML 语句后,Mysql 会立即隐式的提交事务

事务操作

数据准备:

sql
drop table if exists account;
create table account(
id int primary key AUTO_INCREMENT comment 'ID',
name varchar(10) comment '姓名',
money double(10,2) comment '余额'
) comment '账户表';
insert into account(name, money) VALUES ('张三',2000), ('李四',2000);

为控制事务

  • 测试正常情况
sql
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';
  • 测试异常情况
sql
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
出错了....
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';

我们把数据都恢复到 2000, 然后再次一次性执行上述的 SQL 语句(出错了.... 这句话不符合 SQL 语 法,执行就会报错),检查最终的数据情况, 发现数据在操作前后不一致了。

控制事务(一)

  • 查看/设置事务提交方式 0 :手动提交 1:自动提交
sql
SELECT @@autocommit ;
SET @@autocommit = 0 ;
  • 提交事务
sql
COMMIT;
  • 回滚事务
sql
ROLLBACK;

注意

注意:上述的这种方式,我们是修改了事务的自动提交行为, 把默认的自动提交修改为了手动提 交, 此时我们执行的 DML 语句都不会提交, 需要手动的执行 commit 进行提交。

控制事务(二)

  • 开启事务
sql
START TRANSACTION 或者BEGIN;
  • 提交事务
sql
COMMIT;
  • 回滚事务
sql
ROLLBACK;
  • 转账案例
sql
-- 开启事务
start transaction
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';
-- 如果正常执行完毕, 则提交事务
commit;
-- 如果执行过程中报错, 则回滚事务
-- rollback;

事务的四大特性

  • 原子性(Atomicity):

事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不完成,不可能只执行其中的一部分操作

  • 一致性(Consistency):

事务执行的结果必须使数据库从一个一致性状态到另一个一致性状态

  • 隔离性(Isolation):

事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰

  • 持久性(Durability):

已提交的事务对数据库中数据的改变是永久性的,即使数据库发生故障也不应该对其有任何影响

简称 ACID

并发事务问题

  • 脏读: 一个事务读取了另一个事务未提交的数据

比如 B 读取到了 A 未提交的数据。

  • 不可重复读: 一个事务读取了另一个事务已经提交的数据,导致两次读取结果不一致

事务 A 两次读取同一条记录,但是读取到的数据却是不一样的。

  • 幻读: 一个事务读取了另一个事务已经提交的数据,导致两次读取结果不一致

事务隔离级别

为了解决并发事务所引发的问题,在数据库中引入事务隔离级别主要有以下几种:

隔离级别脏读不可重复读幻读
Read uncommitted
Read committed×
Repeatable Read(默认)××
Serializable×××

查看事务隔离级别

SQL
SELECT @@TRANSACTION_ISOLATION;

设置事务隔离级别

SQL
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED |
READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

注意

注意:事务隔离级别越高,数据越安全,但是性能越低