Innodb的S lock和IS lock的范围问题!

时间:2021-03-02 07:32:23
Innodb的S lock和IS lock的范围问题!


Intention shared (IS): Transaction T intends to set S locks on individual rows in table R. 

Intention exclusive (IX): Transaction T intends to set X locks on those rows. 

The intention locking protocol is as follows: 

Before a given transaction can acquire an S lock on a given row, it must first acquire an IS or stronger lock on the table containing that row. 

Before a given transaction can acquire an X lock on a given row, it must first acquire an IX lock on the table containing that row. 


红色片段意思是,在对一行获得S lock之前,你必须对这个行所在的表能获取IS lock。在对一行获得X lock之前,你必须对这个行所在的表能获取IX lock。

问下:为什么S lock的范围比IS lock的小呢?为什么X lock的范围比IX要小呢?S lock是表共享锁啊 IS lock是表的行锁啊,红色部分是不是写反了,还是我理解错了?

6 个解决方案

#1


引用
不仅如此,InnoDB支持多间隔尺寸锁定,它允许记录锁和对整个表的锁共存。要使得多间隔尺寸级别的锁定实际化,额外类型的锁,被称为intention locks被使用。在InnoDB中,意图锁定是表锁定。 对于一个事务,意图锁定之后理想的是指明在该表中对一个行随后需要哪一类型的锁定(共享还是独占)。有两种意图锁被用在InnoDB中(假设事务T 在表R中要求一个已指出的类型的锁): 

·         意图共享(IS):事务T 意图给表T上单独的tuple设置S 锁定。 

·         意图独占(IX):事务T 意图给这些tuple设置X 锁定。 

意图锁协议如下: 

如果一个锁定与现在锁定兼容的话,它被授给一个委托事务。如果一个锁定与现存锁定冲突,它就不被授予一个委托事务。事务等待着直到冲突的现存锁定被释放掉。如果一个锁定请求与现存锁定相冲突,且不能被授予,因为它可能会导致死锁,一个错误产生。 

因此,意图锁定不阻碍任何东西,除了完全表请求(比如LOCK TABLES ... WRITE)。IX 和IS锁定的主要目的是显示某人正锁定一行,或将要在表中锁定一行。 

下列的例子演示当锁定请求可能会导致死锁之时一个错误会如何发生。例子中包括两个客户端A和B。 

首先客户端A创建一个包含一个行的表,然后开始一个事务。在这个事务内,A通过在共享模式选择行获得对行的S 锁定: 

mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)
 
mysql> INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec)
 
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+------+
| i    |
+------+
|    1 |
+------+
1 row in set (0.10 sec)
接着,客户端B开始一个事务并尝试从该表删除行: 

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
 
mysql> DELETE FROM t WHERE i = 1;
删除操作要求一个X 锁定。因为这个锁定不兼容客户端A持有的S锁定,所以X 锁定不被允许,所以请求进入对行及客户端阻挡的锁定请求队列。 

最后,客户端A也试图从表中删除该行: 

mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
因为客户端A需要一个X 锁定来删除该行,所以在这里发生死锁。尽管如此,锁定请求不被允许,因为客户端B已经有一个对X锁定的请求并且它正等待客户端A释放S锁定。因为客户端B之前对X 锁定的请求,被客户端A持有的S锁定也不能升级到X锁定。因此,InnoDB对客户端A产生一个错误,并且释放它的锁定。在那一点上,客户端B的锁定请求可以被许可,并且客户端B从表中删除行。 


·         在假设的事务可以获得对某假定行的S 锁定之前,它必须首先获得对包含该行的表的一个IS 或者更强的锁定。 

·         在假设的事务可以获得对某假定行的X 锁定之前,它必须首先获得对包含该行的表的一个IX 锁定。 

#2


引用 1 楼 acmain_chm 的回复:
引用不仅如此,InnoDB支持多间隔尺寸锁定,它允许记录锁和对整个表的锁共存。要使得多间隔尺寸级别的锁定实际化,额外类型的锁,被称为intention locks被使用。在InnoDB中,意图锁定是表锁定。 对于一个事务,意图锁定之后理想的是指明在该表中对一个行随后需要哪一类型的锁定(共享还是独占)。有两种意图锁被用在InnoDB中(假设事务T 在表R中要求一个已指出的类型的锁):

·  ……


狼头,你不要贴翻译啊,你贴了翻译,我还是不明白为什么呢?

#3


你能说说具体的原因吗?

#4


引用
·         在假设的事务可以获得对某假定行的S 锁定之前,它必须首先获得对包含该行的表的一个IS 或者更强的锁定。  
这句话有什么问题吗?

楼主可以举个例子说明一下你认为它为什么不正确吗?

#5


