首页 > 数据库 >mysql在select ······ for update 在什么情况下加什么锁

mysql在select ······ for update 在什么情况下加什么锁

时间:2024-05-16 18:31:43浏览次数:20  
标签:IX 下加 update 索引 user mysql 主键 select

准备环境:

select @@version;
select @@autocommit;
set @@autocommit=0;

CREATE TABLE `user_info_tab` (
                             `id` int NOT NULL AUTO_INCREMENT,1. 1. 
                             `user_name` varchar(255) DEFAULT NULL,
                             `age` int DEFAULT NULL,
                             `city` varchar(255) DEFAULT NULL,
                             `status` varchar(4) NOT NULL DEFAULT '0',
                             PRIMARY KEY (`id`),
                             UNIQUE KEY `idx_user_name` (`user_name`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=1570072 DEFAULT CHARSET=utf8mb3;
    insert into user_info_tab(`user_name`,`age`,`city`,`status`) values('杰伦',18,'深圳','1');
    insert into user_info_tab(`user_name`,`age`,`city`,`status`) values('奕迅',26,'湛江','0');
    insert into user_info_tab(`user_name`,`age`,`city`,`status`) values('俊杰',28,'广州','1');

RC隔离级别

-- 设置隔离级别
select @@transaction_isolation;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

1 RC + 唯一索引

更新同一条记录


事务2被阻塞

更新其他记录


事务2正常执行
因此在RC隔离级别下,如果条件是唯一索引,那么select...for update加的是行锁

-- 查看加锁情况
SELECT * FROM performance_schema.data_locks;
select * from user_info_tab where user_name ='杰伦' for update
--  语句一共加了3把锁 如下

1, IX 意向排他锁:当事务准备在某条记录上加上X锁时,需要在表级别加一个IX锁。如select ... for update,要给表设置IX锁;意向锁仅仅表明意向的锁,意向锁之间不会互斥,是可以并行的
2,这条记录的唯一索引和主键索引都加了X锁,因为如果并发的一个SQL,通过主键索引来更新,若没有将主键索引上的记录加锁,那么并发的update就会感知不到,违背了同一记录上的更新/删除需要串行执行的约束。

2 RC + 主键索引

更新同一条记录


事务2被阻塞

查看加锁情况

会加两把锁:分表是IX意向排他锁(表锁,不影响插入)、一把X排他锁(行锁,对于主键索引)

3 RC 隔离级别 + 普通索引

-- 添加普通索引
alter table user_info_tab add index idx_city (city);

事务2被阻塞

IX意向排他锁(表锁)、两把X排他锁(行锁,分别对应普通索引的X锁,对应主键的X锁)。

未命中数据库表的记录,只加 IX意向排他锁(表锁,不影响插入)

4 RC 隔离级别 + 无索引

IX意向排他锁(表锁)、一把X排他锁(行锁,对应主键的X锁)。

age列上没有索引,MySQL会走聚簇(主键)索引进行全表扫描过滤。每条记录都会加上X锁。但为了效率考虑,MySQL在这方面进行了改进,在扫描过程中,若记录不满足过滤条件,会进行解锁操作。同时优化违背了2PL原则。

RR 隔离级别

-- 设置RR隔离级别
set global transaction isolation level repeatable read;
select @@transaction_isolation;

1 RR + 唯一索引

-- RR + 唯一索引
## 事务1
begin;
select *from user_info_tab where user_name ='杰伦'for update;

## 事务2
begin;
update user_info_tab set age= '30' where id = '1570074';
update user_info_tab set age= '26' where id = '1570072';

查询条件是唯一索引,命中数据库表记录时,一共会加三把锁:一把IX意向排他锁 (表锁,不影响插入),一把对应主键的X排他锁(行锁),一把对应唯一索引的X排他锁 (行锁)

2 RR + 主键

跟RC隔离级别一样,会加两把锁:一把IX意向排他锁(表锁,不影响插入),一把对应主键的X排他锁(行锁,影响对应主键那一行的插入)。

3 RR + 普通索引

在RR隔离级别下,如果select...for update的查询条件是普通索引的话,除了会加X锁,IX锁,还会加Gap 锁
Gap锁的提出,是为了解决幻读问题引入的,它是一种加在两个索引之间的锁。

实际操作发现并不会阻塞,也没有gap锁

4 RR + 无索引

IX锁(表级别,意向排他锁)+ 每一行的数据记录加X排他锁


RR隔离级别下,对于select...for update,查询条件无索引的话,会加一个IX锁(表锁,不影响插入),每一行实际记录行的X锁,还有对应于supremum pseudo-record的虚拟全表行锁。这种场景,通俗点讲,其实就是锁表了。

实际操作未发现supremum pseudo-record

标签:IX,下加,update,索引,user,mysql,主键,select
From: https://www.cnblogs.com/wise-mushroom/p/18196462

相关文章

  • MySql5.6 关于视图访问权限问题记录
    问题描述使用zstack或root账号访问视图view3出现[root@172-26-52-170mariadb]#mysql-uzstack-pzstack.passwordzstack-e"select*fromview3"ERROR1045(28000)atline1:Accessdeniedforuser'zstack'@'localhost'(usingpassword:YES)......
  • DataX将MySql数据库数据同步到Oracle数据库
    1.下载DataX并解压(本地环境安装有python)DataX/userGuid.mdatmaster·alibaba/DataX(github.com) job文件夹下存放数据同步的json脚本{"job":{"setting":{"speed":{"channel":1}......
  • 10分钟搞定Mysql主从部署配置
    流程Master数据库安装Slave数据库安装配置Master数据库配置Slave数据库网络信息Master数据库IP:192.168.198.133Slave数据库IP:192.168.198.132配置Master数据库在Master数据库安装完毕后,修改/etc/my.cnf[mysqld]server-id=1\\指定ID,主从的两台虚拟机ID必须不同log......
  • lightdb mysql 8.0兼容之不可见主键
    数据库设计通常需要满足一定的范式要求,其中主键更是最基本的要求。不过,数据库管理系统却允许我们创建没有主键的表。这样的表在数据库中会带来查询性能低下、复制延迟甚至无法实现高可用配置等问题。为此,lightdb在22.1版本引入了一个新的功能,叫做不可见主键(GeneratedInv......
  • mysql存储过程中如何使用游标中的值进行查询
    在MySQL中,游标(Cursor)是一种用于从结果集中逐行访问数据的数据库对象。在存储过程(StoredProcedure)中,你可以使用游标遍历查询结果,并对每一行数据进行处理。下面是一个简单的示例,说明如何在MySQL存储过程中使用游标中的值进行查询:创建示例表首先,我们创建一个简单的示例表,用于演......
  • mysql命令行增删改查
    新增数据库shop:createdatabaseshop;查看数据库:showdatabases;查看创建数据库的命令:showcreatedatabaseshop;进入数据库: useshop;查看数据表: showtables;创建数据表name:   createtablename(idint,bsvarchar(50));进入数据表:descname可以查看创建表的命......
  • 聊聊MySQL是如何处理排序的
    本文分享自华为云社区《MySQL怎样处理排序⭐️如何优化需要排序的查询?》,作者:菜菜的后端私房菜。前言在MySQL的查询中常常会用到 orderby 和 groupby 这两个关键字它们的相同点是都会对字段进行排序,那查询语句中的排序是如何实现的呢?当使用的查询语句需要进行排序时有两种......
  • 配置MySQL主从复制和读写分离
    实验环境序号主机名IP地址备注1mysql-master192.168.204.201MySQL主库2mysql-slave192.168.204.202MySQL从库3appserver192.168.204.111应用服务器安装配置MySQL数据库1.使用yum安装mysql和mysql-serveryuminstall-ymariadbmariadb-server2.启......
  • Oracle update语句引起大量业务卡顿
    记一次update语句引起大量业务卡顿分析处理过程,聊聊我的思路。技术人人都可以磨炼,但处理问题的思路和角度各有不同,希望这篇文章可以抛砖引玉。以一个例子为切入点一、问题背景某业务模块反馈最近出现过几次业务卡顿,数据库中定位到有几个insertinto语句的gc等待比较严重,虽然......
  • gorm实现MySQL的INSERT INTO ... ON DUPLICATE KEY UPDATE差异化插入和更新
    比如插入f_create_uid,更新时忽略f_create_uid,只更新f_update_uid。可使用gorm的BeforeCreate和BeforeUpdate钩子,这两个钩子分别在创建和更新记录之前被调用。//BeforeCreate在创建记录之前调用func(dob*MyStruct)BeforeCreate(tx*gorm.DB)(errerror){dob......