mysql 行锁升级为表锁

行锁升级为表锁

总所周知,MySQL 的 InnoDB 存储引擎支持事务,支持行级锁(InnoDB 的行锁是通过给索引项加锁实现的)。得益于这些特性,数据库支持高并发。如果 InnoDB 更新数据使用的不是行锁,而是表锁呢?是的,InnoDB 其实很容易就升级为表锁,届时并发性将大打折扣了。

常用的索引有三类:主键、唯一索引、普通索引。主键不由分说,自带最高效率的索引属性;唯一索引指的是该属性值重复率为0,一般可作为业务主键,例如:学号;普通索引与前者不同的是,属性值的重复率大于0,不能作为唯一指定条件,例如:学生姓名。

下面我们来看下使用索引与不使用索引的情况下加锁会不会升级为表锁。


在不使用索引的情况下加锁

事务顺序事务1事务2
begin;
select * from user where age = 17 for update;
begin;
select * from user where age = 15 for update;
commit;commit;

运行结果:

在这里插入图片描述

在不给 age 字段加索引的情况下进行排它锁的加锁操作,可以看到尽管加锁的数据是不同的,但是事务2在加锁时出现了锁等待现象。说明此时事务1从行级锁升级为表锁,导致事务2在给 age = 15 的数据加锁时出现了锁等待现象。


在使用普通索引的情况进行加锁

alter table user add index idx_age(age); --给age字段加个索引

事务顺序事务1事务2
begin;
select *from user where age = 17 for update;
begin;
select * from user where age = 15 for update;
commit;commit;

运行结果:

在这里插入图片描述
在加了索引之后,再一次进行以上操作。可以看到,user 表不在进行表锁,那是因为行锁是建立在索引字段的基础上,如果行锁锁定的列表锁索引列则会升级为表锁。


范围性查询测试

事务顺序事务1事务2
begin;
select * from user where age between 13 and 16 for update;
begin;
select * from user where age = 17 for update;
commit;commit;

运行结果:

在这里插入图片描述
当要进行加锁的数据不确定时,也一样会升级为表锁。

总结:
行锁是建立在索引的基础上。
普通索引的数据重复率过高导致索引失效,行锁升级为表锁。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: MySQL中的锁是指在执SQL语句时对某一数据进锁定,以防止其他会话对该修改或删除。当一个会话对某一更新或删除操作时,MySQL会为该加上级锁,直到事务提交或回滚后才会释放。 在什么情况下升级为表锁? 当多个会话同时对表中的不同更新或删除操作时,级锁可能会导致死锁问题,影响数据库性能。此时,MySQL会自动将锁升级为表锁,以避免死锁问题的发生。因此,当出现大量并发更新或删除操作时,MySQL可能会自动升级为表锁。 此外,也可以通过手动设置锁级别来控制MySQL的锁为。例如,可以将锁级别设置为READ COMMITTED(读取已提交),在该级别下,MySQL会对读取的数据共享锁,对更新和删除的数据排它锁。如果需要对整个表进操作,可以使用表级锁或表级共享锁。 ### 回答2: 在MySQL中,锁和表锁是两种不同级别的锁机制。通常情况下,MySQL会根据需要自动升级为表锁。主要有以下几种情况: 1. 锁定范围超出了级别:当事务需要锁定的数超过了MySQL设置的阈值时,MySQL会自动将锁升级为表锁。这样做是为了减少锁的数量,提高并发性能。 2. 不同事务涉及到的相互冲突:如果不同的事务需要锁定同一张表中的不同,并且它们之间有冲突,那么MySQL会将锁升级为表锁。这个冲突可能是由于事务之间的读写操作或写入冲突引起的。 3. 显式设置表锁:在一些特定情况下,我们可能需要显式地将锁升级为表锁。这可以通过使用LOCK TABLES语句来实现。但是,这个操作需要小心使用,因为表锁会限制其他事务的读写操作。 需要注意的是,MySQL锁和表锁是根据实际情况进升级的,并不是所有的锁都会自动升级为表锁。升级为表锁的条件是符合上述所述的情况。在实际应用中,我们需要根据具体的业务需求和场景,合理选择和使用锁和表锁,以提高数据库的并发性和性能。 ### 回答3: MySQL中的锁升级为表锁是在以下情况下发生的: 1. 事务涉及到的数量超过了innodb_locks_unsafe_for_binlog的阈值,默认值是30000。如果一个事务涉及到的数超过了这个阈值,锁就会自动升级为表锁。这是为了防止由于级锁过多导致事务无法进的情况。 2. 出现了锁等待超时。当一个事务等待锁的时间超过了设置的超时时间(innodb_lock_wait_timeout),锁也会自动升级为表锁。这个超时时间可以在MySQL的配置文件中进设置。 需要注意的是,锁升级为表锁可能会导致并发性能下降。因为表级锁会导致其他事务需要等待,无法并发执。因此,在设计数据库时,需要合理使用级锁和表级锁。对于并发读多写少的场景,可以使用锁来提高并发性能。对于并发写多的场景,可以考虑使用表锁来避免锁冲突。此外,可以使用合理的索引设计来减少锁竞争,提高并发性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值