SQL中的事务
目录
1、概述
---1.1事务是什么?
---1.2例子:银行转账业务
---1.3四个特征ACID
---1.4和事务有关的两条SQL语句(TCL)
---1.5事务开启和结束的标志
2、事务的提交和回滚的演示
---2.1事务的提交
---2.2事务的回滚
---2.3手动设置事务开关
3、事务的隔离级别
---3.1read uncommitted 读未提交(级别最低)
---3.2read committed 读已提交
---3.3repeatable read 可重复读
---3.4serializable 串行化(序列化)
---3.5查看隔离级别
---3.6设置隔离级别
---3.7隔离级别不一致性问题的关系
概述
事务是什么?
1、一个最小的不可再分的工作单元;
2、通常一个事务对应一个完整的业务;(如:银行转账业务)
3、而一个完整的业务需要批量的DML(insert、update、delete)语句共同完成;
4、事务只和DML语句有关系,或者说只有DML语句才有事务(保证数据的安全性);
5、以上所描述的批量DML语句共有多少DML语句,这个和业逻辑有关系,业务逻辑不同DML语句个数不同 。
6、一些关键词:
1、开启事务:start transaction
2、结束事务:end transaction
3、提交事务:commit transaction
4、回滚事务:rollback transaction
例子:银行转账业务
1、银行转账业务:是一个完整的业务,最小的单元,不可再分。
2、act-001(50000.0)转10000.0给act-002(10000.0),操作如下:
update t_act set balance = 40000.0
where actno = ‘act-001’;
update t_act set balance = 20000.0
where actno = ‘act-002’;
3、分析
a)以上两条DML语句必须同时成功或者同时失败,因为它为最小业务单元,不可拆分;
b)当第一条DML语句执行成功之后,并不能将底层数据库中的第一个账户的数据修改,只是将操作记录了一下,这个记录是在内存中完成的;
c)当第二条DML语句执行成功之后,和底层数据库文件中的数据完成同步。
d)若第二条DML语句执行失败,将清空所有的历史操作记录。
结论:要完成以上功能,必须借助事务(transaction)。
四个特征ACID
1、原子性(Atomicity)
事务是最小单元,不可再分;
2、一致性(Consistency)
事务要求所有的DML语句操作的时候,必须保证同时成功或同时失败;
3、隔离性(Isolation)
一个事务不会影响其它事务的运行;
4、持久性(Durability)
在事务完成之后,该事务对数据库所作的更改将持久地保存在数据库中,并不会被回滚。
和事务有关的两条SQL语句(TCL)
1、COMMIT; 提交
2、ROLLBACK; 回滚
事务开启和结束的标志
- 开启的标志
任何一条DML语句执行,标志事务的开启。 - 结束的标志
提交(commit)或者回滚(rollback)
1、提交:成功的结束,将所有的DML语句操作记录和底层硬盘文件中数据进行一次同步。
2、回滚:失败的结束,将所有DML语句操作记录全部清空。 - 重点
1、在事务进行过程中,未结束之前,DML语句是不会修改底层数据库文件中的数据。
2、只是将历史操作记录一下,在内存中完成记录。
3、只有在事务成功结束的时候才会修改底层硬盘文件中的数据。
事务的提交和回滚的演示
- 自动提交事务
在MySQL数据库管理系统中,默认情况下,事务是自动提交的。也就是说,叧要执行一条DML语句,就开启了事务,并且提交了事务。
事务的提交
- 第一步:
start transaction;
手动开启事务;
- 第二步:
DML语句….
执行批量DML语句;
INSERT INTO t_user(`name`)
VALUES('lisi');
INSERT INTO t_user(`name`)
VALUES('zhaoliu');
SELECT * FROM t_user;
当前窗口可以查看刚刚插入的数据:
其它窗口则看不见:
- 第三步:
commit;
手动提交事务(事务成功结束)。
提交后都能看见:
事务的回滚
- 第一步:
start transaction;
手动开启事务
- 第二步:
DML语句…..
批量DML语句
INSERT INTO t_user(`name`)
VALUES('jack');
INSERT INTO t_user(`name`)
VALUES('rose');
SELECT * FROM t_user;
当前窗口:
其它窗口:
- 第三步:
rollback;
手动回滚事务(事务失败结束)
其它窗口:
手动设置事务开关
1、两种关闭自动提交事务
a)set autocommit = off;
b)set session autocommit = off;
set autocommit = off;
show variables like '%commit%';
2、两种打开自动提交事务
a)set autocommit = on;
b)set session autocommit = on;
set autocommit = on;
show variables like '%commit%';
注意:以上打开或关闭事务只对当前窗口有效。
3、查询事务状态:show variables like '%commit%';
事务的隔离级别
事务四个特性ACID之一:隔离性(isolation)
- 隔离性有四个隔离级别:
1、read uncommitted 读未提交
2、read committed 读已提交
3、repeatable read 可重复读
4、serializable 串行化
read uncommitted 读未提交(级别最低)
1、事务A和和事务B,事务A未提交的数据,事务B可以读取;
2、这里读取到的数据可以叫做“脏数据”或“脏读 Dirty Read”;
3、读未提交隔离级别最低,这种级别一般叧在理论上存在,数据库默认隔离级别一般都高于该隔离级别。
read committed 读已提交
1、事务A和事务B,事务A提交的数据,事务B才可读取到;
2、该隔离级别高于“读未提交”级别;
3、换句话说:对方事务提交之后的数据,当前事务才可读取到;
4、该隔离级别可以避免脏数据;
5、该隔离级别能够导致“不可重复读取”(只能读到对方事务提交之后的数据(更新后的),不能读到原来的数据);
6、Oracle数据库管理系统默认隔离级别为:读已提交。
repeatable read 可重复读
1、事务A和事务B,事务A提交之后的数据,事务B读取不到;
2、事务B是可重复读到数据的;
3、这种隔离级别高于“读已提交”;
4、换句话说,对方提交之后的数据,还是读取不到;
5、这种隔离级别可以避免“脏读和不可重复读”,达到“重复读取”;
6、MySQL数据库管理系统默认隔离级别为:可重复读;
7、虽然可以达到“可重复读”效果,但是会导致“幻象读”(只能读到原来的数据)。
serializable 串行化(序列化)
1、事务A和事务B,事务A在操作数据库表中数据的时候,事务B只能排队等待(解决了以上所有问题,但是效率太低);
2、这种事务隔离级别一般很少使用,吞吐量太低,用户体验不好;
3、这种隔离级别可以避免“幻象读”,每一次读取都是数据库表中真实的记录;
4、事务A和事务B不再并发。
查看隔离级别
- 查看当前会话级隔离级别
select @@session.transaction_isolation;
- 查看当前全局隔离级别:
select @@global.transaction_isolation;
设置隔离级别
- 事务隔离级别的作用范围分为两种:会话级、全局级
1、会话级(session):只对当前会话有效。
2、全局级(global):对所有会话有效。 - 例子
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED 事务隔离级别
事务隔离级别:
--- READ UNCOMMITTED
--- READ COMMITTED
--- REPEATABLE READ
--- SERIALIZABLE
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED
select @@global.transaction_isolation;
隔离级别不一致性问题的关系
隔离级别 | 脏读 | 不可重复读 | 幻象读 |
---|---|---|---|
读未提交 | √ | √ | √ |
读已提交 | × | √ | √ |
可重复读 | × | × | √ |
串行化 | × | × | × |