1.事务的四大特征
ACID
原子性(Automicity):不可分割的最小单位,要么同时成功,要么同时失败。
持久性(Durablity):当事务提交或回滚之后,数据库会持久化的保存数据。
隔离性(Isolation):多个事务之间相互独立。事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干预,事务之间要相互隔离。
一致性(Consistency):事务操作前后,数据总量不变。
(1)原子性
针对同一个事务
这个过程包含两个步骤
A: 800 - 200 = 600
B: 200 + 200 = 400
原子性表示,这两个步骤一起成功,或者一起失败,不能只发生其中一个动作。
(2)持久性
表示事务结束后的数据不随着外界原因导致数据丢失
操作前A:800,B:200
操作后A:600,B:400
如果在操作前(事务还没有提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为
A:800,B:200
如果在操作后(事务已经提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为
A:600,B:400
(3)隔离性
针对多个用户同时操作,主要是排除其他事务对本次事务的影响
两个事务同时进行,其中一个事务读取到另外一个事务还没有提交的数据
(4)一致性
针对一个事务操作前与操作后的状态一致
操作前A:800,B:200
操作后A:600,B:400
一致性表示事务完成后,符合逻辑运算
2.事务隔离级别
(1)概念
多个事务之间隔离的,相互独立的,但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。
(2)存在问题
脏读:一个事务,读取到另一个事务中没有提交的数据
不可重复读(虚读):在同一个事务中,两次读取的数据不一样
幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
(3)隔离级别
- read uncommited:读未提交
设置这样的数据库隔离级别,会产生的问题:脏读、不可重复读、幻读
- read commited:读已提交(ORACLE默认)
产生的问题:不可重复读、幻读
- repeatable read:可重复读(MySQL默认)
产生的问题:幻读
- serializable:串行化
可以解决所有的问题。其实就是一个锁表的动作,如果一个事务在操作一张数据表,另外一个事务是不可以操作这张表的,只有当这个锁打开之后,才可以操作。但是这样的效率会很低。
注意:隔离级别从小到大安全性越来越高,但是效率越来越低
数据库查询隔离级别:
select @@tx_isolation;
数据库设置隔离级别:
set global transaction isolation level 级别字符串;
下面演示脏读和不可重复读的情况:(注意两边都要开启事务才能看到)
zhangsan这边开了一个窗口:执行下面的操作
lisi这边开了个窗口:查看钱是否到账:
lisi发现钱到账了
之后,zhangsan又执行了一步回滚的操作
lisi再去查,发现钱并没有转过来,这样就发生了脏读,不可重复读
隔离级别设置成可重复读:
zhangsan账户:
lisi账号:
串行化:
其实就是一个锁表的动作,如果一个事务在操作一张数据表,另外一个事务是不可以操作这张表的,只有当这个锁打开之后,才可以操作。但是这样的效率会很低。
set global transaction isolation level serializable;
start transaction;
-- 转账操作:
update account set money = money - 500 where id = 1;
update account set money = money + 500 where id = 2;
select @@tx_isolation;