事务
什么是事务
要么都成功,要么都失败
一组事务(银行转账)
- SQL执行 A给B转帐 A 1000 ——>200 B 200
- SQL 执行 B收到A的钱 A 800 B 400
将一组SQl放在一个批次中去执行
事务的原则
ACID原则
原子性(Atomicity)
要么都成功,要么都失败
针对一个事务:
包含两个操作:
A: 800-200=600
B:200+200=400
原子性表示,这两个步骤一起成功,或者一起失败,不能只发生其中一个动作
一致性(Consistency)
事务前后数据的完整性必须保持一致。
操作前:
总金额=A(800)+B(200)=1000
操作后:
总金额=A(600)+B(400)=1000
一致性表示事务完成后,符合逻辑运算
隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
两件事务:
事务一 A向B转账200
事务二 C向B转账100
两个事务同时进行,其中一个事务读取到另外一个事务还没有提交的数据,隔离性能很好解决这个问题。
持久性(Durability)
事务一旦提交则不可逆,被持久化到数据库中!
操作前:
A:800,B:200
操作后:
A:600,B:400
如果在操作前(事务还没有提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为
A:800,B:200
如果在操作后(事务已经提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为
A:600,B:400
表示事务结束后的数据不随着外界原因导致数据丢失
事物的隔离级别
脏读
指一个事务读取了另外一个事务未提交的数据。
不可重复读
在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对).
页面统计查询值:
生成报表的时候,B有人转账进来300(B事务已经提交):
虚读(幻读)
是指在一个事务内读取到了别的事务插入的数据,导致前后读取数量总量不一致。
模拟场景
先贴代码(效果图在下面,也可以自行测试)
-- 建立数据库
CREATE DATABASE shop
-- 使用数据库
USE shop
-- 建立数据表
CREATE TABLE `account` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR ( 30 ) NOT NULL,
`money` DECIMAL(9,2) not null,
PRIMARY KEY (`id`)
);
-- 插入数据
INSERT INTO `account`(`name`,`money`)
VALUES ('A',2000.00),('B',1000.00);
-- 模拟事务:银行转账
-- 注意:mysql是默认开启事务自动提交的
SET autocommit = 0;-- 关闭自动提交
START TRANSACTION -- 开启事务
UPDATE account SET money=money-500 WHERE name='A';-- A减500
update account ste money=money+500 where name='B';-- B加500
-- 提交事务
commit;
-- 回滚事务
Rollback;
-- 恢复默认值
set COMMIT=1;
建表成功,插入数据后:
事务提交过后:
事务回滚后:
如果代码过长,可设置保留点
SAVEPOINT 保存点名 -- 设置一个事务的保存点
rollback to SAVEPOINT 保存点名 -- 回滚到保存点
RELEASE SAVEPOINT 保存点名 -- 撤销保存点
参考博客 链接