悲观锁和乐观锁是并发控制常用的两种技术手段。
并发控制是用来确保 多个事务同时读写DB中同一条数据时不破坏事务的隔离性、统一性以及数据库的统一性。

悲观锁

悲观锁 (Pessimistic Lock),又称悲观并发控制 (Pessimistic Concurrency Control)

对数据的处理保持悲观的心态。在数据处理过程中,利用数据库层提供的锁机制,始终将数据置于锁定状态,直至处理完成。

悲观锁的流程如下:
1. 在数据更新前对该待更新数据加排他锁
2. 若加锁失败,说明该条数据正在被更新,则等待解锁或抛异常
3. 若加锁成功,则开始更新操作,事务完成后解锁。期间若其它事务尝试更新该数据则会等待解锁或抛异常

一个典型的示例:

-- 0. 开始事务
-- 1. 使用 select ... for update 加锁 (需要注意 where 内字段需要加索引否则会锁表)
select id from table_name where id=1 for update;
-- 2. 更新操作
-- 3. 提交事务

乐观锁

乐观锁 (Optimistic Locking),又称乐观并发控制 (Optimistic Concurrency Control)

对数据的处理保持乐观的心态。假定在更新数据时不会有其它事务同时来更新。只在数据更新时进行判定,若与预期不符合则不进行更新。

一般实现乐观锁的方式是记录数据版本,实现数据版本有两种方式: 版本号和时间戳。

一个典型的示例:

-- 1. 查询信息
select id,type,version from table_name where id=1;
-- 2. 更新操作
update table_name set type=2,version=version+1 where id=1 and version=version; 

乐观锁因锁的时间短(只发生在update时),与悲观锁相比效率会更高一些(支持更高的并发量),但同样因此可能存在ABA的问题。

参考

  1. 深入理解乐观锁与悲观锁
  2. MySQL 乐观锁与悲观锁