您的位置:首页 > 其它

20hibernate hibernate的性能优化之事务并发和事务隔离机制

2014-07-09 16:43 218 查看
5.事务并发处理//面试的意义更大
a.事务:
是并发控制的单位,是用户定义的一个操作序列。
这些操作要么都做,要么都不做,是一个不可分割的工作单位。
通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,
以便服务器保持数据的完整性。

事务四个特性:ACID
(1)Atomicity	原子性
//事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。
(2)Consistency	一致性
// 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
//一致性与原子性是密切相关的。
(3)Isolation	独立性
//一个事务的执行不能被其他事务干扰。
(4)Durability	永久性
// 一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

b.事务并发时可能出现的问题
(1)第一类丢失更新(lost update)--见图一
//撤销一个事务覆盖了另一个已经提交事务
//只有在不支持事务的数据库才会出现的问题
(2)脏读(dirty read)--见图二
//读到了另一个事务还没提交的数据
(3)不可重复读(non-repeatable read)--见图三
//被另一个事务影响,在一个事务中前后读取的数据不一致,不知道该用哪一个
(4)第二类丢失更新(second lost update problem 不可重复读的特殊情况)
--见图四
//相当于还是前后读取的数据不一致
(5)幻读(phamtom read)--见图五
//在读的过程中,另一事务涉及到插入和删除的操作,影响了读取的结果

面试掌握(2)(3)(5),是经常出现的问题

c.数据库的事务隔离机制
(1)四种隔离级别:(级别越高,效率越低,因为要检查要上锁)
1.read uncommitted
//可以读取未提交的数据,会出现脏读、幻读和不可重复读问题
//只要数据库支持事务,就不可能出现第一类丢失更新
2.read committed (一般采用)
//只有提交过的数据才能被读取,但不能避免不可重复读和幻读
//并发性也比较好
3.repeatable read
//相当于在读取的数据上加把锁,这个事务没有结束前,别的事务不能修改该数据
4.serializable(大多数情况下不会采用)
//事务不能并发,排队进行

d.设定hibernate的事务隔离级别
(1)在hibernate.cfg.xml中设置hibernate.connection.isolation=2
//取值有1,2,4,8(值是通过二进制设置的,算法效率高,通过左移右移可实现更改)
//1是read-uncommitted;2是read-committed
//4是repeatable read;8是serializable
//不设的话,依赖于数据库
//原则是尽量平衡并发和效率
(2)用悲观锁解决repeatable read的问题(依赖于数据库本身的实现)
1.select...for update
2.load(xx.class,i,LockMode.Upgrade)//Upgrade的意思是让数据库加把锁
a.LockMode.None 无锁的机制,Transaction结束时,切换到此模式
b.LockMode.read 在查询的时候hibernate会自动获取锁
c.LockMode.write insert update的时候hibernate会自动获取锁
d.以上三种锁的模式,是hibernate内部使用的
e.LockMode.Upgrade_NOWAIT oracle支持的锁的方式

@Entity
public class Account
{
private int id;
private int balance;//涉及金额应采用BigDecimal
}

public void testPessimisticLock(){
Session session = sf.openSession();
session.beginTransaction();

Account a = (Account)session.load(Account.class,1,LockMode.UPGRADE);
int balance = a.getBalance();
balance = balance-10;
a.setBalance(balance);

session.getTransaction().commit();
session.close();
}

e.hibernate(JPA)乐观锁定(Read Committed)
//采用@Version注解
//悲观锁是借助数据库的锁,乐观锁是设置版本字段,
//乐观锁通过比较版本来判断当前数据是否被更新过
@Entity
public class Account
{
private int id;
private int balance;
@Version
private int version;
}

public void testOptimisticLock(){
Session session = sf.openSession();
Session session2 = sf.openSession();
session.beginTransaction();
Account a1 = (Account)session.load(Account.class,1);

session2.beginTransaction();
Account a2 = (Account)session2.load(Account.class,1);

a1.setBalance(900);
a2.setBalance(1100);

session.getTransaction().commit();
System.out.println(a1.getVersion());

session2.getTransaction().commit();
//此处会报错:Row was updated or deleted by another transaction
System.out.println(a2.getVersion());

session.close();
session2.close();
}










内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: