MySQL 数据库锁定机制
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MySQL 数据库锁定机制
MySQL 数据库锁定机制简介
●行级锁定(row-level)
行级锁定最大的特点就是锁定对象的颗粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。
虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了。此外,行级锁定也最容易发生死锁。
●表级锁定(table-level)
和行级锁定相反,表级别的锁定是MySQL 各存储引擎中最大颗粒度的锁定机制。该锁定机制最大的特点是实现逻辑非常简单,带来的系统负面影响最小。所以获取锁和释放锁的速度很快。由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题。当然,锁定颗粒度大所带来最大的负面影响就是出现
锁定资源争用的概率也会最高,致使并大度大打折扣。
●页级锁定(page-level)
页级锁定是MySQL 中比较独特的一种锁定级别,在其他数据库管理软件中也并不是太常见。页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也同样是介于上面二者之间。另外,页级锁定和行级锁定一样,会发生死锁。
在数据库实现资源锁定的过程中,随着锁定资源颗粒度的减小,锁定相同数据量的数据所需要消耗的内存数量是越来越多的,实现算法也会越来越复杂。不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也随之提升。
在MySQL 数据库中,使用表级锁定的主要是MyISAM,Memory,CSV 等一些非事务性存储引擎,而使用行级锁定的主要是Innodb 存储引擎和NDB Cluster 存储引擎,页级锁定主要是BerkeleyDB 存储引擎的锁定方式。MySQL 的如此的锁定机制主要是由于其最初的历史所决定的。在最初,MySQL 希望设计一种完全独立于各种存储引擎的锁定机制,而且在早期的MySQL 数
据库中,MySQL 的存储引擎(MyISAM 和Momery)的设计是建立在“任何表在同一时刻都只允许单个线程对其访问(包括读)”这样的假设之上。但是,随着MySQL 的不断完善,系统的不断改进,在MySQL3.23 版本开发的时候,MySQL 开发人员不得不修正之前
的假设。因为他们发现一个线程正在读某个表的时候,另一个线程是可以对该表进行insert 操作的,只不过只能INSERT 到数据文件的最尾部。这也就是从MySQL 从3.23 版本开始提供的我们所说的Concurrent Insert。
当出现Concurrent Insert 之后,MySQL 的开发人员不得不修改之前系统中的锁定实现功能,但是仅仅只是增加了对Concurrent Insert 的支持,并没有改动整体架构。可是在不久之后,随着BerkeleyDB存储引擎的引入,之前的锁定机制遇到了更大的挑战。因为BerkeleyDB存储引擎并没有MyISAM 和Memory存储引
擎同一时刻只允许单一线程访问某一个表的限制,而是将这个单线程访问限制的颗粒度缩小到了单个page,这又一次迫使MySQL 开发人员不得不再一次修改锁定机制的实现。
由于新的存储引擎的引入,导致锁定机制不能满足要求,让MySQL 的人意识到已经不可能实现一种完全独立的满足各种存储引擎要求的锁定实现机制。如果因为锁定机制的拙劣实现而导致存储引擎的整体性能的下降,肯定会严重打击存储引擎提供者的积极性,这是MySQL 公司非常不愿意看到的,因为这完全不符合MySQL 的战略发展思路。所以工程师们不得不放弃了最初的设计初衷,在锁定实现机制中作出修改,允许存储引擎自己改变MySQL 通过接口传入的锁定类型而自行决定该怎样锁定数据。
各种锁机制分析
在整体了解了MySQL 锁定机制之后,这一节我们将详细分析MySQL 自身提供的表锁定机制和其他储引擎实自身实现的行锁定机制,并通过MyISAM存储引擎和Innodb存储引擎实例演示。
表级锁定
MySQL 的表级锁定主要分为两种类型,一种是读锁定,
另一种是写锁定。在MySQL 中,主要通过四个队列来维护这两种锁定:两个存放当前正在锁定中的读和写锁定信息,另外两个存放等待中的读写锁定信息,如下:
•Current read-lock queue (lock->read)
•Pending read-lock queue (lock->read_wait) •Current write-lock queue (lock->write)
•Pending write-lock queue (lock->write_wait)
当前持有读锁的所有线程的相关信息都能够在Current read-lock queue 中找到,队列中的信息按照获取到锁的时间依序存放。而正在等待锁定资源的信息则存放在Pending read-lock queue 里面,另外两个存放写锁信息的队列也按照上面相同规则来存放信息。虽然对于我们这些使用者来说MySQL 展现出来的锁定(表锁定)只有读锁定和写锁定这两种类型,但是在MySQL 内部实现中却有多达11 种锁定类型,由系统中一个枚举量(thr_lock_type)定义
读锁定
一个新的客户端请求在申请获取读锁定资源的时候,需要满足两个条件:
1、请求锁定的资源当前没有被写锁定;
2、写锁定等待队列(Pending write-lock queue)中没有更高优先级的写锁定等待;
如果满足了上面两个条件之后,该请求会被立即通过,并将相关的信息存入Current read-lock
queue 中,而如果上面两个条件中任何一个没有满足,都会被迫进入等待队列Pending read-lock queue中等