MySQL中的 ”SELECT FOR UPDATE“ 一次实践
背景
最近工作中遇到一个问题,两个不同的线程会对数据库里的一条数据做修改,如果不加锁的话,会得到错误的结果。
就用了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“ 一次实践的更多相关文章
- MySQL中ON DUPLICATE KEY UPDATE使用
今天做推断插入用到了MySQL中ON DUPLICATE KEY UPDATE,如今Mark下面! 假设你想做到数据库中没有数据的话插入数据.有数据的话更新数据,那么你能够选择ON DUPLICATE ...
- sql判断以逗号分隔的字符串中是否包含某个字符串--------MYSQL中利用select查询某字段中包含以逗号分隔的字符串的记录方法
sql判断以逗号分隔的字符串中是否包含某个字符串---------------https://blog.csdn.net/wttykj/article/details/78520933 MYSQL中利 ...
- 【转载】MySQL事务以及SELECT ... FOR UPDATE的使用
MySQL中的事务,默认是自动提交的,即autocommit = 1: 但是这样的话,在某些情形中就会出现问题:比如: 如果你想一次性插入了1000条数据,mysql会commit1000次的, 如果 ...
- mysql事务,select for update,及数据的一致性处理
在MySQL的InnoDB中,预设的Tansaction isolation level 为REPEATABLE READ(可重读) 在SELECT 的读取锁定主要分为两种方式: SELECT ... ...
- 一个MySQL中两表联合update的例子(并带有group by分组)
内容简介 本文主要展示了在MySQL中,使用两表联合的方式来更新其中一个表字段值的SQL语句. 也就是update table1 join table2 on table1.col_name1=tab ...
- MYSQL中的SELECT查询时进行运算
SELECT在mysql中是查询表中的数据的作用,但也可以在查询的时候直接进行运算,然后返回查询后的结果 比如 )) FROM username2 其中的IFNULL函数是对adven数据进行判断,若 ...
- MYSQL中利用select查询某字段中包含以逗号分隔的字符串的记录方法
首先我们建立一张带有逗号分隔的字符串. CREATE TABLE test(id int(6) NOT NULL AUTO_INCREMENT,PRIMARY KEY (id),pname VARCH ...
- 【数据库系列】MySql中的select的锁表范围
由于InnoDB预设的是Row-Level Lock,只有明确指定主键的时候MySql才会执行Row lock,否则MySql将会执行Table Lock. 1.明确指定主键则是行锁 2.明确指定主键 ...
- mysql中的select语句where条件group by ,having , order by,limit的顺序及用法
-- 语法: SELECT select_list FROM table_name [ WHERE search_condition ] [ GROUP BY group_by_expression ...
随机推荐
- Linux下Docker容器安装与使用
注:作者使用的环境是CentOS 7,64位,使用yum源安装. 一.Docker容器的安装 1.查看操作系统及内核版本,CentOS 7安装docker要求系统为64位.系统内核版本为 3.10及以 ...
- 掌握这些springboot的配置方式,让你工作效率翻个倍!
springboot的多种配置方式 java配置主要靠java类和一些注解,比较常用的注解有: @Configuration :声明一个类作为配置类,代替xml文件 @Bean :声明在方法上,将方法 ...
- appium元素定位总结
appium元素定位方法总结 使用uiautomator定位 driver.find_element_by_android_uiautomator(uia_string) 根据resourceId属性 ...
- (1)Hello World
语出<论语·卫灵公>:子贡问为仁.子曰:"工欲善其事,必先利其器.居是邦也,事其大夫之贤者,友其士之仁者." 2020年11月终于下定决心开始 Visual C++ 的 ...
- [TroubleShootting]Zabbix数据采集出现断点的问题
背景 最近发现公司的Zabbix监控大屏上的监控图经常出现数据断点的现象,主要集中在一些自定义的监控项数据上,如下图: 原因 查看Zabbix Server日志以及zabbix官方手册后,分析可能原因 ...
- moviepy应用pyinstaller打包后执行报错AttributeError: module audio/video.fx.all has no attribute fadein、crop
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 在开发moviepy的Python程序使用pyinstaller打包后 ...
- PyQt学习随笔:QtDesigner ListView控件列表项的初始化
在QtDesigner中设计的界面中添加ListView控件后,是没办法添加需要在ListView控件中显示的列表项.由于ListView控件只是一个展示列表项的视图控件,实现了界面与数据的分离,其要 ...
- PyQt(Python+Qt)学习随笔:什么是信号绑定(Unbound and Bound Signals)?
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 1.概述 信号的绑定是由在类的实例变量中第一次通过类实例的方式(即"self.信号&quo ...
- 本地代码上传到github
一,注册Github账号 1.先注册一个账号,注册地址:https://github.com/ 2.登录后,点击start a project 3.创建一个repository name,输入框随便取 ...
- 使用T4模板动态生成NPoco实体类
这是一个妥妥的NPoco类,这是我们在工作开发中,手动去写这个实体类,属实非常心累,字段少无所谓一次两次,数量多了,字段多了,就心态裂开