背景

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

就用了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. Linux下Docker容器安装与使用

    注:作者使用的环境是CentOS 7,64位,使用yum源安装. 一.Docker容器的安装 1.查看操作系统及内核版本,CentOS 7安装docker要求系统为64位.系统内核版本为 3.10及以 ...

  2. 掌握这些springboot的配置方式,让你工作效率翻个倍!

    springboot的多种配置方式 java配置主要靠java类和一些注解,比较常用的注解有: @Configuration :声明一个类作为配置类,代替xml文件 @Bean :声明在方法上,将方法 ...

  3. appium元素定位总结

    appium元素定位方法总结 使用uiautomator定位 driver.find_element_by_android_uiautomator(uia_string) 根据resourceId属性 ...

  4. (1)Hello World

    语出<论语·卫灵公>:子贡问为仁.子曰:"工欲善其事,必先利其器.居是邦也,事其大夫之贤者,友其士之仁者." 2020年11月终于下定决心开始 Visual C++ 的 ...

  5. [TroubleShootting]Zabbix数据采集出现断点的问题

    背景 最近发现公司的Zabbix监控大屏上的监控图经常出现数据断点的现象,主要集中在一些自定义的监控项数据上,如下图: 原因 查看Zabbix Server日志以及zabbix官方手册后,分析可能原因 ...

  6. moviepy应用pyinstaller打包后执行报错AttributeError: module audio/video.fx.all has no attribute fadein、crop

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 在开发moviepy的Python程序使用pyinstaller打包后 ...

  7. PyQt学习随笔:QtDesigner ListView控件列表项的初始化

    在QtDesigner中设计的界面中添加ListView控件后,是没办法添加需要在ListView控件中显示的列表项.由于ListView控件只是一个展示列表项的视图控件,实现了界面与数据的分离,其要 ...

  8. PyQt(Python+Qt)学习随笔:什么是信号绑定(Unbound and Bound Signals)?

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 1.概述 信号的绑定是由在类的实例变量中第一次通过类实例的方式(即"self.信号&quo ...

  9. 本地代码上传到github

    一,注册Github账号 1.先注册一个账号,注册地址:https://github.com/ 2.登录后,点击start a project 3.创建一个repository name,输入框随便取 ...

  10. 使用T4模板动态生成NPoco实体类

    这是一个妥妥的NPoco类,这是我们在工作开发中,手动去写这个实体类,属实非常心累,字段少无所谓一次两次,数量多了,字段多了,就心态裂开