悲观锁 lock_only_if_exists 参数的场景有哪些呢?

TIKV 的代码中,PessimisticLock 接口:

从注释中可以看到,一般有两种场景:
有 write 记录的时候才需要加锁
不管有没有 write 记录都需要加锁

这两个场景都对应 sql 事务的哪些情况呢?
我目前猜测:
insert/ select for update/ update/ delete 语句感觉是无论有没有记录都需要加锁

不太清楚没有记录就不需要加锁的场景是什么呢?

高并发环境适用悲观锁

乐观锁。

我想问的是悲观锁请求过程中的 lock_only_if_exists 参数哪些场景使用,而不是悲观锁哪些场景使用

  1. 数据更新操作:当需要更新某个数据记录时,可以先查询该记录是否存在,如果存在,则使用 lock_only_if_exists 参数来锁定该记录,以确保在更新过程中不会被其他事务修改。
  2. 资源预订/分配:在需要预订或分配资源时,可以先检查资源的可用性,如果资源存在且可用,则使用 lock_only_if_exists 参数来锁定该资源,以防止其他请求同时操作同一资源。
  3. 订单处理:在处理订单或交易时,可以先检查订单状态或库存情况,如果订单存在或库存足够,则使用 lock_only_if_exists 参数来锁定相关数据,以确保订单处理过程中数据的完整性。
  4. 并发控制:在需要对数据进行并发控制的场景下,可以使用 lock_only_if_exists 参数来实现对特定数据的精确加锁,避免对整个数据表或数据集进行加锁,提高系统并发性能。

select * from t for update;有记录加锁没记录不加锁

lock_only_if_exists参数是在TiDB的悲观锁实现中的一个选项,表明TiDB在加悲观锁时只有在目标行存在时才加锁,使用场景大概包括:
1. 外键约束检查:在处理外键约束时,TiDB 可能需要对参照的行加锁以确保外键约束的正确性。在这种情况下,如果参照的行不存在,就没有必要加锁,当然Tidb不进行强制外键约束检查,这一点可以忽略。
2. SELECT FOR UPDATE 语句:在执行 SELECT FOR UPDATE 语句时,用户可能只希望对实际存在的行加锁。通过指定 lock_only_if_exists,TiDB 可以只对查询到的存在的行加悲观锁,而不是对所有可能的行(例如,范围查询中的间隙)都加锁。
3. 性能优化: 在读已提交的隔离级别下,某些查询可能只需要检查锁是否存在,而不需要实际获取锁。使用 lock_only_if_exists 可以避免不必要的锁等待,从而提高查询性能
4. 减少锁的范围:在某些场景下,为了减少锁的范围和锁的持有时间,只对存在的行加锁可以减少锁的影响,提高并发性能。
5. 避免死锁:在某些情况下,如果多个事务互相等待对方释放锁,就可能发生死锁。使用 lock_only_if_exists可以让事务在检测到锁不存在时立即返回,从而避免死锁的发生。

select * from t where id=1 for update;
语句表中没有 id = 1 的记录场景下,
如果不加锁的话,是否需要担心有并发事务 insert 了一条 id = 1 的记录呢

这个要看事物隔离级别,和悲观事物和乐观事物,你可以配合做一下试验

1 个赞

此话题已在最后回复的 60 天后被自动关闭。不再允许新回复。