blog » 数据库基础 » 悲观锁总结

悲观锁总结

悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

一个典型的倚赖数据库的悲观锁调用:

select * from account where name="Erica" for update

这条 sql 语句锁定了 account 表中所有符合检索条件( name=”Erica” )的记录。 本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。

Hibernate 的悲观锁,也是基于数据库的锁机制实现。下面的代码实现了对查询记录的加锁:

String hqlStr = "from TUser as user where user.name='Erica'";
Query query = session.createQuery(hqlStr);
query.setLockMode("user",LockMode.UPGRADE); // 加锁
List userList = query.list();// 执行查询,获取数据

query.setLockMode 对查询语句中,特定别名所对应的记录进行加锁(我们为TUser 类指定了一个别名”user”),这里也就是对返回的所有 user 记录进行加锁。
观察运行期 Hibernate 生成的 SQL 语句:

select tuser0_.id as id, tuser0_.name as name, tuser0_.group_id as group_id, tuser0_.user_type as user_type, tuser0_.sex as sex from t_user tuser0_ where (tuser0_.name='Erica' ) for update

这里 Hibernate 通过使用数据库的 for update 子句实现了悲观锁机制。

Hibernate 的加锁模式有:

LockMode.NONE : 无锁机制。
LockMode.WRITE : Hibernate 在 Insert 和 Update 记录的时候会自动获取。
LockMode.READ : Hibernate 在读取记录的时候会自动获取。

以上这三种锁机制一般由 Hibernate 内部使用,如 Hibernate 为了保证 Update过程中对象不会被外界修改,会在 save 方法实现中自动为目标对象加上 WRITE 锁。

LockMode.UPGRADE :利用数据库的 for update 子句加锁。
LockMode. UPGRADE_NOWAIT : Oracle 的特定实现,利用 Oracle 的 forupdate nowait 子句实现加锁。

上面这两种锁机制是我们在应用层较为常用的,加锁一般通过以下方法实现:

Criteria.setLockMode
Query.setLockMode
Session.lock

注意,只有在查询开始之前(也就是 Hiberate 生成 SQL 之前)设定加锁,才会真正通过数据库的锁机制进行加锁处理,否则,数据已经通过不包含 for update 子句的 Select SQL 加载进来,所谓数据库加锁也就无从谈起。

This post has already been read 873 times!

Related posts

RSS 2.0 | leave a response | trackback

发表评论