事务遇上分布式锁

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

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>