登录/注册
小张
1699
占位
2
占位
0
浏览量
占位
粉丝
占位
关注
事务遇上分布式锁
小张
2022-07-25 11:16:46 2022-07-25
77
0

文章目录

1.分布式锁的几种实现方式

  • 直接使用MySQL进行同步异常处理
  • redis Lua脚本或者redison
  • zookeeper原子树结构

2. MySQL使用自带锁进行分布式同步控制

mysql加锁方式,todo。

2.1 环境准备

DROP TABLE IF EXISTS `metering`;
CREATE TABLE `metering` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`rest` double(20, 2) NOT NULL DEFAULT 0.00,
`version` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of metering
-- ----------------------------
INSERT INTO `metering` VALUES (1, '小碗熊干脆面', 100.00, 0, '');
INSERT INTO `metering` VALUES (2, '魔法师干脆面', 100.00, 0, '');
INSERT INTO `metering` VALUES (3, '飞旺辣条', 100.00, 0, '');
INSERT INTO `metering` VALUES (4, '绿箭辣条', 100.00, 0, '');

输入以下命令查看隔离级别

show variables like 'tx_isolation';

输入以下命令查看是否自动提交事务

show variables like 'autocommit';

ON 自动提交 OFF不是自动提交

修改自动提交状态:

set autocommit=on;

手动提交命令

start transaction;
SQL;
commit;

2.2 可重复读下的for update的验证

在可重复读隔离级别下读不到别的事务还未提交的内容,并且在事务未提交之前都是对事务开启时刻的数据的快照读,即读不到别的事务已经修改的内容,这样就导致了使用version 字段的时候普通select 无法读最新数据。

事务1 事务2
start transaction;
start transaction;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述事务1进行解锁
在这里插入图片描述事务2获取到锁就读到当前最新数据,但是也同时对数据进行了加锁

有一种强制读的办法就是加for update,但如果别的事务没有提交修改内容就会处于等待锁的过程中。

同时需注意的是,如果没有开启事务,如果事务1获取到X锁,在未开启事务场景下的事务2使用for update 会阻塞,而且也是属于快照读。读不到事务1未提交的内容,但是不加for update时可以读到已经提交的内容,验证结果如下:

事务1 未开事务
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

验证2,事务外可读事务已提交内容:

事务1 未开事务
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述读到已经提交的内容

如果在for update 加X锁读的时候不是按照索引来读的,则会锁表。

事务1 未开事务
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

所以使用X锁在innodb引擎下注意要和索引进行使用。

3.Redis使用分布式锁

todo

暂无评论