- 数据库事务特点 ACID原子性,一致性,隔离性,永久性ACID是Atomic(原子性) Consistency(一致性) Isolation(隔离性) Durability(持久性)
- 数据库事务说是如何实现的?
- 通过预写日志方式实现的,redo和undo机制是数据库实现事务的基础
- redo日志用来在断电/数据库崩溃等状况发生时重演一次刷数据的过程,把redo日志里的数据刷到数据库里,保证了事务的持久性(Durability)
- undo日志是事务执行失败的时候撤销对数据库的操作,保证了事务的原子性。
- 数据库事务隔离级别
- 读未提交read-uncommitted:脏,不可重复读-幻读,A读取了B未提交的事务,B回滚,A出现脏读; 最低级别,以上问题均无法解决。
- 不可重复读read-committed:不可重复读-幻读,A只能读取B已经提交的事务,但是A还没结束,B又更新数据隐式提交,然后A又读了一次出现不可重复读; 可避免脏读情况发生。
- 可重复读repeatable-read<默认>-幻读,事务开启,不允许其他事务的UPDATE修改操作,A读取B已经提交的事务,然而B在该表插入新的行,之后A在读取的时候多出一行,出现幻读; 确保事务可以多次从一个字段中读取相同的值,在此事务持续期间,禁止其他事务对此字段的更新,可以避免脏读和不可重复读,仍会出现幻读问题。
- 串行化serializable-最严格的事务隔离级别,要求所有事务被串行执行,不能并发执行,可避免脏读、不可重复读、幻读情况的发生。
- 七种事务传播行为
(1)Propagation.REQUIRED<默认> 如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。
(2)Propagation.SUPPORTS 如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
(3)Propagation.MANDATORY 如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
(4)Propagation.REQUIRES_NEW 重新创建一个新的事务,如果当前存在事务,延缓当前的事务。
(5)Propagation.NOT_SUPPORTED 以非事务的方式运行,如果当前存在事务,暂停当前的事务。
(6)Propagation.NEVER 以非事务的方式运行,如果当前存在事务,则抛出异常。
(7)Propagation.NESTED 如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。
- 产生死锁的四个必要条件
(1):互斥: 资源x的任意一个时刻只能被一个线程持有
(2):占有且等待:线程1占有资源x的同时等待资源y,并不释放x
(3):不可抢占:资源x一旦被线程1占有,其他线程不能抢占x
(4):循环等待:线程1持有x,等待y,线程2持有y,等待x
当全部满足时才会死锁
- @Transaction
底层实现是AOP,动态代理
(1):实现是通过Spring代理来实现的。生成当前类的代理类,调用代理类的invoke()方法,在invoke()方法中调用 TransactionInterceptor拦截器的invoke()方法;
(2):非public方式其事务是失效的;
(3):自调用也会失效,因为动态代理机制导致
(4)多个方法外层加入try…catch,解决办法是可以在catch里 throw new RuntimeException()来处理