NOTE

数据库锁

1. 是什么 多个事务并发访问同一份数据的时候,肯定会有冲突发生,那么怎么处理这种冲突呢? 主要有两种思想: 1. 悲观锁机制:避免冲突发生,如Read/Write Locks,Two Phase Locking 2. 乐观锁机制:允许冲突发生,后续需要检测出冲突,如MVCC 用Java语言描述 使用Java进行多线程编程的时候,需要加锁。 最简单的就是ReentranLock,这玩意读写互斥,读读互斥; 换成ReentrantReadWriteLock,这玩意读读不互斥,但是读写互斥; 最后换成CopyOnWriteList,这玩意读读不会互斥,读写也不会互斥; MVCC差不多类似于Copy

Database创建于 更新于 约 2 分钟读完historical

这是历史学习笔记,可能存在过时或不完整的理解。

1. 是什么

  • 多个事务并发访问同一份数据的时候,肯定会有冲突发生,那么怎么处理这种冲突呢?
  • 主要有两种思想:
    1. 悲观锁机制:避免冲突发生,如Read/Write Locks,Two-Phase Locking
    2. 乐观锁机制:允许冲突发生,后续需要检测出冲突,如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. 参考

讨论

使用 GitHub 账号参与讨论,评论会保存在 GitHub Issues 中。在 GitHub 查看