悲观锁
它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
最佳实践
具体示例请参照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
欢迎大家索引!