乐观锁和悲观锁
悲观锁
在修改数据之前先锁定(悲观地认为一定有并发),再修改的方式 被称之为悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control)。
悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。
但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加死锁的机会; 另外,还会降低并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务 处理完才可以处理那行数据。
乐观锁
实现方式:Compare And Swap(CAS)
ABA问题:
+-------------------------------------------+-------------------------------------------+
|事务A |事务B |
+-------------------------------------------+-------------------------------------------+
|start transaction with consistent snapshot;|start transaction with consistent snapshot;|
+-------------------------------------------+-------------------------------------------+
|select quantity from items where id=1; |select quantity from items where id=1; |
|quantity: 3 |quantity: 3 |
+-------------------------------------------+-------------------------------------------+
| |update items set quantity=2 where id=1 and |
| | quantity=3; |
+-------------------------------------------+-------------------------------------------+
| |update items set quantity=3 where id=1 and |
| | quantity=2; |
+-------------------------------------------+-------------------------------------------+
|update items set quantity=4 where id=1 and | |
| quantity=3; (blocked) | |
+-------------------------------------------+-------------------------------------------+
使用一个递增的version字段来解决ABA问题:
|
|
上面加锁的粒度还是太大了,如果并发度上来后,就会出现大量无效(update的行数为0)的事务。
可以像这样,直接在一个sql语句中实现:
总结
能一个sql搞定的,尽量用一个sql。 能使用乐观锁的,尽量使用乐观锁。