背景

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

就用了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. 赶紧收藏!这些Java中的流程控制知识你都不知道,你凭什么涨薪?

    Java的流程控制 基础阶段 目录: 用户交互Scanner 顺序结构 选择结构 循环结构 break & continue 练习题 1.Scanner对象 之前我们学的基本语法中并没有实现程 ...

  2. Vegas视频的音频叠加效果怎么实现,可以用其他软件吗

    有时我们会用Vegas为某段影片配音,我们要怎么把配音和背景声融合在一起呢?想必马上会有人反应过来:让配音和背景声分别置于两条轨道上就好了.这当然是一个相当好的方式. 可是,如果我想要把两段音频合成一 ...

  3. 为什么企业需要CRM系统?CRM的作用及其重要性分析

    客户管理系统(CRM)是企业核心应用软件之一,对于提高企业业绩起着至关重要的作用,现在很多企业都在客户发展方面投入大量的资金,以求获得更好的回报. 关于CRM CRM是一个客户数据中心,在CRM中,你 ...

  4. 面试题59 - II. 队列的最大值

    请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value.push_back 和 pop_front 的时间复杂度都是O(1). 若队列为空,pop_front 和 ...

  5. Nginx搭建文件共享服务器

    前言 Nginx除了做正反向代理和负载均衡,还能做动静分离服务器,如此便可以当作文件共享服务器使用. 环境 WIN 10 Vmware Workstation 15 Player CentOS Lin ...

  6. limit+orderBy陷阱

    碰到一个奇怪的bug,在排序的时候对一个非唯一的字段做order by, 结果在分页的时候,发现每一页的数据都是乱的,并不是对整个排序之后再去limit的. 当我们用唯一字段去排序的时候,因为在找到满 ...

  7. spring bean注册和实例化

    1.左边3个接口定义了基本的Ioc容器的2.HierarchicalBeanFactory增加了getParentBeanFactory()具备了双亲Ioc的管理能力3.ConfigurableBea ...

  8. 20190814_tomcat配置项目的错误页

    1. 打开项目中的web.xml, 注意不是tomcat的web.xml; 一般是在项目的 WEB-INF目录下, 然后加上下面的语句 <error-page> <error-cod ...

  9. python数据更新

    def cal(s,m): if s==u"废弃" or s==u"拆除": return 4 elif s==u"竣工": return ...

  10. Python中函数的参数带星号是什么意思?

    参数带星号表示支持可变不定数量的参数,这种方法叫参数收集. 星号又可以带1个或2个,带1个表示按位置来收集参数,带2个星号表示按关键字来收集参数. 1.带一个星号的参数收集模式: 这种模式是在函数定义 ...