【学习笔记】事务
什么是事务?
要么都成功,要么都失败
以转账为例:
有两条sql,第一条是A给B转账,第二条是B接收A的转账
这两条语句,必须都成功,或都失败,不能一条成功,一条失败
事务原则:ACID原则
原子性(Atomicity):事务中的操作要么都发生,要么都不发生。
如A给B转账,B收到A的转账,这两个动作必须一起成功,或者一起失败
一致性(Consistency):事务前后的数据完整性要保证一致
转账前:A + B = 1000
转账后: A + B = 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
隔离所导致的问题
脏读:
指一个事务读取了另外一个事务未提交的数据。
如图:事务二中读到了事务一中A还为转账时的状态
不可重复读:
在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对)
页面统计查询值 生成报表的时候,B有人转账进来300(B事务已经提交)
虚读(幻读)
是指在一个事务内读取到了别的事务插入的数据,导致前后读取数量总量不一致。 (一般是行影响,如下图所示:多了一行)
参考博客:
执行事务
mysql是自动开启事务提交
-- mysql 默认开启事务自动提交
SET autocommit = 0 -- 关闭
SET autocommit = 1 -- 开启(默认)
-- 关闭后需要手动处理事务
流程:
-- 关闭事务自动提交
SET autocommit = 0 -- 关闭
-- 事务开启
START TRANSACTION -- 标记一个事务的开始,从这个之后的sql都在同一个事务内
INSERT xxx
UPDATE xxx
-- 提交事务(成功)
COMMIT
-- 回滚 (失败)
ROLLBACK
-- 事务结束,开启自动提交
SET autocommit = 1 -- 开启(默认)
关于保存点:
-- 关于保存点(就像存档一样)
SAVEPOINT 保存点名称 -- 设置一个事务的保存点
ROLLBACK TO SAVEPOINT 保存点名称 -- 回滚到保存点
RELEASE SAVEPOINT 保存点名称 -- 删除保存点
模拟事务(转账)
-- 模拟转账
-- 创建表
CREATE TABLE `account`(
`id` INT(3) NOT NULL auto_increment,
`name` VARCHAR(20) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 插入数据
INSERT INTO `account`(`name`,`money`)
VALUES('A',800.00),('B',200.00)
-- 关闭自动提交
SET autocommit = 0
-- 开启事务
START TRANSACTION
-- A给B转账200
UPDATE `account` SET `money` = `money`-200 WHERE `name` = 'A'
-- B接收A的转账
UPDATE `account` SET `money` = `money`+200 WHERE `name` = 'B'
-- 提交
COMMIT
-- 回滚
ROLLBACK
SET autocommit = 1 -- 恢复默认值
必须要一步一步去执行,否则会报错