MySQL原理与优化意向锁,IS,IX

先来看一种应用场景,当有两个线程A和B分别访问一张表。

线程A:针对表中的一条语句进行update操作,假设根据记录的id更新记录,此时开启的事务会对这条记录加行锁。

线程B:如果需要进行锁表的操作,例如:locktables[table_name]read/write,也就是对表加上读写锁。在加表锁之前需要检查行记录是否加锁,如果有加锁就需要等待锁释放以后再进行表锁的后续操作。此时检查行锁的操作,就需要从表的第一行向下逐一进行,直到最后一行记录。

大家知道对表进行扫描操作的效率是非常低的,此时就引入了意向锁。

意向锁就是避免DML在执行时,加的行锁和表锁发生冲突而引入的,使得表锁不用加茶妹行数据是否加锁,使用意向锁来减少表锁的检查。

如上图所示,在引入意向锁之后按照这个步骤进行加锁

线程A对表中的某条记录加行锁。同时对表加上意向锁。当线程B对表加表锁的时候,发现线程A加的意向锁,会将表锁与意向锁进行对比。如果两锁互斥:等待意向锁释放执行表锁的操作,如果两锁不互斥:就执行表锁的操作。

按照这个执行步骤,线程B就不用去对整张表进行全表扫描了。

意向锁分为两类:

意向共享锁:IS,select...lockinsharemode

意向排他锁:IX,insert、update、delete、select...forupdate

从上面的语句可以看出意向共享锁主要对应查询操作,意向排他锁对应更新操作。

意向锁与表锁的互斥情况:

意向共享锁:与表共享锁(read)兼容,与表锁排他锁(write)互斥。

意向排他锁:与表共享锁(read)以及排他锁(write)都互斥。意向锁之间不会互斥。

意向锁对记录进行读操作的时候,表锁可以加读锁,也就是其他的线程可以读表,但是不能写表。当意向锁对记录进行写入操作的时候,表锁线程不能对表的数据进行读和写的操作,需要等到意向排他锁对应的事务提交以后才能,进行后续操作。

下面来看两个例子

第一个例子

开启线程,通过在sql语句后面加上lockinsharemode,表示对表加上意向共享锁

begin;

select*fromcoursewhereid=2lockinsharemode;

通过sql语句查询意向锁的情况

selectobject_schema,object_name,index_name,lock_type,lock_mode,lock_datafromperformance_schema.data_locks;

从上图可以看到select语句在record(行)上加了共享锁(read),在table(表)上加了IS共享锁。

打开另外一个客户端执行如下语句

locktablescourseread;

上图可见,此时加锁是成功的说明意向共享锁和表共享锁(read)是兼容的。

接着加上表的互斥锁write

locktablescoursewrite;

发现光标闪动,说明线程阻塞了。因为意向共享锁和表排他锁(write)是互斥的

回到第一个事务,将其


转载请注明:http://www.aierlanlan.com/rzgz/1729.html