事物的四大特性:一致性、隔离性、原子性、持久性
- 原子性(Atomicity):事务是数据库的逻辑工作单位,它对数据库的修改要么全部执行,要么全部不执行。
- 一致性(Consistemcy):事务前后,数据库的状态都满足所有的完整性约束。
- 隔离性(Isolation):并发执行的N个事务是隔离的,一个不影响一个,一个事务在没有commit之前,被修改的数据不可能被其他事务看到(通过设置数据库的隔离级别)。
- 持久性(Durability):持久性意味着当系统或介质发生故障时,确保已提交事务的更新不能丢失。持久性主要在于DBMS的恢复性能。
事物的隔离级别,主要是指多个事物在并发执行过程中,相互之间不被彼此干扰的特性。隔离性是事物ACID特性中的I,事物的隔离级别从低到高分为 Read Uncommitted(读未提交),Read Committed(读已提交),Repeatable Read(可重复读),Serializable(串行化)四种隔离级别。
脏读
脏读表示在一个事物中读取了另外一个未提交事物的数据
会话1 | 会话2 |
---|---|
begin | begin |
update table set age = 10 where id =1 | |
select age from table where id =1 | |
commit | commit |
表格说明了脏读在实际中的体现方式,表格中表示两个线程同时去访问表中id=1的age字段值,如果会话1和会话2都没有执行前,id=1的age=5,会话1和2一开始都开启了显示的事务(只有执行commit命令才会提交数据的修改),会话2先执行了update操作(将id=1de age字段由原来的5改为10),在会话2执行commit之前,会话1通过select语句查询了id=1的age字段值,会话1得到的数据就是10。这种就是所谓的脏读。因为会话1是在会话2没有commit之前获取的数据,如果会话2最终commit,那么对业务上没有任何损失。如果会花2在update操作后,执行了rollack,那么会话1获取的值就是错误的。
不可重复读
会话1 | 会话2 |
---|---|
begin | begin |
select age from table where id =1 | |
update table set age = 10 where id =1 | |
commit | |
select age from table where id =1 | |
commit |
如上,假设数据库表table里面id=1的记录行中age列一开始值为5,然后会话1和会话2分别开启了一个事务,会话1首先查询id=1的记录中age字段值为5,然后会话2修改id=1的记录中age的值为10然后提交了事务,然后会话1再次搜出id=1的记录中age的值,如果出现了不可重复读,则这时候搜出来的age的值为10而不是5。需要注意的是会话1两次查询是在同一个事务内进行的,期间事务并没有提交。不可重复读的存在显得不是那么不可容忍,毕竟读取的是已经提交了的数据。
幻读
会话1 | 会话2 |
---|---|
begin | begin |
select age from table where id >1 | |
insert into table(id,age) values(5,10) | |
commit | |
select age from table where id >1 | |
commit |
如上图假设表table里面一开始有一个id=3的记录,会话1首先开启了一个事务,然后查找id>2的记录,会发现结果只有一个记录,然后会话2开启事务插入了id=5的一个记录,然后提交。这时候会话1再次查找id>2的记录,如果存在幻读,则这时候会话1会看到两条记录。
注:脏读是指一个事务读取到了其他事务没有提交的数据,不可重复读是指一个事务
内多次根据同一个查询条件查询出来的同一行记录的值不一样,幻读是指一个事务内
多次根据同个条件查出来的记录行数不一样。为了解决事务并发带来的问题,才有了
事务规范中的四个事务隔离级别,不同隔离级别对上面问题部分或者全部做了避免。