目录
08、数据库事务
8.1、事务含义
事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行
,要么全部不执行
。
Transaction Control Language :事务控制语言
为什么要使用事务:
- 案例:转账
ACCOUNT_A 1000
ACCOUNT_B 1000
账户A向账户B转账
- 账户A已经扣钱
update 表 set ACCOUNT_A的余额=500 where name='ACCOUNT_A'
- 中间发生意外账户B没有收到钱
update 表 set ACCOUNT_B的余额=1500 where name='ACCOUNT_B'
- 分析:如果不使用事务,则A的账户少了钱,B账户没有得到钱,这就难受了!!!!!
8.2、事务特点:ACID
- 原子性(atomicity):要么都执行,要么都回滚
- 一致性(consistency):保证数据的状态操作前和操作后保持一致
- 隔离性(isolation):多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受另外一个事务的干扰
- 持久性(durability):一个事务一旦提交,它对数据库中的数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。数据将持久化到本地。
使用事务事务相关步骤:
- 1、开启事务
- 2、编写事务的一组逻辑操作单元(多条sql语句)
- 3、提交事务或回滚事务
8.3、事务的分类:
隐式事务:没有明显的开启和结束事务的标志
比如:insert、update、delete语句本身就是一个事务
显式事务,具有明显的开启和结束事务的标志
1、开启事务
set autocommit=0;
start transaction;可选的
2、编写事务的一组逻辑操作单元(多条sql语句)
insert
update
delete
3、提交事务或回滚事务
commit;提交事务
rollback;回滚事务
- 注意:
前提,必须先设置自动提交功能为禁用
set autocommit=0;
8.4、使用到的关键字
- 设置取消自动提交
set autocommit=0;
- 设置开启事务
start transaction;
- 事务的提交
commit;
- 事务回滚
rollback;
- 设置保存点:结合
commit
和rollback
使用
savepoint 断点
commit to 断点
rollback to 断点
8.5、事务的隔离级别
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制
,就会导致各种并发问题
事务并发问题如何发生?
- 当多个事务同时操作同一个数据库的相同数据时
事务的并发问题有哪些?
- 脏读:一个事务读取到了另外一个事务未提交的数据
举例:对于两个事务T1,T2,T1读取了已经被T2更新但还
没有被提交
的字段之后,若T2回滚,T1读取的内容就是临时且无效的
- 不可重复读:同一个事务中,多次读取到的数据不一致
举例:对于两个事务T1,T2,T1读取了一个字段,然后T2
更新
了该字段之后,T1再次读取同一个字段,值不一样。
- 幻读:一个事务读取数据时,另外一个事务进行更新,导致第一个事务读取到了没有更新的数据
举例:对于两个事务T1,T2,T1读取了一个表中的一个字段,然后T2在该表中
插入
了一些新的行之后,T1再次读取同一个表,就会多出几行。
如何避免事务的并发问题?
- 通过设置
事务的隔离级别
隔离级别 | 描述 |
---|---|
READ UNCOMMITTED:读取为提交的数据 | 允许事务读取未被 其他事务提交的变更 ,脏读,不可重复读,幻读都会出现 |
READ COMMITTED:读已提交的数据 | 只允许事务读取已经 被其他事务提交的变更 。可避免脏读,但是可能会出现不可重复读和幻读 |
REPEATABLE READ:可重复度 | 确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止和其他事务对这个字段进行更新 ,可以避免脏读和不可重复读,但是幻读的可能会出现 |
SERIALIZABLE:串行化 | 确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入 ,更新 和删除 操作,所有问题都可避免,但是性能低下 |
注意:
- Oracle支持两种事务隔离级别:READ COMMITED,SERIALIZABLE
- MySQL支持四种隔离级别:
默认的隔离界别为REPEATABLE READ
设置隔离级别:
- 设置当前会话的隔离级别:只对当前会话有效
set session transaction isolation level 隔离级别名;
- 设置全局的隔离级别:对所有会话有效
set global transaction isolation level 隔离级别名;
查看隔离级别:
select @@tx_isolation;
8.6、演示事务隔离级别
创建一个数据库:demo
CREATE DATABASE IF NOT EXISTS demo;
USE demo;
DROP TABLE IF EXISTS tab_tx;
CREATE TABLE tab_tx(
id int(4) PRIMARY KEY,
userName varchar(20) ,
money int(4)
);
查看数据库的隔离级别:
select @@tx_isolation;
READ UNCOMMITTED级别演示
设置隔离级别
set session transaction isolation level READ UNCOMMITTED;
第一个事务更新
一下表,但是不提交
,然后使用第二个事务读取表中的数据,看看能否读到,也就是会不会出现脏读:
- 如果事务
不执行提交操作
而是执行回滚操作
,就会出现脏读,事务二两次读到的数据不一样
READ COMMITTED级别演示
设置隔离级别
set session transaction isolation level READ COMMITTED;
第一个事务更新
一下表,如果不提交,第二个事务读取不到,如果提交
就可以读取到,避免了脏读
:
但是会出现不可重复读,事务二第一次读取的结果和第二次读取的结果不一样:
REPEATABLE READ级别演示
设置隔离级别
set session transaction isolation level REPEATABLE READ;
第一个事务更新
一下表,无论是否提交
,第二个事务都读取不到,有效避免了脏读
和不可重复读
:
看看会不会出现幻读:
- 开启事务后事务一向表中
插入
一行,事务二单纯的查询
是不会有问题的,但是如果事务二在事务一进行插入操作后
,执行更新操作
就会出现问题,原本的一条数据
,执行更新后变成了两条数据
,这就是所谓的幻读:
SERIALIZABLE级别演示
设置隔离级别
set session transaction isolation level SERIALIZABLE;
隔离级别四也是最高的隔离级别
,同时也是效率最差的隔离级别
,因为当一个事务开启之后,就会阻塞
其他事务的进行,只有这个事务提交之后,其他事务才可以进行,类似于锁机制
,这样就可以避免所有的问题。