事务
事务
概念
一个事务是由一条或者多条sql语句构成,这一条或者多条sql语句要么全部执行成功,要么全部执行失败。
默认情况下,每条单独的sql语句就是一个单独的事务。
事务属于 Transaction Control Language 事务控制语言(TCL)
举例:
银行转账,侠奢转20块到猪猪的账户,这其实需要两条SQL语句:
- 给侠奢三的账户减去20元;
- 给猪猪的账户加上20元。
如果在第一条SQL语句执行成功后,在执行第二条SQL语句之前,程序被中断了(可能是抛出了某个异常,也可能是其他什么原因),那么李四的账户没有加上20元,而张三却减去了20元。这是不允许的。
所以说:事务中的多个操作,要么完全成功,要么完全失败,不可能存在成功一半的情况。也就是说给张三的账户减去20元如果成功了,那么给李四的账户加上20元的操作也必须是成功的;否则给张三减去20元,以及给李四加上20元都是失败的。
四大特性:ACID
- 原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
- 一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
- 隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰,即一个事务的执行不能杯其他事务干扰。(与隔离级别有关)
- 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。
MySql中的事务
在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。
l 开启事务:start transaction;
l 结束事务:commit或rollback。
在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后要结束事务,commit表示提交,即事务中的多条SQL语句所做出的影响会持久化到数据库中。或者rollback,表示回滚,即回滚到事务的起点,之前做的所有操作都被撤消。
实例一:
# 事务
/*
概念:由一条或多条sql语句组成,要么都成功,要么都失败
mysql 中 innodb 存储引擎支持事务
分类:
1.隐式事务:没有明显的开启和结束标记
比如DML语句中的insert、update、delete语句本身就是一条事务
例如,insert中只要有一个数据插入失败,则整条语句不能执行:
insert into students values(1, '侠奢', '男’, 'xxx@163.com')
2.显式事务:具有明显的开启和结束标记
一般由多条sql语句组成,必须具有明显的开启和结束标记
步骤:
0. 取消隐式事务自动开启的功能
set autocommit=0;
1. 开启事务
start transaction;
2. 编写事务需要的sql语句(1条或多条)
(select insert update delete)
savepoint 节点名;设置保存点
3. 结束事务:
commit;提交事务
rollback;回滚事务
*/
-- 查看事务是否自动开启
SHOW VARIABLES LIKE '%auto%'
# 事务使用步骤
-- 0. 取消事务自动开启
SET autocommit = 0;
-- 1. 开启事务
START TRANSACTION;
-- 2. 编写事务的sql语句,侠奢转给猪猪500块钱
# 侠奢的钱-500
UPDATE person SET money=money-500 WHERE id=1;
# 猪猪的钱+500
UPDATE person SET money=money+500 WHERE id=2;
-- 3. 提交事务
# 提交
# commit;
# 回滚
ROLLBACK;
事务隔离级别
对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:
-- 脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
-- 不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段。之后, T1再次读取同一个字段, 值就不同了.
-- 幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行。之后, 如果 T1 再次读取同一个表, 就会多出几行
一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好, 但并发性越弱。四个隔离级别如下图所示:

-- 事务的隔离级别:
脏读 不可重复读 幻读
read uncommitted: √ √ √
read committed: × √ √
repeatable read: × × √
serializable: × × ×
mysql中默认 第三个隔离级别 repeatable read
oracle中默认第二个隔离级别 read committed
查看隔离级别
select @@tx_isolation;
设置隔离级别
set session|global transaction isolation level 隔离级别;
实例二:
-- 1. 演示事务对于delete和truncate的处理的区别
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE account;
DELETE FROM account;
ROLLBACK;
-- 2. 演示savepoint 的使用,即id为25的数据删掉,id为28的没有删掉
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a; #设置保存点
DELETE FROM account WHERE id=28;
ROLLBACK TO a; #回滚到保存点
SELECT * FROM account;

浙公网安备 33010602011771号