事务学习笔记
1、事务的4个属性
(1)Atomic原子性
(2)Consistent一致性
(3)Isolation隔离性
(4)Duration持久性
2、3种事务会出现的问题
(1)dirty read 脏读
如:A事务开始执行,并修改了资源数据,A事务未提交B事务读取A事务修改后的值,A事务可能回滚。(即:一个事务读取另一个未提交事务的数据)
(2)norepeatable-read 不可重复读
如:A事务读取数据后,中间B事务插队进来对数据进行操作(更新)并提交,当A事务在读取数据时,两次读取数据不同(不可重复读主要指更新)
(3)Phantom read幻读
如:A事务读取数据后,中间B事务插队进来对数据进行操作(删除或插入)并提交,当A事务在读取数据时,两次读取数据不同(幻象读主要指删除或插入)
3、java API Connection 五个事务级别
(1)TRANSACTION_NONE 不支持事务级别,可以不在考虑的范围之内
(2)TRANSACTION_READ_UNCOMMITTED 即在一个事务没有提交另一个事务可以进行操作,脏读,不可重复读,幻象读都可以发生。
(3)TRANSACTION_READ_COMMITTED 在一个事务提交后,另一个事务可以操作,可避免脏读
(4)TREANSACTION_REPEATABLE_READ 可重复读,可以避免脏读,不可重复读(ps:这里原理还不太清楚,知道的大侠多多拍砖)
(5)TRANSACTION_SERIALIZABLE 事务序列化,事务串行执行,可以避免上述所有事务问题,但效率差,这是必须的吗,并发性降低了
4、Hibernate对事物的处理
a.在并发性和数据处理之间的一个平衡点,一般是将事物级别设置为hibernate.connection.isolation=2,即TRANSACTION_READ_COMMITTED可以防止脏读。
b.悲观锁,在读取出来的时候加上一把锁,load(String entityName, Serializable id, LockOptions lockOptions),把LockOptions设置为LockOptions.UPGRADE
c.乐观锁,通过数据库的冗余来达到高并发,在数据库中设置一个版本字段,也即是在持久化的pojo对象中增加一个版本属性 version并用@Version 进行注解,只要一个事务对数据进行更新操作版本字段就会改变+1,这样另A个事务开始时读取的版本号与事务提交时的读入版本号不同,则说明其他事务应经动过改数据,就会抛出StaleObjectStateException,那么现在就好办了,捕获异常并进行处理就ok了
5、事务的传播行为
如:方法A--->methodA(),调用方法B---->methodB()
(1)TransactionAttributeType.REQUIRED 大概就是被调用的方法一定会在一个事务范围中运行
)
methodA()methodB()在一个事务中直接处于methodA()事务范围中进行运行不在在一个事务中抛出TransactionRequiredException
(4)TransactionAttributeType.NOT_SUPPORTED 大概就是被调用的方法一定不会有事务范围中运行
methodA()methodB()在一个事务中a.挂起methodA当前事务b.执行methodB()c.执行完methodB()之后恢复methodA()事务不在在一个事务中执行methodB()
(5)TransactionAttributeType.SUPPORTS 大概就是被调用的方法可以在有事务范围或无事务范围中运行(有点嫁鸡随鸡,嫁狗随狗的感觉)
methodA()methodB()在一个事务中在methodA()事务范围中执行不在在一个事务中执行methodB()
(6)TransactionAttributeType.NEVER大概就是被调用的方法可一定要在事务范围中运行
methodA()methodB()在一个事务中抛出RemoteException不在在一个事务中执行methodB()
6、EJB的事务管理
(1)CMT-->Container Manage Transaction 由容器完成事务的处理
(2)BMt --->Bean Manage Transaction 开发者通过代码完成事务的处理
参考:经典JAVA EE企业应用实战