Mysql数据库锁定机制详细介绍(6)
虽然Innodb的锁定机制和Oracle有不少相近的地方,但是两者的实现确是截然不同的。总的来说就是Oracle锁定数据是通过需要锁定的某行记录所在的物理block上的事务槽上表级锁定信息,而Innodb的锁定则是通过在指向数据记录的第一个索引键之前和最后一个索引键之后的空域空间上标记锁定信息而实现的。Innodb的这种锁定实现方式被称为“NEXT-KEYlocking”(间隙锁),因为Query执行过程中通过过范围查找的华,他会锁定整个范围内所有的索引键值,即使这个键值并不存在。
间隙锁有一个比较致命的弱点,就是当锁定一个范围键值之后,即使某些不存在的键值也会被无辜的锁定,而造成在锁定的时候无法插入锁定键值范围内的任何数据。在某些场景下这可能会对性能造成很大的危害。而Innodb给出的解释是为了组织幻读的出现,所以他们选择的间隙锁来实现锁定。
除了间隙锁给Innodb带来性能的负面影响之外,通过索引实现锁定的方式还存在其他几个较大的性能隐患:
当Query无法利用索引的时候,Innodb会放弃使用行级别锁定而改用表级别的锁定,造成并发性能的降低;
当Quuery使用的索引并不包含所有过滤条件的时候,数据检索使用到的索引键所只想的数据可能有部分并不属于该Query的结果集的行列,但是也会被锁定,因为间隙锁锁定的是一个范围,而不是具体的索引键;
当Query在使用索引定位数据的时候,如果使用的索引键一样但访问的数据行不同的时候(索引只是过滤条件的一部分),一样会被锁定
Innodb 各事务隔离级别下锁定及死锁
Innodb实现的在ISO/ANSISQL92规范中所定义的ReadUnCommited,ReadCommited,RepeatableRead和Serializable这四种事务隔离级别。同时,为了保证数据在事务中的一致性,实现了多版本数据访问。
之前在第一节中我们已经介绍过,行级锁定肯定会带来死锁问题,Innodb也不可能例外。至于死锁的产生过程我们就不在这里详细描述了,在后面的锁定示例中会通过一个实际的例子为大家爱展示死锁的产生过程。这里我们主要介绍一下,在Innodb中当系检测到死锁产生之后是如何来处理的。
在Innodb的事务管理和锁定机制中,有专门检测死锁的机制,会在系统中产生死锁之后的很短时间内就检测到该死锁的存在。当Innodb检测到系统中产生了死锁之后,Innodb会通过相应的判断来选这产生死锁的两个事务中较小的事务来回滚,而让另外一个较大的事务成功完成。那Innodb是以什么来为标准判定事务的大小的呢?MySQL官方手册中也提到了这个问题,实际上在Innodb发现死锁之后,会计算出两个事务各自插入、更新或者删除的数据量来判定两个事务的大小。也就是说哪个事务所改变的记录条数越多,在死锁中就越不会被回滚掉。但是有一点需要注意的就是,当产生死锁的场景中涉及到不止Innodb存储引擎的时候,Innodb是没办法检测到该死锁的,这时候就只能通过锁定超时限制来解决该死锁了。另外,死锁的产生过程的示例将在本节最后的Innodb锁定示例中演示。
Innodb 锁定机制示例
mysql> create table test_innodb_lock (a int(11),b varchar(16)) engine=innodb;
Query OK, 0 rows affected (0.02 sec)
mysql> create index test_innodb_a_ind on test_innodb_lock(a);
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
- 上一篇:Mysql日志文件和日志类型介绍
- 下一篇:MySQL全局共享内存介绍