首页 > 数据库 >mysql什么时候会行锁升级为表锁(转)

mysql什么时候会行锁升级为表锁(转)

时间:2023-06-30 20:33:57浏览次数:34  
标签:事务 加锁 会行锁 age 为表锁 索引 user 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;

运行结果:
image

在不给 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;

运行结果:
image
在加了索引之后,再一次进行以上操作。可以看到,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;

运行结果:
image
当要进行加锁的数据不确定时,也一样会升级为表锁。

总结:

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

原文链接:https://blog.csdn.net/qq_39408664/article/details/118937047

标签:事务,加锁,会行锁,age,为表锁,索引,user,mysql
From: https://www.cnblogs.com/yliunyue/p/17517757.html

相关文章

  • Mysql基础篇(二)之函数和约束
    一.函数Mysql中的函数主要分为四类:字符串函数、数值函数、日期函数、流程函数1.字符串函数常用函数如下:函数功能CONCAT(S1,S2,......Sn)字符串拼接,将S1,S2,.....Sn拼接成一个字符串LOWER(str)将字符串str全部转为小写UPPER(str)将字符串str全部转为大写......
  • MySQL分区表各个分区如何创建在不同目录
     MySQL分区表各个分区如何创建在不同目录 分区表无法创建在共享表空间(系统表空间,通用表空间),只能放在不同的独立表空间上。以下是分区表不同分区放在不同目录的示例:CREATETABLEzkm.employees(idINTNOTNULL,fnameVARCHAR(30),lnameVARCHAR(30),......
  • MySQLINNODB表空间分类简单介绍
     MySQLINNODB表空间分类简单介绍 从功能上看INNODB表空间共以下几种:系统表空间File-Per-Table表空间通用表空间Undo表空间临时表空间 从共享与否角度看上边提到的五种表空间可以这么归类。共享表空间独立表空间官档中有明确提到“共享表空间”这个说法:http......
  • 高手都是如何做 Mysql 慢 SQL 优化
    tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。......
  • Docker安装MySQL8.0
    安装拉取镜像默认拉取最新版本的镜像$dockerpullmysql如果要指定版本,使用下面的命令$dockerpullmysql:8.0.16创建数据目录和配置文件 在宿主机创建放置mysql的配置文件的目录和数据目录,并且进行授权$mkdir-p/usr/mysql/conf/usr/mysql/data$chmod-R755/usr/m......
  • MySQL 知识合集
    脏页脏页的来历一言蔽之,脏页就是插入和更新的数据锁保存的对应的内存(缓存)页脏页的刷新脏页的刷新采用定时+阈值触发+关闭前 相关参数innodb_page_cleanersinnodb_buffer_pool_instancesinnodb_lru_scan_depthinnodb_nax_dirty_pages_pct是否刷新脏页......
  • mysql 如何 使用一个字符串来进行排序
    如果想进行对一个字段进行排序,但是这个字段却不是int类型,适应varchar类型怎么办呢?常用的方式:给字符字段加上0,举例:1:假设scoreRate是一个varchar类型,并且值是一个百分(90%)的数据格式.要求:请获取scoreRate值最高的一条数据:sql:select*fromresultTableorderbyreplace(sco......
  • 一文读懂 Mysql MVCC
    ......
  • MySQL如何将创建外部表
     MySQL如何将创建外部表 本文实验版本MySQL8。MySQL中所谓的外部表,就是将innodb表创建在变量datadir代表的数据目录之外。(跟Oracle外部表完全不是一个东西)出于扩容,空间管理,IO优化等原因。这里可以使用如下3种方式创建外部表:使用DATADIRECTORY子句使用CREATETA......
  • MYSQL查询时间范围内的数据
    其中,table_name是要查询的表名,date_column是日期字段的列名。一周SELECT *FROM table_nameWHERE date_columnBETWEENDATE_SUB(CURDATE(),INTERVAL1WEEK)ANDCURDATE();一个月SELECT *FROM table_nameWHERE date_columnBETWEENDATE_SUB(CURDATE(),INTERV......