diff --git a/docs/05.MySQL/QA.md b/docs/05.MySQL/QA.md index d1c6bfa..4c0f06c 100644 --- a/docs/05.MySQL/QA.md +++ b/docs/05.MySQL/QA.md @@ -120,19 +120,31 @@ SELECT FORMAT(2.7895, 2); #2.79 多个查询需要在同一时刻修改数据,会产生并发控制的问题。使用锁可以有效解决这个问题 +#### 乐观锁与悲观锁 + +我们都知道锁的种类一般分为乐观锁和悲观锁两种,InnoDB 存储引擎中使用的就是悲观锁,而按照锁的粒度划分,也可以分成行锁和表锁。 + +- 乐观锁是一种思想,它其实并不是一种真正的『锁』,它会先尝试对资源进行修改,在写回时判断资源是否进行了改变,如果没有发生改变就会写回,否则就会进行重试,在整个的执行过程中其实都没有对数据库进行加锁; +- 悲观锁就是一种真正的锁了,它会在获取资源前对资源进行加锁,确保同一时刻只有有限的线程能够访问该资源,其他想要尝试获取资源的操作都会进入等待状态,直到该线程完成了对资源的操作并且释放了锁后,其他线程才能重新操作资源; + +虽然乐观锁和悲观锁在本质上并不是同一种东西,一个是一种思想,另一个是一种真正的锁,但是它们都是一种并发控制机制。 + +![体系结构图](./assets/Optimistic-Pessimistic-Locks.jpg) + +乐观锁不会存在死锁的问题,但是由于更新后验证,所以当冲突频率和重试成本较高时更推荐使用悲观锁,而需要非常高的响应速度并且并发量非常大的时候使用乐观锁就能较好的解决问题,在这时使用悲观锁就可能出现严重的性能问题;在选择并发控制机制时,需要综合考虑上面的四个方面(冲突频率、重试成本、响应速度和并发量)进行选择。 + #### 读写锁 -- 共享锁:同一时刻可以同时读取同一个资源 -- 排他锁:一个写锁会阻塞其他的写锁和读锁 +- 共享锁(读锁):允许事务对一条行数据进行读取; +- 互斥锁(写锁,也叫排他锁):允许事务对一条行数据进行删除或更新; #### 锁粒度 - 表锁:开销最小,对表进行写操作,需要获得写锁,会阻塞该表的所有读写操作 - 行级锁:最大锁开销,可以最大程度地支持并发处理 -#### 乐观锁 +拓展阅读 [《『浅入浅出』MySQL 和 InnoDB》](https://draveness.me/mysql-innodb/) -#### 悲观锁 ### 事务 @@ -273,4 +285,4 @@ MySQL 单表容量在`500万`左右,性能处于最佳状态,此时,MySQL ### my.cnf 配置 -### 慢查询 \ No newline at end of file +### 慢查询 diff --git a/docs/05.MySQL/assets/Optimistic-Pessimistic-Locks.jpg b/docs/05.MySQL/assets/Optimistic-Pessimistic-Locks.jpg new file mode 100644 index 0000000..6cfff4a Binary files /dev/null and b/docs/05.MySQL/assets/Optimistic-Pessimistic-Locks.jpg differ