select for update是什么?作用?
查询的时候,加锁。
何时释放锁?
获取锁的当前数据库连接提交或回滚的时候,就会释放锁。
有加锁,就要释放锁。一个锁,一定有加锁和释放锁。任何一个锁,加了锁,都要释放锁。不然就有问题,其他数据库连接一直获取不了锁,就会一直阻塞。
实现原理
底层的实现原理是数据库厂商实现了行级锁,即select for update会锁住一行或几行数据,本质是数据库客户端的连接,同一时间,只有一个连接能够获取锁住的行的数据,其他连接都获取不了。
和java并发请求的原理其实是一样的,同一时间,只有一个请求线程能执行锁住的代码——锁住代码之后,就锁住了对共享数据的并发修改,最后的目的还是要锁住数据。
如何测试?
比如在pl sql客户端,开2个窗口,模拟2个客户端连接,执行同样的select for update,就会发现:
- 第一个连接可以获取数据,但是第一个连接不提交事务
- 执行第二个连接的sql,获取不到数据,阻塞了,因为获取不到锁
- 提交第一个连接的事务,再次执行第二个连接的sql,现在可以获取到数据了
实际演示如下,开两个窗口:
1)第一个窗口用select for update查询
2)在另一个窗口用同样的语句查询,会显示一直在查询...说明被block了
3)、点击第一个窗口里的提交事务按钮,另一个窗口可以立刻获取查询结果
总结
- 行级锁
select for update本质是数据库的行级,而是是数据库本身实现的。
- 数据库厂商
oracle、mysql,都实现了select for update 行级锁。
在代码里如何使用?
比如在hibernate里有select for update这个配置。
如何使用?
在dao类里调用hibernate的方法即可,dao类的代码如下:
/**
*
* @param srcCustId
* @param orderId
* @return
*/
public Orderbill selectBySrcOrderIdWithLock(String srcCustId, String orderId) {
QueryHelper help = new QueryHelper();
help.append("from Orderbill orderbill");
help.append(" where orderbill.srcCustid=? ", srcCustId);
help.append(" and orderbill.orderid=? ", orderId);
Orderbill orderbill = (Orderbill) getUniqueResult(help, "orderbill",
LockMode.UPGRADE); //
return orderbill;
}
service类的代码是
事务方法{
查询sql for update:比如查询订单; //当前数据库连接获取锁,其他数据库连接阻塞
更新sql:比如更新订单
} //spring事务方法结束的时候,提交事务,就会释放锁
参考
www.techonthenet.com/oracle/curs…