事务属性的种类:传播行为,隔离级别,只读和事务超时。
1.传播行为定义了被调用方法的事务边界。
propergation_mandatory 表示方法必须运行在一个事务中,如果当前事务不存在,就抛出异常。
propagation_nested 表示如果当前事务存在,则方法应该运行在一个嵌套事务中。否则它和propergation_mandatory一样。
propagation_never 表示一个方法不能运行在一个事务中,否则抛出异常。
propagation_not_supported 表示方法不能运行在一个事务中,如果当前存在一个事务,哪么方法将被挂起。
propagation_required 表示当前方法必须运行在事务中,如果当前存在一个事务,就在这个事务中运行,否则创建一个事务。
propagation_requires_new 表示当前方法必须运行在自己的事务中,如果当前存在一个事务,那么这个事务在方法运行时会被挂起。
propagation_supports 表示当前方法不需要运行在事务中,如果当前有一个事务,该方法也可以运行在这个事务中。
2.隔离级别:在操作数据的时候可能会带来三个副作用,分别是脏读,不可重复读,幻读,为了避免这三个副作用的发生,在标准的sql语句中定义了4种隔离级别,分别是未提交读,已提交读,可重复读,可序列化。而在spring事务中提供了5种隔离级别对应sql中的4中隔离级别。
脏读:一个事务读取到另一个事务没有提交的数据。当一个事务对数据进行了修改,而这种修改还没提交到数据库,这时另一个事务也访问了这条数据,然后使用了这条数据。因为这个事务读取到的是另一个事务没提交的数据,那么这一个事务读取到的数据就是脏数据,依据脏数据所做的操作可能不正确的。
例如:
张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。
与此同时,
事务B正在读取张三的工资,读取到张三的工资为8000。
随后,
事务A发生异常,而回滚了事务。张三的工资又回滚为5000。
最后,
事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。
不可重复读:是指在同一事务内,多次读取同一事务,在这个事务没有结束时,另一个事务也访问了同一数据,在第一个事务读取两次数据之间,第二个事务进行了修改并且提交了,导致事务1两次读取数据不同,这样就导致在一个事务中两次读取到的数据不一样,称为不可重复读。
例如:
在事务A中,读取到张三的工资为5000,操作没有完成,事务还没提交。
与此同时,
事务B把张三的工资改为8000,并提交了事务。
随后,
在事务A中,再次读取张三的工资,此时工资变为8000。在一个事务中前后两次读取的结果并不致,导致了不可重复读。
幻读:同一事务中,用同样的操作读取两次,得到的记录数不同。事务不是独立执行时发生的一种现象,例如一个事务对表中的数据进行了修改,这种修改涉及到表中的的所有数据行,同时第二个事务向表中插入了一条数据。在操作第一个事务的用户来看还有一条数据还没有修改,就好像产生幻觉了。
例如:
目前工资为5000的员工有10人,事务A读取所有工资为5000的人数为10人。
此时,
事务B插入一条工资也为5000的记录。
这是,事务A再次读取工资为5000的员工,记录为11人。此时产生了幻读。
隔离级别
isolation_default 使用后端数据库默认的隔离级别
isolation_read_uncommitted 允许读取未提交的数据,可能导致脏读,不可重复读,幻读
isolation_reda_committed 允许在一个事务中读取另一个已经提交的事务的数据。可避免脏读,不可避免重复读和幻象读
isolation_repeatable_reda 一个事务不可能更新由另一个事务修改但尚为提交的数据,可避免脏读,不可重复读,不可避免幻象读。
isolation_serializable 这种隔离级别是所有的事务都在一个执行队列中,依次顺序执行,而不是并行。可以避免脏读,不可重复读,幻象读。但是这种隔离级别效率特别低,除非必须,不建议使用。
3.只读:如果在一个事务中,所有有关数据库的操作都是只读,也就是说这些操作只读取数据库中的数据,并不进行更新,那么应将事务设为只读模式(reda_only_marker),这样更有利于数据库优化。
因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些可能具有启动新事物的传播行为(propagation_nested propagation_required propagation_required_new)的方法的事务标记为只读才有意义.
如果使用hibernate作为持久化机制,那么将事务标记为只读后,会将hibernate的flush模式设置为FLUSH_NEVER,以告诉hibernate避免和数据库之间进行不必要的同步,并将所有更新延迟到事务结束。
4.事务超时。
如果一个事务长时间运行,这是为了尽量避免系统资源的浪费,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设计只读属性一样事务有效属性也需要给那些具有可能启动新事务的传播行为的方法的事务标记成只读才有意义