意向锁
意向锁的概念
意向锁是InnoDB自动添加的一种锁,不需要用户去干预。
是数据库中的一种表级锁,一个事务要给一个资源加锁时,必须要先获取到对应类型的意向锁之后,才可以给这个资源加上自己想要的共享锁或者排他锁(不论是行级还是表级的共享/排他锁,都是需要先获取到意向共享/排他锁)。
意向锁并不是真正的锁,而是为了协调事务对表中行的锁定请求而引入的一个概念。
意向锁业的两个类型
意向共享锁(Intention Shared Lock,IS锁): 表示事务有获取到表的表级或行级共享锁的意向。
意向排他锁(Intention Exclusive Lock,IX锁): 表示事务有获取到表的表级或行级排它锁的意向。
注意:获取意向锁只是表示事务有获取到共享锁和排它锁的意向意图,而不是表示获取了意向锁,就是实际锁定了任何行或表。
意向锁是互相兼容的,不会互斥。
说明案例
前提:
如果事务A需要修改user表的id(有索引)为 '1' 的数据行,则事务A会给这行数据加上一个行级排他锁,和一个意向排他锁。
场景一:
此时如果事务B想修改user表的name(无索引)为 '张三' 的数据行,则事务B就需要给user表加上表级排他锁,但是在获取表级排他锁之前,还需要获取意向排他锁,然后就发现已经有事务A获取了意向排他锁,则事务B可以直接阻塞等待了,不再需要往下尝试判断能否获取到表级排他锁。
意向锁通过这种前置判断的操作,很好的解决了行锁与表锁共存时的事务隔离性问题。
场景二:
此时如果事务B想修改user表的id(有索引)为 '2' 的数据行,则事务B就需要先获取意向排他锁,虽然此时事务A已经持有了user表的意向排他锁,但是事务B仍旧可以去获取user表的意向排他锁,因为 ++意向锁是互相兼容的,不会互相排斥++ (上文也有说到),获取到意向排他锁之后,再去判断id为2的数据行是否有共享锁和排他锁,发现没有,则事务B持有到user表id为2的数据行的行级排他锁。
总结
行表头为事务A已经获取的锁
列表头为事务B能否获取的锁
意向共享锁 | 意向排他锁 | 表级共享锁 | 表级排他锁 | 行级共享锁 | 行级排它锁 | |
---|---|---|---|---|---|---|
意向共享锁 | 兼容 | 兼容 | 兼容 | 不兼容 | 兼容 | 不兼容 |
意向排他锁 | 兼容 | 兼容 | 不兼容 | 不兼容 | 不兼容 | 不兼容 |
表级共享锁 | 兼容 | 不兼容 | 兼容 | 不兼容 | 兼容 | 不兼容 |
表级排他锁 | 不兼容 | 不兼容 | 不兼容 | 不兼容 | 不兼容 | 不兼容 |
行级共享锁 | 兼容 | 额外讨论-1 | 兼容 | 不兼容 | 兼容 | 同行不兼容 不同行兼容 |
行级排它锁 | 额外讨论-2 | 额外讨论-1 | 不兼容 | 不兼容 | 同行不兼容 不同行兼容 | 同行不兼容 不同行兼容 |
额外讨论-1
事务A获取了 意向排他锁
,事务B能否获取 行级共享锁
或 行级排他锁
需要继续往下去判断,判断事务A的排他锁是表锁还是行锁,
如果是表锁,则事务B不能再加行级共享锁;
如果是行锁,则继续判断事务B要加行级共享锁的行是否被事务A或其他事务加了行级排它锁,如果加了,则事务B不能再加行级共享锁,如果这一行没加行级排他锁,则事务B可以加上行级共享锁(行锁:同行不兼容,不同行兼容)。
额外讨论-2
事务A获取了 意向共享锁
,事务B能否获取 行级排他锁
需要继续往下去判断,判断事务A的共享锁是表锁还是行锁,
如果是表锁,则事务B不能再加行级排他锁;
如果是行锁,则继续判断事务B要加行级排他锁的行是否被事务A或其他事务加了行级共享锁,如果加了,则事务B不能再加行级排他锁,如果这一行没加行级共享锁,则事务B可以加上行级排他锁(行锁:同行不兼容,不同行兼容)。
关注我,我将持续输出Java常用相关技术文章。