引用 4 楼 acmain_chm 的回复:
引用· 在假设的事务可以获得对某假定行的S 锁定之前,它必须首先获得对包含该行的表的一个IS 或者更强的锁定。 这句话有什么问题吗?

楼主可以举个例子说明一下你认为它为什么不正确吗?


我理解的 是IS的锁范围和权力比S lock大?
道理上来说,S是表锁 而IS是行锁,为什么这里的描述里面,给我的意思是IS lock要比S的范围和权力更大呢?

#6


建议举个例子,比如有表A,其中有记录1,2,3,4.。。。。。

#1


引用
不仅如此,InnoDB支持多间隔尺寸锁定,它允许记录锁和对整个表的锁共存。要使得多间隔尺寸级别的锁定实际化,额外类型的锁,被称为intention locks被使用。在InnoDB中,意图锁定是表锁定。 对于一个事务,意图锁定之后理想的是指明在该表中对一个行随后需要哪一类型的锁定(共享还是独占)。有两种意图锁被用在InnoDB中(假设事务T 在表R中要求一个已指出的类型的锁): 

·         意图共享(IS):事务T 意图给表T上单独的tuple设置S 锁定。 

·         意图独占(IX):事务T 意图给这些tuple设置X 锁定。 

意图锁协议如下: 

如果一个锁定与现在锁定兼容的话,它被授给一个委托事务。如果一个锁定与现存锁定冲突,它就不被授予一个委托事务。事务等待着直到冲突的现存锁定被释放掉。如果一个锁定请求与现存锁定相冲突,且不能被授予,因为它可能会导致死锁,一个错误产生。 

因此,意图锁定不阻碍任何东西,除了完全表请求(比如LOCK TABLES ... WRITE)。IX 和IS锁定的主要目的是显示某人正锁定一行,或将要在表中锁定一行。 

下列的例子演示当锁定请求可能会导致死锁之时一个错误会如何发生。例子中包括两个客户端A和B。 

首先客户端A创建一个包含一个行的表,然后开始一个事务。在这个事务内,A通过在共享模式选择行获得对行的S 锁定: 

mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)
 
mysql> INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec)
 
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+------+
| i    |
+------+
|    1 |
+------+
1 row in set (0.10 sec)
接着,客户端B开始一个事务并尝试从该表删除行: 

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
 
mysql> DELETE FROM t WHERE i = 1;
删除操作要求一个X 锁定。因为这个锁定不兼容客户端A持有的S锁定,所以X 锁定不被允许,所以请求进入对行及客户端阻挡的锁定请求队列。 

最后,客户端A也试图从表中删除该行: 

mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
因为客户端A需要一个X 锁定来删除该行,所以在这里发生死锁。尽管如此,锁定请求不被允许,因为客户端B已经有一个对X锁定的请求并且它正等待客户端A释放S锁定。因为客户端B之前对X 锁定的请求,被客户端A持有的S锁定也不能升级到X锁定。因此,InnoDB对客户端A产生一个错误,并且释放它的锁定。在那一点上,客户端B的锁定请求可以被许可,并且客户端B从表中删除行。 


·         在假设的事务可以获得对某假定行的S 锁定之前,它必须首先获得对包含该行的表的一个IS 或者更强的锁定。 

·         在假设的事务可以获得对某假定行的X 锁定之前,它必须首先获得对包含该行的表的一个IX 锁定。 

#2


引用 1 楼 acmain_chm 的回复:
引用不仅如此,InnoDB支持多间隔尺寸锁定,它允许记录锁和对整个表的锁共存。要使得多间隔尺寸级别的锁定实际化,额外类型的锁,被称为intention locks被使用。在InnoDB中,意图锁定是表锁定。 对于一个事务,意图锁定之后理想的是指明在该表中对一个行随后需要哪一类型的锁定(共享还是独占)。有两种意图锁被用在InnoDB中(假设事务T 在表R中要求一个已指出的类型的锁):

·  ……


狼头,你不要贴翻译啊,你贴了翻译,我还是不明白为什么呢?

#3


你能说说具体的原因吗?

#4


引用
·         在假设的事务可以获得对某假定行的S 锁定之前,它必须首先获得对包含该行的表的一个IS 或者更强的锁定。  
这句话有什么问题吗?

楼主可以举个例子说明一下你认为它为什么不正确吗?

#5


引用 4 楼 acmain_chm 的回复:
引用· 在假设的事务可以获得对某假定行的S 锁定之前,它必须首先获得对包含该行的表的一个IS 或者更强的锁定。 这句话有什么问题吗?

楼主可以举个例子说明一下你认为它为什么不正确吗?


我理解的 是IS的锁范围和权力比S lock大?
道理上来说,S是表锁 而IS是行锁,为什么这里的描述里面,给我的意思是IS lock要比S的范围和权力更大呢?

#6


建议举个例子,比如有表A,其中有记录1,2,3,4.。。。。。