文章目录
数据库事务
1. 概念
事务是指逻辑上的一组操作,做成这组操作的各个单元,要么全部成功,要么全部不成功。从而确保数据的准确与安全。
2. 事务的四大特性
特性 | 描述 |
---|---|
原子性 | 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生 |
一致性 | 事务必须使数据库从一个一致性状态变换到另一个一致性状态 |
隔离性 | 事务的隔离性是指多个用户并发访问数据库时,数据库为每一个用户开启的事务都不能被其他事务的操作所干扰,多个并发事务之间要相互隔离 |
持久性 | 持久性是指一个事务一旦被提交,它对数据库中的数据的改变是永久的,接下来即使数据库发生故障也不应该对其有任何影响 |
3. 事务的隔离级别
3.1 不考虑隔离级别会出现的错误情况
脏读
一个线程中的事务读到了另一线程中未提交的数据
不可重复读
一个线程中的事务读到另一线程中已经提交的update的数据(前后内容不一致)
场景:
- 员工A发起事务1,查询工资,工资为1W,此时事务1尚未关闭
- 财务人员发起了事务2,给员工涨了2K工资,并且提交了事务
- 员工A通过事务1再次发起查询请求,发现工资为1.2W,原来读出的1W读不到了
幻读(虚读)
一个线程中的事务读到另一线程中已经提交的insert或者delete的数据(前后条数不一样)
场景:
- 事务1查询所有工资为1W的员工的总数,查询出来是10人,此时事务尚未关闭
- 事务2财务人员发起,新来员工,工资1W,向表中插入2条数据,并且提交了事务
- 事务1再次查询工资为1W的员工个数,发现有12个人,见了鬼
不可重复读和幻读的区别
从总的结果来看,似乎两者都表现为两次读取的结果不一致。但从解决两者问题的控制角度看,两者还是有较大的区别。避免不可重复读只要锁住满足条件的行就行,避免幻读则需要所表。不可重复读重点在于update操作,而幻读的重点在于insert操作。
如果使用锁机制来实现这两种隔离级别,在可重复读中,该sql第一次读取到数据后,就将这些数据加锁,其它事务无法修改这些数据,就可以实现可重复 读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会 发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。
3.2 事务的隔离级别
隔离级别 | 能解决的问题 |
---|---|
Serializable (串行化) | 可避免脏读、不可重复读、幻读。隔离级别最高 |
Repeatable Read(可重复读) | 可避免脏读、不可重复读。(幻读可能发生) 该机制下会对要update的行进行加锁 |
Read Committed(读已提交) | 可以避免脏读情况,不可重复读和幻读一定会发生 |
Read Uncommitted(读未提交) | 最低级别,脏读、不可重复读和幻读都会发生 |
4. 事务的传播行为
事务往往在service层进行控制,如果出现service层方法A调用另一个service层方法B,A和B方法本身已经添加了事务控制,那么A调用B的时候,就需要进行事务的一些协商,这就加做事务的传播行为