MySQL中只有使用了innodb数据库引擎的数据库或表才支持事务。
事务的AICD
原子性:Atomicity 是一个不可分割的工作单元,事务中的操作要么都发生,要么都不发生
一致性:Consistency 事务前后数据的完整性必须保持一致
隔离性:Isolation 并发事务之间相互隔离
持久性:Durability 事务一旦被提交,它对数据库中数据的改变就是永久性的
脏读:一个事务读取了另一个事务未提交的数据
不可重复度:一个事务内,多次读取结果不同
虚读(幻读):在一个事务内读取到了别的事务插入的数据,导致前后读取不一致
事务的四种隔离级别:
读未提交 最低级别,以上情况均无法避免
读已提交 可避免脏读
可重复读 可避免脏读、不可重复读
串行化 以上情况都可避免
java中事务的隔离级别
ISOLATION_DEFAULT:
是事务管理器的默认隔离级别,使用数据库默认的隔离级别,另外四个与jdbc的隔离级别相对应
ISOLATION_READ_UNCOMMITTED:
最低的隔离级别,它允许一个事务读取另一个事务未提交的数据,会产生脏读不可重复读,幻读
ISOLATION_READ_COMMITTED:
保证一个事务修改的数据提交后另一个事务才能读取到,可以避免脏读.
ISOLATION_REPEATABLE_READ:
数据库就是使用的这种隔离级别,可以避免脏读和不可重复读,但是可能出现幻读(幻读:一个事务读取完,
另一个事务提交了更新,本事务再次读取会发现前后数据不一致,像产生了幻觉一样,所以叫幻读)
ISOLATION_SERIALIZABLE:
花费代价最高也是最可开的事务隔离级别,事务被处理为顺序执行,但是这种隔离级别会产生锁表,就是
一个事务读取之后,另一个事务必须等待这个事务完成,他才可以进行,第一个事务会将整张表锁起来,
一般不会使用这种隔离级别,性能极低!
事务的传播机制:多个事务方法互相调用时,事务如何在这些方法间传播。
Spring定义事务传播行为七种类型:
REQUIED (spring默认的事务传播类型):如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务。
SPORTS:当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行。
MANDATORY:当前存在事务,则加入当前事务,如果当前不存在事务,则抛出异常。
REQUIED_NEW:创建一个新事务,如果存在当前事务,则挂起该事务。
NOT_SUPPORTED:始终以非事务的方式执行,如果存在事务,则挂起事务。
NEVER:不使用事务,如果当前存在事务,则抛出异常。
NESTED:如果当前事务存在,则在嵌套事务(父子事务)中执行,否则开启一个事务。
和REQUIED_NEW的区别:REQUIED_NEW是新建一个事务,与原有事务无关,而NESTED则是当前事务(父事务)存在时,开启一个嵌套事务(子事务),父事务回滚时,子事务也会回滚;而REQUIED_NEW,原有事务回滚,不会影响新开启的事务。
和REQUIED的区别:REQUIED调用方和被调用方使用同一个事务,由于共用一个事务,无论调用方是否catch,事务都会回滚;而NESTED,调用方catch了异常,当被调用发生异常时,只有子事务发生回滚,父事务不会回滚。
分布式事务:用于在分布式系统中保证不同节点间的数据一致性。
XA协议,两阶段提交和三阶段提交两种实现。prepare确认-commit确认,三阶段添加了超时机制,超时自动commit。(角色:事务协调者、事务参与者)
存在的问题:性能问题(强一致性)、协调者单点故障、丢失消息导致不一致
MQ事务,最终一致性。
TCC事务,try-commit-cancel,代码层面人为实现。
事务实现原理、事务失效的场景