背景

最近工作中遇到一个问题,两个不同的线程会对数据库里的一条数据做修改,如果不加锁的话,会得到错误的结果。

就用了MySQL中for update 这种方式来实现

本文主要测试主键、唯一索引和普通索引使用for update 会锁哪些数据

使用两个console来模拟两个事务运行的情况

表结构

/*
Navicat Premium Data Transfer Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50730
Source Host : localhost:3306
Source Schema : test Target Server Type : MySQL
Target Server Version : 50730
File Encoding : 65001 Date: 18/12/2020 20:28:58
*/ SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for select_for_update_test
-- ----------------------------
DROP TABLE IF EXISTS `select_for_update_test`;
CREATE TABLE `select_for_update_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
KEY `age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of select_for_update_test
-- ----------------------------
BEGIN;
INSERT INTO `select_for_update_test` VALUES (1, 'a', 1);
INSERT INTO `select_for_update_test` VALUES (2, 'b', 2);
INSERT INTO `select_for_update_test` VALUES (3, 'c', 3);
INSERT INTO `select_for_update_test` VALUES (4, 'd', 4);
INSERT INTO `select_for_update_test` VALUES (5, 'e', 5);
INSERT INTO `select_for_update_test` VALUES (6, 'f', 6);
INSERT INTO `select_for_update_test` VALUES (7, 'g', 7);
INSERT INTO `select_for_update_test` VALUES (8, 'h', 8);
COMMIT; SET FOREIGN_KEY_CHECKS = 1;

主键的影响

  • 选一行数据
console1

START TRANSACTION;
SELECT * FROM select_for_update_test WHERE id = 1 FOR UPDATE;
console2
SELECT * FROM select_for_update_test WHERE id = 1 FOR UPDATE; 会锁 SELECT * FROM select_for_update_test WHERE id = 2 FOR UPDATE; 不会锁
  • 选取多行记录
console1

START TRANSACTION;
SELECT * FROM select_for_update_test WHERE id >= 2 AND id <= 5 FOR UPDATE;
console2

SELECT * FROM select_for_update_test WHERE id = 1 FOR UPDATE; 不会锁

SELECT * FROM select_for_update_test WHERE id = 3 FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE id = 6 FOR UPDATE; 会锁

唯一索引

  • 选一行数据
console1

START TRANSACTION;
SELECT * FROM select_for_update_test WHERE `name` = 'a' FOR UPDATE;
console2

SELECT * FROM select_for_update_test WHERE `name` = 'a' FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE `name` = 'b' FOR UPDATE; 不会锁
  • 选取多行记录
console1

START TRANSACTION;
SELECT * FROM select_for_update_test WHERE `name` >= 'b' AND `name` <= 'e' FOR UPDATE;
console2

SELECT * FROM select_for_update_test WHERE `name` = 'a' FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE `name` = 'c' FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE `name` = 'f' FOR UPDATE; 会锁
  • 选取多行记录
console1

START TRANSACTION;
SELECT * FROM select_for_update_test WHERE `name` >= 'c' AND `name` <= 'e' FOR UPDATE;
console2

SELECT * FROM select_for_update_test WHERE `name` = 'b' FOR UPDATE; 不会锁

SELECT * FROM select_for_update_test WHERE `name` = 'c' FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE `name` = 'f' FOR UPDATE; 会锁

普通索引

  • 选一行数据
console1

START TRANSACTION;
SELECT * FROM select_for_update_test WHERE age = 1 FOR UPDATE;
console2

SELECT * FROM select_for_update_test WHERE age = 1 FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE age = 2 FOR UPDATE; 不会锁
  • 选取多行记录
console1

START TRANSACTION;
SELECT * FROM select_for_update_test WHERE age >= 2 AND age <= 5 FOR UPDATE;
console2

SELECT * FROM select_for_update_test WHERE age = 1 FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE age = 3 FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE age = 6 FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE age = 8 FOR UPDATE; 不会锁
  • 选取多行记录
console1

START TRANSACTION;
SELECT * FROM select_for_update_test WHERE age >= 3 AND age <= 5 FOR UPDATE;
console2

SELECT * FROM select_for_update_test WHERE age = 2 FOR UPDATE; 不会锁

SELECT * FROM select_for_update_test WHERE age = 3 FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE age = 6 FOR UPDATE; 会锁

SELECT * FROM select_for_update_test WHERE age = 8 FOR UPDATE; 不会锁

