乐观锁和悲观锁

乐观锁:

	原理:
		1)通过在数据库表中添加一个版本号(version)字段来实现乐观锁。
		2)更新前先获取到该条数据的版本号(v1),然后在更新语句(更新数据&更新版本号)的where条件中添加 version=v1 条件,
			1>若满足version=v1条件(即:成功获取乐观锁),则成功更新数据且版本号+1;
			2>若不满足version=v1条件(即:获取乐观锁失败),说明该条数据被其它线程修改过了,则更新失败,回滚事务。
	特点:
		1)不发生获取锁失败的情况下,开销比较小。
		2)若获取锁失败,则代码需要回滚,开销比较大。
		
	应用:
		乐观锁适用于锁获取失败的概率比较小的场景,即:读取比较频繁、写入较少的场景。
	
	缺点:
		只能保证本系统对数据(数据库表)的操作是安全的,外部系统对数据(数据库表)的操作是不可控的。
		解决办法:对外部系统设置权限,即外部系统只有普通查询的权限。

		
悲观锁:

	原理:使用数据库提供的锁机制(select .. for update)。

	注意:使用悲观锁前,必须先关闭MySQL的自动提交属性。
	
	应用:
		写入比较频繁的场景。
	
	
我们应该尽量避免使用长事务:

	1)在一个事务中执行批量操作(eg:循环插入数据、循环删除数据等)会导致该事务的执行时间变长。
	2)长事务会导致数据库连接被长时间持有,如果该请求的并发量较高,则很可能出现连接池中的连接被用光的情况,从而导致其它的请求(因无法获取到数据库连接)一直处于等待状态,无法被响应。
	3)我们应该将事务的范围控制在单个操作上。


Hibernate中的乐观锁和悲观锁:

	概念:指数据库的隔离级别设为read committed时,为了解决不可重复读的问题而采用的两种办法:

	1)设定hibernate的事务隔离级别(使用hibernate.connection.isolation配置:取值1、2、4、8)
		hibernate.connection.isolation = 2(如果不设,则默认依赖数据库本身的级别)
	2)采用乐观锁和悲观锁解决不可重复读的问题
		1)悲观锁:使用另一种load方法:load(xx.class , id , LockMode.Upgrade),把读出来的数据加上一把锁,在事务结束前别人无法访问,需要借助数据库中的锁。
			注:LockMode.UPGRADE_NOWAIT是 ORACLE 支持的锁的方式
		2)乐观锁:在程序中添加一个version字段,用来检查是否被修改过。版本检查使用版本号或者时间戳来检测更新冲突(并且防止更新丢失)。
			在实体类中增加version属性(数据库也会对应生成该字段,初始值为0),并在其get方法前加@Version注解,则在操作过程中每更新一次该行数据则version值加1,即可在事务提交前判断该数据是否被其他事务修改过。
	
	eg:
		悲观锁(PessimisticLock):

		public void testPessimisticLock() {
			Session session = sf.openSession();
			session.beginTransaction();
			
			// LockMode.UPGRADE 的意思就是:在读这条记录的时候,请数据库为我读的这条记录加把锁
			Account a = (Account)session.load(Account.class, 1L, LockMode.UPGRADE);
			int balance = a.getBalance();
			//do some caculation
			balance = balance - 10;
			a.setBalance(balance);
			
			session.getTransaction().commit();
			session.close();
		}

		控制台发出的SQL语句:select ... for update	
		分析:在select语句后加上了for update,说明这里在数据库中加了一把锁。


	

	
	
			

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值