事务要么全做,要么全都不做。
事务并发会引发脏读,不可重复读和幻读,事务隔离就是解决这个问题,有多种隔离级别。
虽然也能通过JDBC代码改事务隔离级别,但是这是数据库层面的。
低级的事务隔离级别支持更高的并发操作,系统代价也更小。
慎用高级的事务隔离级别。
脏读:一个事务读取了另一个事务尚未提交的数据。
案例:是指一个事务读取了另一个事务尚未提交的数据。假设Mary的工资是1000,财务人员在某一时刻将Mary的工资改成8000(但未提交这个修改事务),此时Mary读取自己的工资,发现变为了8000,欢天喜地!但财务发现操作有误,回滚了事务,Mary的工资又变为了1000
解决办法:Mary读到的8000是脏数据。如果在第一个事务提交前,任何其他事务不可读取其修改过的值,则可以避免该问题
不可重复读:一个事务的操作导致另一个事务前后两次读取到不同的数据。
在事务1中,Mary 读取到工资是1000,但针对工资的操作并没有完成,在另个事务中,财务人员修改了Mary的工资为2000,并提交,这时在事务1中,Mary再次读取自己的工资时,工资变为了2000
解决办法:只有在修改事务完全提交之后,才可以允许读取数据
幻读:一个事务的操作会导致另一个事务前后两次查询的结果不同。
在事务1里,读取到了10条工资是1000元的员工记录,这时事务2又插入了一条员工记录,工资也是1000,那么事务1再次以“工资是1000的员工”作为查询条件读取时,就会返回11条数据
解决办法:在操作事务完成数据处理之前,任何其他事务都不能添加新数据,则可避免该问题
不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
1、事务隔离级别为读提交时,写数据只会锁住相应的行
2、事务隔离级别为可重复读时,如果检索条件有索引(包括主键索引)的时候,默认加锁方式是next-key 锁;如果检索条件没有索引,更新数据时会锁住整张表。一个间隙被事务加了锁,其他事务是不能在这个间隙插入记录的,这样可以防止幻读。
3、事务隔离级别为串行化时,读写数据都会锁住整张表
4、隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
JDBC中事务隔离:
读取未提交:TRANSACTION_READ_UNCOMMITTED,允许脏读、不可重复读和幻读
读取提交:TRANSACTION_READ_COMMITTED,禁止脏读,但允许不可重复读和幻读
可重读:TRANSACTION_REPEATABLE_READ,禁止脏读和不可重复读,但允许幻读
可串化:TRANSACTION_SERIALIZABLE,禁止脏读、不可重复读和幻读
TRANSACTION_NONE含义是,JDBC驱动不支持事务
不设用数据库默认的隔离级别,MySQL是可重读,Oracle是读取提交
事务隔离级别设置过高的话:
比如设置可串化,禁止脏读、不可重复读和幻读
一个事务在操作时,会导致其它事务等待,但保持连接
如果该事务持续时间很长,这段时间来了很多事务,会导致连接数过高
数据库服务器有连接数上限,到达后其它连接进不来
会导致前台的业务操作无法继续
总结:
要能说明脏读,不可重复读,幻读的概念
说明JDBC多个值,支持的级别,默认值。
隔离级别过高的危害。
引出事务传播机制等