事务并发的五类问题
- 第一类丢失更新:两个事务同时更新一个数据,A提交,B回滚,数据回滚
- 第二类 丢失更新:两个数据同时关系一个数据,A晚提交,B早提交,B无效
- 脏读:一个事务内,读取了事务B未提交的数据.(结果事务B回滚,该事务就用了脏数据)
- 虚读:一个事务内,前后读取不一致,(期间有人增加过数据)
- 不可重复读:一个事务内两次读取同一条数据,返回结果不相同.(期间有人修改过该数据)
MySQL的隔离级别
Serializable(串行化):可避免脏读、不可重复读、虚读情况的发生。
Repeatable read(可重复读):可避免脏读、不可重复读情况的发生。(默认)
Read committed(读已提交):可避免脏读情况发生。
Read uncommitted(读未提交):最低级别,以上情况均无法保证。
悲观锁
原理:事务不并发.
事务A开始后,拿到锁.直至回滚或提交才放锁.其他事务无锁就一直等待(不提交,造成死锁),等同于: select for update
例1:
事务1:
Employee e1=session.get(Employee.class,1L,LockOptions.UPGRADE);//对该对象上锁
事务2:
Employee e1=session.get(Employee.class,1L);
e1.setName("XX");//执行修改时候被锁住
例2:
事务1:
Employee e1=session.get(Employee.class,1L,LockOptions.UPGRADE);//对该对象上锁
事务2:
Employee e1=session.get(Employee.class,1L,LockOptions.UPGRADE);//查询时候被锁住
e1.setName("XX");//不会到这一步
乐观锁
原理:支持并发:在类加属性,在表中加列 表示版本号
在查询对象时候,获得版本号;
在修改对象时, 版本号+1 where id=? AND 版本号=?;
此时,若版本号不一致,说明已经被更换数据,会导致本次更改失败
例:
//在类中
private Integer version;
//映射文件中
<version name="version"/>