实现方式 | 加锁时机 | 常见的调用方式 | 优势 | 不足 | 适用场景 | |
乐观锁 | 开发自定义 | 更新数据的时候 | sql语句中进行version的判断 | 高并发 | 容易出现不一致的问题 | 高并发读,少写 |
悲观锁 | Mysql内置 | 查询数据的开始 | select * for update | 保证一致性 | 低并发 | 互联网高并发场景极少使用了,多见于某些产品内置的数据库系统 |
乐观锁
顾名思义,总是一副乐天派的样子。每次读取数据时都很乐观,认为绝不会产生并发问题(不会有其他线程对数据进行修改)。因此,一般也不会上锁。只有在更新数据时才会去判断其他线程在此期间有没有对数据进行修改。
若未修改,则操作成功;若数据已经发生了变化则表明期间有被修改,则事务回滚并错误提示给用户端。
简单理解:别想太多,你尽管用,出问题了算我怂,大不了操作失败后事务回滚、提示用户!!!
常见的实现机制为“版本号控制”,简化版的实现思路如下:
- [li]读取记录时,获取当前
version
- 更新时,带上这个
version
- 执行更新时,
set version = newVersion where version = oldVersion
- 如果
version
不对,则更新失败,事务回滚
[/li]
update table set name = \'Aron\', version = version + 1 where id = #{id} and version = #{version};
悲观锁
顾名思义,总是假设最坏的情况。每次读取数据时都认为其他线程会同时修改数据,所以每次读取都会加(悲观)锁。
一旦加锁,不同线程同时执行时只能有一个线程执行成功,其他的线程在入口处等待,直到锁被释放。
常见的应用有:
- [li]
MySQL
的读锁、写锁、行锁等
-
Java
的
synchronized
关键字
[/li]