NOTE
数据库锁
1. 是什么 多个事务并发访问同一份数据的时候,肯定会有冲突发生,那么怎么处理这种冲突呢? 主要有两种思想: 1. 悲观锁机制:避免冲突发生,如Read/Write Locks,Two Phase Locking 2. 乐观锁机制:允许冲突发生,后续需要检测出冲突,如MVCC 用Java语言描述 使用Java进行多线程编程的时候,需要加锁。 最简单的就是ReentranLock,这玩意读写互斥,读读互斥; 换成ReentrantReadWriteLock,这玩意读读不互斥,但是读写互斥; 最后换成CopyOnWriteList,这玩意读读不会互斥,读写也不会互斥; MVCC差不多类似于Copy
这是历史学习笔记,可能存在过时或不完整的理解。
1. 是什么
- 多个事务并发访问同一份数据的时候,肯定会有冲突发生,那么怎么处理这种冲突呢?
- 主要有两种思想:
- 悲观锁机制:避免冲突发生,如Read/Write Locks,Two-Phase Locking
- 乐观锁机制:允许冲突发生,后续需要检测出冲突,如MVCC
- 用Java语言描述
- 使用Java进行多线程编程的时候,需要加锁。
- 最简单的就是ReentranLock,这玩意读写互斥,读读互斥;
- 换成ReentrantReadWriteLock,这玩意读读不互斥,但是读写互斥;
- 最后换成CopyOnWriteList,这玩意读读不会互斥,读写也不会互斥;
- MVCC差不多类似于CopyOnWriteList,只不过读的时候不仅是简单的复制当前数据,而是保存了一系列快照的版本
2. 悲观锁
在对数据进行修改之前加锁,修改后释放锁
2.1. 两阶段锁
- 在一个事务里,分加锁和解锁阶段。在事务开始时,锁的数量上升,在事务结束时才把所有的锁释放
2.1.1. 两阶段锁的缺点
2.2. 读写锁
- 读操作需要一个共享锁,写操作需要一个互斥锁
- 共享锁会阻塞写,但是允许其他读者获取同样的共享锁
- 共享锁阻塞写,允许并发读。互斥锁阻塞读和写
- 互斥锁则会同时阻塞读者和写者
2.2.1. 读写锁的缺点
- Readers block Writers, Writers block Readers
3. 乐观锁
3.1. MVCC
- 读不加锁,读写不冲突
- 写加锁,写写互斥
3.1.1. 常用实现方法
3.1.2. 回滚段保存旧数据
写新数据时,把旧数据转移到一个单独的地方,如回滚段中,其他人读数据时,从回滚段中把旧的数据读出来,如Oracle数据库和MySQL中的innodb引擎。
3.1.3. 旧数据不删除
写新数据时,旧数据不删除,而是把新数据插入。PostgreSQL就是使用的这种实现方法。
- 优点
- 无论事务进行了多少操作,事务回滚可以立即完成
- 数据可以进行很多更新,不必像Oracle和MySQL的Innodb引擎那样需要经常保证回滚段不会被用完,也不会像oracle数据库那样经常遇到“ORA-1555”错误的困扰
- 缺点
- 旧版本的数据需要清理。当然,PostgreSQL 9.x版本中已经增加了自动清理的辅助进程来定期清理
- 旧版本的数据可能会导致查询需要扫描的数据块增多,从而导致查询变慢
3.2. PostgreSQL的实现
3.3. MySQL InnoDB的实现
4. 参考
- 浅析MySQL的锁机制 - 哔哩哔哩
- How does MVCC (Multi-Version Concurrency Control) work - Vlad Mihalcea
- PgSQL · 特性分析 · MVCC机制浅析
- postgresql系列_MVCC机制以及锁机制理解 - 简书
- PostgreSQL的MVCC并发处理 | Piglei
- MYSQL MVCC实现原理 - 简书
- Two Phase Locking Protocol - GeeksforGeeks
- 两阶段锁协议 - 使命召唤 - 博客园
- 三级加锁协议_百度百科
- 详解MySQL两阶段加锁协议 - SegmentFault 思否
讨论
使用 GitHub 账号参与讨论,评论会保存在 GitHub Issues 中。在 GitHub 查看