您的位置:首页 > 数据库 > MySQL

mysql数据库锁定机制

2013-09-16 11:12 274 查看
为了保证数据的一致完整性,任何一个数据库都存在锁定机制。锁定机制的优劣直接应想到一个数据库系统的并发处理能力和性能,所以锁定机制的实现也就成为了各种数据库的核心技术之一。下面将对 MySQL 的 Innodb 各自的锁定机制进行较为详细的分析。

总的来说, MySQL 各存储引擎使用了三种类型(级别)的锁定机制:行级锁定,页级锁定和表级锁定。下面我们先分析一下 MySQL 这三种锁定的特点和各自的优劣所在。

● 行级锁定( row-level )

行级锁定最大的特点就是锁定对象的颗粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了。此外,行级锁定也最容易发生死锁。

● 表级锁定( table-level )

和行级锁定相反,表级别的锁定是 MySQL 各存储引擎中最大颗粒度的锁定机制。该锁定机制最大的特点是实现逻辑非常简单,带来的系统负面影响最小。所以获取锁和释放锁的速度很快。由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题。当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并大度大打折扣。

● 页级锁定( page-level )

页级锁定是 MySQL 中比较独特的一种锁定级别,在其他数据库管理软件中也并不是太常见。页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也同样是介于上面二者之间。另外,页级锁定和行级锁定一样,会发生死锁。

在数据库实现资源锁定的过程中,随着锁定资源颗粒度的减小,锁定相同数据量的数据所需要消耗的内存数量是越来越多的,实现算法也会越来越复杂。不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也随之提升。

在 MySQL 数据库中,使用表级锁定的主要是 MyISAM , Memory , CSV 等一些非事务性存储引擎,而使 用行级锁定的主要是 Innodb 存储引擎和 NDB Cluster 存储引擎,页级锁定主要是 BerkeleyDB 存储引擎的 锁定方式。

锁定机制分析:

表级锁定

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)

Innodb 锁定模式及实现机制

Innodb 的锁定机制和 Oracle 数据库有不少相似之处。 Innodb 的行级锁定同样分为两种 类型,共享锁和排他锁,而在锁定机制的实现过程中为了让行级锁定和表级锁定共存, Innodb 也同样使用了意向锁(表级锁定)的概念,也就有了意向共享锁和意向排他锁这两种。当一个事务需要给自己需要的某个资源加锁的时候,如果遇到一个共享锁正锁定着自己需要的资源的时候,自己可以再加一个共享锁,不过不能加排他锁。但是,如果遇到自己需要锁定的资源已经被一个排他锁占有之后,则只能等待该锁定释放资源之后自己才能获取锁定资源并添加自己的锁定。
而意向锁的作用就是当一个事务在需要获取资源锁定的时候,如果遇到自己需要的资源已经被排他锁占用的时候,该事务可以需要锁定行的表上面添加一个合适的意向锁。如果自己需要一个共享锁,那么就在表上面添加一个意向共享锁。而如果自己需要的是某行(或者某些行)上面 添加一个排他锁的话,则先在表上面添加一个意向排他锁。意向共享锁可以同时并存多个,但是意向排他锁同时只能有一个存在。所以,可以说 Innodb 的锁定模式实际上可以分为四种:共享锁( S ),排他锁( X ),意向共享锁( IS )和意向排他锁( IX ),我们可以通过以下表格来总结上面这四种所的共存逻辑关系:



除了间隙锁给 Innodb 带来性能的负面影响之外,通过索引实现锁定的方式还存在其他几个较大的性能隐患:

● 当 Query 无法利用索引的时候, Innodb 会放弃使用行级别锁定而改用表级别的锁定,造成并发性能的降低;

● 当 Quuery 使用的索引并不包含所有过滤条件的时候,数据检索使用到的索引键所只想的数据可能有部分并不属于该 Query 的结果集的行列,但是也会被锁定,因为间隙锁锁定的是一个范围,而不是具体的索引键;

● 当 Query 在使用索引定位数据的时候,如果使用的索引键一样但访问的数据行不同的时候(索引只是过滤条件的一部分),一样会被锁定

在 Innodb 中当系检测到死锁产生之后是如何来处理的:

在 Innodb 的事务管理和锁定机制中,有专门检测死锁的机制,会在系统中产生死锁之后的很短时间内就检测到该死锁的存在。当 Innodb 检测到系统中产生了死锁之后, Innodb 会通过相应的判断来选这 产生死锁的两个事务中较小的事务来回滚,而让另外一个较大的事务成功完成。那 Innodb 是以什么来为标准判定事务的大小的呢? MySQL 官方手册中也提到了这个问题,实际上在 Innodb 发现死锁之后,会计算出两个事务各自插入、更新或者删除的数据量来判定两个事务的大小。也就是说哪个事务所改变的记录条数越多,在死锁中就越不会被回
滚掉。但是有一点需要注意的就是,当产生死锁的场景中涉及到不止Innodb 存储引擎的时候, Innodb 是没办法检测到该死锁的,这时候就只能通过锁定超时限制来解决该死锁了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: