MySQL中的 ”SELECT FOR UPDATE“ 一次实践
2020-12-18 23:22
204 查看
背景
最近工作中遇到一个问题,两个不同的线程会对数据库里的一条数据做修改,如果不加锁的话,会得到错误的结果。
就用了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; 不会锁
- 选取多行记录1
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; 会锁
- 选取多行记录2
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; 不会锁
- 选取多行记录1
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; 不会锁
- 选取多行记录2
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中select * for update
- Mysql加锁过程详解(4)-select for update/lock in share mode 对事务并发性影响
- MySQL行级锁SELECT FOR UPDATE 和LOCK IN SHARE MODE区别
- MySQL read lock.. 利用 select .. for update 解决.
- Mysql 数据库死锁过程分析(select for update)
- 从 select ... for update来分析mysql的锁
- Mysql查询语句使用select.. for update导致的数据库死锁分析
- mysql中select * for update
- Mysql加锁过程详解(4)-select for update/lock in share mode 对事务并发性影响
- MySQL事务以及select...for update
- 【MySQL】select for update 的Row Lock 与Table Lock
- MySQL update && select ,update的同时select,和for update 语句说再见。
- MySQL与PostgreSQL的 SELECT FOR UPDATE
- No NOWAIT Option in MySQL SELECT FOR UPDATE
- MySQL中的行级锁SELECT FOR UPDATE 和LOCK IN SHARE MODE 区别
- mysql SELECT FOR UPDATE语句使用示例
- Mysql中You can't specify target table for update in FROM clause错误的意思是说,不能先select出同一表中的某些值,再update这个表(在同一语句中)。
- mysql中select * for update
- mysql 加锁读Locking Reads (SELECT ... FOR UPDATE and SELECT ... LOCK IN SHARE MODE)