Hibernate上路_19-事务的丢失更新

事务的并发问题:脏读、不可重复读、幻读。
    脏读:一个事务读取另外一个事务未提交的数据。
    不可重复读:在一个事务中,读取到另外一个事务已经提交update数据,形成两次读取不同。
    幻读:在一个事务中,读取到另外一个事务已经提交insert数据,形成读取记录条数不同。
    丢失更新:两个事务同时修改目标数据,后提交的事务,会覆盖以前提交的数据。 java

鉴于并发访问出现的以上问题,数据库提供了事务隔离级别:
    1. READ_UNCOMMITED:会发生以上全部问题
    2. READ_COMMITTED:阻止脏读的发生,会发生不可重复读和幻读(Oracle 默认级别)
    3. REPEATABLE_READ:阻止脏读和不可重复读发生,会发生幻读(MySQL 默认级别)
    4. SERIALIZABLE:不会发生并发问题,串行初始化(性能很是差,也不会使用)

mysql

1.MySql事务操做:

1start transaction:开始事务
2commit:提交事务

sql

2.修改MySql事务隔离级别:

<hibernate-configuration>
	<session-factory>
		<!-- 修改事务隔离级别 -->
		<property name="hibernate.connection.isolation">2</property>

隔离级别对应数值:
    read uncommitted isolation --- 1
    read committed isolation ------ 2
    repeatable read isolation ------ 4
    serializable isolation ----------- 8  数据库

丢失更新问题解决:
    悲观锁和乐观锁。 session

2.悲观锁:

假设丢失更新发生几率很大,底层原理使用数据库内部锁的机制。 并发

    1Mysql数据库内部提供读锁(共享锁)、写锁(排它锁 );
    2)一张数据表容许添加多个读锁;
    3)一张数据表只能添加一个写锁,其与其余锁互斥。添加了写锁则不能再添加读锁;
    4)默认状况下,在修改记录时,会自动添加写锁;
    5)在执行查询时,也能够为数据添加共享锁和排它锁 
        select * from customer lock in share mode; 添加共享锁 
        select * from customer for update; 添加排它锁 
    6)悲观锁使用的便是排它锁。第1个修改执行select * from customer for update,第个操做(包括查询)须要等待
    session提供.get(Class class, Serializable id, LockMode lockMode); 
oracle

//类型,OID,锁
PojoUser user = (PojoUser) session.get(PojoUser.class, 1, LockMode.UPGRADE);
//更新操做
user.setName("XXxxx");
mysql 对应 LockMode UPGRADE
oracle  对应 LockMode UPGRADE_NOWAIT


3.乐观锁:

假设丢失更新发生几率不高,底层原理为数据添加版本号,由程序来维护版本。 app

1)在POJO中添加Integer version字段:

2)在POJO.hbm.xml中添加版本字段:

3)加断点在debug模式测试:

提交的版本号和数据库中版本不一样则报错: dom

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [cn.cvu.hibernate.domain.PojoUser#3] 

- end
   性能

相关文章
相关标签/搜索