数据库锁定机制简单来说就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问时变得有序(不会使得数据的完整性和一致性被破坏)所设计的一种规则。
MySQL的各种存储引擎使用了三种级别的锁机制: 行级锁,页级锁,表级锁。
- 行级锁 row-level
- 锁粒度最小
- 实现逻辑复杂
- 发生锁定资源争抢的概率小
- 提高应用程序的并发处理能力
- 表级锁 table_level
- 锁粒度最大
- 实现逻辑简单
- 发生锁定资源争抢概率大
- 降低应用程序的并发处理能力
- 由于表级锁一次会锁定整个表,所以很好的避免死锁问题
- 页级锁定 page-level
- 锁粒度介于表级锁和行级锁之间
- 发生锁定资源争抢的概率介于表级锁和行级锁之间
- 应用程序的并发处理能力介于表级锁和行级锁之间
- 会发生死锁
MySQL中,使用表级锁的主要是MyISAM,Memory,CSV等一些非事务性存储引擎,使用行级锁的主要是 Innodb 存储引擎和 NDB Cluster 存储引擎,页级锁主要是 BerkeleyDB 存储引擎。
MySQL锁定机制演变:
最初,MySQL 希望设计一种完全独立于各种存储引擎的锁机制,而且早期的 MySQL 数据库中,MySQL 的存储引擎 MyISAM , Memory ,的设计是建立在 “任何表在任何时刻都只允许单个线程对其访问(包括读操作)”这个假设之上。在 MySQL 3.23 版本开发时,MySQL 开发人员不得不修正之前的假设,开发人员发现一个线程正在读取某个表时,另一个线程可以对该表进行 INSERT 操作,只不过只能 INSERT 到数据文件的最尾部。这就是从 MySQL 3.23 版本开始我们所说的 Concurrent Insert 。
此时并没有对整体架构进行改动,随着 BerkeleyDB 存储引擎的引入,之前的锁定机制受到了挑战。因为 BerkeleyDB 没有 MyISAM , Memory 的同一时刻单线程访问一个表的限制,而是将这个限制控制到了单个 page 级别,这就迫使 MySQL 再一次修改锁定机制。
由于新的存储引擎的引入,导致锁定机制不能满足要求。让 MySQL 意识到已经不可能实现一种完全独立的满足各种存储引擎要求的锁定机制。所以放弃了最初设计的初衷,在锁定实现机制中做出修改,允许存储引擎自己改变 MySQL 通过接口传入的锁定类型而自行决定该怎样锁定数据。