MySQL中的 ”SELECT FOR UPDATE“ 一次实践的更多相关文章

  1. MySQL中ON DUPLICATE KEY UPDATE使用

    今天做推断插入用到了MySQL中ON DUPLICATE KEY UPDATE,如今Mark下面! 假设你想做到数据库中没有数据的话插入数据.有数据的话更新数据,那么你能够选择ON DUPLICATE ...

  2. sql判断以逗号分隔的字符串中是否包含某个字符串--------MYSQL中利用select查询某字段中包含以逗号分隔的字符串的记录方法

    sql判断以逗号分隔的字符串中是否包含某个字符串---------------https://blog.csdn.net/wttykj/article/details/78520933 MYSQL中利 ...

  3. 【转载】MySQL事务以及SELECT ... FOR UPDATE的使用

    MySQL中的事务,默认是自动提交的,即autocommit = 1: 但是这样的话,在某些情形中就会出现问题:比如: 如果你想一次性插入了1000条数据,mysql会commit1000次的, 如果 ...

  4. mysql事务,select for update,及数据的一致性处理

    在MySQL的InnoDB中,预设的Tansaction isolation level 为REPEATABLE READ(可重读) 在SELECT 的读取锁定主要分为两种方式: SELECT ... ...

  5. 一个MySQL中两表联合update的例子(并带有group by分组)

    内容简介 本文主要展示了在MySQL中,使用两表联合的方式来更新其中一个表字段值的SQL语句. 也就是update table1 join table2 on table1.col_name1=tab ...

  6. MYSQL中的SELECT查询时进行运算

    SELECT在mysql中是查询表中的数据的作用,但也可以在查询的时候直接进行运算,然后返回查询后的结果 比如 )) FROM username2 其中的IFNULL函数是对adven数据进行判断,若 ...

  7. MYSQL中利用select查询某字段中包含以逗号分隔的字符串的记录方法

    首先我们建立一张带有逗号分隔的字符串. CREATE TABLE test(id int(6) NOT NULL AUTO_INCREMENT,PRIMARY KEY (id),pname VARCH ...

  8. 【数据库系列】MySql中的select的锁表范围

    由于InnoDB预设的是Row-Level Lock,只有明确指定主键的时候MySql才会执行Row lock,否则MySql将会执行Table Lock. 1.明确指定主键则是行锁 2.明确指定主键 ...

  9. mysql中的select语句where条件group by ,having , order by,limit的顺序及用法

    -- 语法: SELECT select_list FROM table_name [ WHERE search_condition ] [ GROUP BY group_by_expression ...

随机推荐

  1. 面试阿里,腾讯,字节跳动90%都会被问到的Spring中的循环依赖

    前言 Spring中的循环依赖一直是Spring中一个很重要的话题,一方面是因为源码中为了解决循环依赖做了很多处理,另外一方面是因为面试的时候,如果问到Spring中比较高阶的问题,那么循环依赖必定逃 ...

  2. MathType中如何实现上下两行公式“=”号对齐

    作为功能强大的数学公式编辑器,MathType可以轻松输入各种复杂的公式和符号,与 Office 文档完美结合,显示效果超好,比 Office 自带的公式编辑器要强大很多,可以为办公文档.网页.桌面出 ...

  3. 下载器Folx怎么安装使用

    应该使用哪个下载工具?这个如果是Windows上会有无数答案的问题,在Mac上却变得异常的纠结.比如Leech和Aria2,这两款软件,前者功能相对比较简单,后者的配置又稍微有点复杂,很难找到一款相对 ...

  4. guitar pro 系列教程(十一):Guitar Pro菜单工具之MIDI效果的提升

    对于新手的一些朋友,看谱,编曲时使用Guitar Pro时,因为对其功能不是很了解而显得困难重重,导致出现的音频效果不是很理想,因此,小编今天要做的便是,单独把Guitar Pro里的MIDI效果如果 ...

  5. redlock分布式锁真的安全吗

    此文是对http://zhangtielei.com/posts/blog-redlock-reasoning-part2.html文章的个人归纳,如有问题请联系删除 什么是redlock redlo ...

  6. LCCUP 2020 秋季编程大赛 补题

    果然是力扣杯,难度较于平时周赛提高了不少,个人感觉最后两题并不太容易QAQ LCP 18.早餐组合 #二分思想 题目链接 题意 你获得了每种主食的价格,及每种饮料的价格,你需要选择一份主食和一份饮料, ...

  7. Java基础教程——包装类

    Java出道之时,自诩为"纯面向对象的语言",意思是之前的所谓"面向对象语言"不纯. 但是,有人指责Java也不纯--8种基本类型并非类类型.为此,Java为他 ...

  8. Leetcode第 217 场周赛(思维量比较大)

    Leetcode第 217 场周赛 比赛链接:点这里 做完前两题我就知道今天的竞赛我已经结束了 这场比赛思维量还是比较大的. 1673. 找出最具竞争力的子序列 题目 给你一个整数数组 nums 和一 ...

  9. C语言--计算代码段运行时间

    c语言中有专一包含计算时间函数的头文件,time.h.当我们需要计算某段程序运行的时间时就需要用到time.h包含的clock()函数,在这里介绍一下如何使用这个函数计算代码运行时间. clock函数 ...

  10. BYTE WORD DWORD

    在Visual C++ 6.0中,BYTE与WORD,DWORD本质上都是一种无符号整型,它们在WINDEF.H中被定义,定义如下:typedef unsigned char       BYTE;t ...