数据库的悲观锁和乐观锁

悲观锁

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

最佳实践

具体示例请参照MySQL的悲观锁实现

乐观锁

  乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库 性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。相对悲观锁而言,乐观锁更倾向于开发运用。

最佳实践

首先创建一张表。

mysql> CREATE TABLE optimistic_lock(id INT PRIMARY KEY, name CHAR(20), version TIMESTAMP);

TIMESTAMP类型有个特性,就是数据一旦有增改就会自动变化。

然后向表里插入三条数据。

mysql> INSERT INTO optimistic_lock(id, name) VALUES(1, '张三'),(2, '李四'),(3, '王五');

目前数据是这样的。

下面开始模拟在多线程下进行数据更新:

程序A读取id为1的数据,其中version字段值为2017-12-23 02:27:25。

这时程序B也读取id为1的数据,其中version字段值也为2017-12-23 02:27:25。

mysql> SELECT version FROM optimistic_lock WHERE id = 1;

程序A开始更新id为1的数据的name字段为刘勇。

mysql> UPDATE optimistic_lock SET name = '刘勇' WHERE id = 1 AND version = '2017-12-23 02:27:25';

这里与平时唯一不同的地方就是我将version字段也当做更新条件。

我们可以查看一下更新结果:

name字段已经变为刘勇,而根据TIMESTAMP类型的特性也改变了时间戳。

这时程序B对id为1的数据的name字段进行更新。

mysql> UPDATE optimistic_lock SET name = '王亮' WHERE id = 1 AND version  = '2017-12-23 02:27:25';

我们也看一下更新结果:

数据没有更新,因为version字段已经匹配不上了。

优缺点

相比悲观锁的长事务阻塞,乐观锁实现了数据自有读取更新,提高了读写效率和并发量。但缺点也很明显,谁先更新数据谁就可以获得成功,这样的无序也源于乐观锁的开放性。


 

本文索引关键字:

乐观锁:http://www.cnblogs.com/huanStephen/p/8094017.html#o_lock

欢迎大家索引!

posted @ 2017-12-23 17:53  huanStephen  阅读(1477)  评论(0编辑  收藏  举报