MySQL高级锁之意向锁_mysql意向锁

  • 方式1):判断表中的每一行是否已被行锁锁住(效率非常低)
  • 方式2):直接判断整表是否已被其他事务用表锁锁表

意向锁就是在这个时候发挥作用的,有了意向锁。在意向锁存在的情况下,事务A必须先申请表的意向共享锁(表级锁),成功后再申请一行的行锁。下次事务B去申请表的排它锁时,发现有意向共享锁,说明表中肯定有某些行被锁住了,事务B将会阻塞;
当我们需要加一个排他锁时,需要根据意向锁去判断表中有没有数据行被锁定;
(1)如果意向锁是行锁,则需要遍历每一行数据去确认;
(2)如果意向锁是表锁,则只需要判断一次即可知道有没数据行被锁定,提升性能。
因此,意向锁是表级别的;

2.1.2 意向锁的应用

测试IS和IX之间是共享的,意向锁(共享和排他)和表级别的X锁是冲突的;

  • 测试数据:
drop table if exists test4;

CREATE TABLE `test4`  (
  `id` int(11) NOT NULL AUTO\_INCREMENT,
  `name` varchar(255) ,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = innodb ;

INSERT INTO test4 VALUES(1,'aa');
INSERT INTO test4 VALUES(2,'bb');

  • 案例:
session-01session-02
begin;
begin;
select * from test4 where id=1 lock in share mode; – 申请这行的共享锁
select * from test4 for update; – 申请整表的排它锁(阻塞)

示意图:

Tips:有了意向锁,在事务B申请表的排它锁时,MySQL就可以很轻松判断这个表中是否记录被锁住了;

2.1.3 意向锁与X/S锁之间的关系

我们之前说过,事务A在锁定一行记录时,会先加上意向锁(表级别),之后事务B申请整个表的排它锁时,先加上意向排它锁,发现该表已经被加上意向锁了,但是意向锁之间是兼容的,可以申请成功,之后事务B尝试申请表级别排它锁,申请锁失败,被阻塞;因为表级别的排它锁和意向锁是冲突的;
按照这个逻辑来说,如果此时事务B申请的是行锁呢(而且并不是事务A锁定的那一条记录)?根据意向锁是表锁的原则,那么此时事务B也会申请意向排它锁(表级别),这样下来不是会造成事务B阻塞吗?但事实并不是这样;因为所有的意向锁之间都是兼容的!
测试意向锁和行级S/X锁是兼容的,并且所有的意向锁直接都是兼容的

  • 测试案例:
session-01session-02
begin;
begin;
select * from test3 where id=1 lock in share mode; – 申请这行的共享锁
select * from test3 where id=2 for update; – 申请这行的排它锁

示意图:

Tips:意向锁与行级的S/X锁之间的兼容的
关系如下:

XIXSIS
X(表级)ConflictConflictConflictConflict
S(表级)ConflictConflictCompatibleCompatible
X(行级)Conflict/CompatibleCompatibleConflict/CompatibleCompatible
S(行级)Conflict/CompatibleCompatibleCompatibleCompatible

注意:这里的排他 / 共享锁指的都是表锁!意向锁不会与行级的共享 / 排他锁互斥
上了行级X锁后,行级X锁不会因为有别的事务上了IX而堵塞,一个mysql是允许多个行级X锁同时存在的,只要他们不是针对相同的数据行。

笔者福利

以下是小编自己针对马上即将到来的金九银十准备的一套“面试宝典”,不管是技术还是HR的问题都有针对性的回答。

有了这个,面试踩雷?不存在的!

回馈粉丝,诚意满满!!!




p9AzP1cS-1719168995676)]
[外链图片转存中…(img-apTy1Hvx-1719168995677)]
[外链图片转存中…(img-gW64gZ3T-1719168995677)]

Redis并没有直接实现意向锁的功能。意向锁是一种用于协调并发事务的机制,用于在事务执行之前确定是否需要获取。在Redis中,可以通过使用分布式来实现类似的功能。 分布式是一种在分布式系统中实现互斥访问的机制。在Redis中,可以使用SETNX命令(SET if Not eXists)来实现分布式。具体步骤如下: 1. 客户端尝试执行SETNX命令,将一个特定的键作为的标识,并设置一个过期时间,以防止被永久占用。 2. 如果SETNX命令返回1,表示成功获取到,客户端可以执行需要互斥访问的操作。 3. 如果SETNX命令返回0,表示已经被其他客户端占用,客户端可以选择等待一段时间后重新尝试获取,或者放弃执行操作。 以下是一个使用Redis实现分布式的示例代码: ```python import redis import time def acquire_lock(conn, lock_name, acquire_timeout=10, lock_timeout=10): end_time = time.time() + acquire_timeout lock = False while time.time() < end_time and not lock: lock = conn.setnx(lock_name, "LOCKED") if lock: conn.expire(lock_name, lock_timeout) return lock def release_lock(conn, lock_name): conn.delete(lock_name) # 使用示例 conn = redis.Redis(host='localhost', port=6379, db=0) lock_name = "my_lock" if acquire_lock(conn, lock_name): try: # 执行需要互斥访问的操作 print("执行操作...") finally: release_lock(conn, lock_name) else: print("获取失败") ``` 请注意,以上示例代码仅为演示分布式的基本原理,实际使用时还需要考虑更多的情况,如的超时处理、异常情况下的释放等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值