Hibernate事务隔离机制(乐观锁-悲观锁)(一)

2015-01-21 11:21:11 · 作者: · 浏览: 22

事务隔离机制

1、事务:ACID

2、事务并发时可能出现的问题

a) 第一类丢失更新

时间

取款事务A

存款事务B

T1

开始事务

?

T2

?

开始事务

T3

查询账户余额为1000元

?

T4

?

查询账户余额为1000元

T5

?

汇入100元把余额改成1100元

T6

?

提交事务

T7

取出100元把余额改成900元

?

T8

撤销事务

?

T9

余额恢复为1000元(丢失更新)

?

?

b) dirty read脏读(读了另一个事务没有提交的数据)

时间

取款事务A

存款事务B

T1

开始事务

?

T2

?

开始事务

T3

?

查询账户余额为1000元

T4

?

汇入100元把余额改成1100元

T5

查询账户余额为1100元(读取脏数据)

?

T6

?

回滚

T7

取款1100元

?

T8

事务提交失败

?

?

c) non-repeatable-read不可重复读(同一个事务中,读取同一个数据,得到的值不同)

?

时间

取款事务A

转账事务B

T1

事务开始

?

T2

?

事务开始

T3

查询账户余额为1000元

?

T4

?

汇入100元把余额改成1100元

T5

?

提交事务

T6

查询账户余额为1100元

?

T7

提交事务

?

?

d)second lost update problems第二类丢失更新(不可重复读的特殊情况)

时间

转账事务A

取款事务B

T1

?

开始事务

T2

开始事务

?

T3

?

查询账户余额为1000元

T4

查询账户余额为1000元

?

T5

?

取出100元把余额改成900元

T6

?

提交事务

T7

汇入100元

?

T8

提交事务

?

T9

把余额改成1100元(丢失更新)

?

?

e) phantom read 幻读(插入、删除问题导致取得的结果不同)

时间

查询学生事务A

插入学生事务B

T1

开始事务

?

T2

?

开始事务

T3

查询学生为10人

?

T4

?

插入一个新学生

T5

查询学生为11人

?

T6

?

提交事务

T7

提交事务

?

?

?

3、数据库的事务隔离机制

1、read-uncommited

2、read-commited

3、repeatable-read

4、serializable

?

a) 只要数据库支持事务,就不会出现read-uncommited情况

b) read-uncommited会出现dirty-read,phantom read,non-repeatable-read问题

c) sead-commited不会出现dirty-read,但仍会出现non-repeatable-read,phantom read

d) repeatable-read

e) serializable解决一切问题

?

?

4、设定hibernate的事务隔离级别

1、为了考虑并发效率,设置Hibernte.connection.isolate=2(即使用的是read-commited)

2、用悲观锁解决repeatable read问题(依赖于数据库的锁)

A)相当于select ...for update

?

?

?

?

?

悲观锁:

实验:

(1)建立Account.java类

package com.zgy.hibernate.model;

?

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

?

@Entity

public class Account {

private int id;

private int balance; //BigDecimal

@Id

@GeneratedValue

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public int getBalance() {

return balance;

}

public void setBalance(int balance) {

this.balance = balance;

}

?

?

}

(2)HibernateUtil.java,用于获取SessionFactory

package com.zgy.hibernate.model;

?

import org.hibernate.SessionFactory;

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import org.hibernate.cfg.Configuration;

import org.hibernate.service.ServiceRegistry;

?

public class HibernateUtil {

static SessionFactory sessionFactory = buildSessionFactory();

?

private static SessionFactory buildSessionFactory() {

Configuration configure = new Configuration().configure();

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()

.applySettings(configure.getProperties()).build();

return sessionFactory = configure.buildSessionFactory(serviceRegistry);

}

?

public static SessionFactory getSessionFactory(){

return sessionFactory;

}

}

(3)测试类

package com.zgy.hibernate.model;

?

?

import org.hibernate.LockMode;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

import org.hibernate.tool.hbm2ddl.SchemaExport;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.Test;

?

public class HibernateLockTest {

private static SessionFactory sf;

?

@BeforeClass

public static void beforeClass() {

sf = HibernateUtil.getS