mysql 悲观锁 机制 请教

2022-11-28 14:55:42 +08:00
 hhhhhh123

问题 1.:悲观锁 运行机制 目前无法理解的是 假设 pk_money= 1 , 我每次运行都会+ 1 但是我没提交啊
不知道为什么他会每次 + 1 ,
不知道是我 sql 语法问题 还是啥 ?
难道每次运行的时候 会把没有提及的 sql 自动提交? 但是我已经关闭了自动提交 。

问题 2: 我想把 set pk_money=pk_money+1 这个 pk_money 等于上面的查询结果 然后在+ 1 这个应该怎么写啊? 同时是悲观锁。 怎么把 下面的 select 和 update 合并。

问题 3: 我不提交的话,我重新开个窗口 单独去运行

update user_basic_info set pk_money=pk_money+1 where uid=123456803;

是会被阻塞到超时。 说明这个悲观锁是起作用了。 但是不知道怎么解释第一个问题

set autocommit=0;
start transaction;
select `pk_money` from user_basic_info where uid=123456803 for update ;
update user_basic_info set pk_money=pk_money+1 where uid=123456803;
--  COMMIT;

不会放图片。。。。

set autocommit=0
> OK
> Time: 0.074s


start transaction
> OK
> Time: 0.077s


select `pk_money` from user_basic_info where uid=123456803 for update
> Affected rows: 0
> Time: 0.071s


update user_basic_info set pk_money=pk_money+1 where uid=123456803
> Affected rows: 1
> Time: 0.074s


--  COMMIT;
> OK
> Time: 0.071s

1994 次点击
所在节点    程序员
44 条回复
hhhhhh123
2022-11-28 15:35:12 +08:00
是 InnoDB
zhanglintc
2022-11-28 15:57:11 +08:00
@hhhhhh123 #20 你这个现象倒是很神奇。我`Distrib 5.5.60-MariaDB`的版本,反正没能再现出来你的现象。如果是`REPEATABLE-READ`状态,没有 commit 之前,其他窗口是看不到这个变更的。

-----

> 问题 2: 我想把 set pk_money=pk_money+1 这个 pk_money 等于上面的查询结果 然后在+ 1 这个应该怎么写啊? 同时是悲观锁。 怎么把 下面的 select 和 update 合并。

这个问题没看懂。
感觉你这个需求直接用 update 命令就行了:`set pk_money=pk_money+1`。不需要用到`select`命令,没有合并一说。
hhhhhh123
2022-11-28 17:59:35 +08:00
@zhanglintc 因为网上的教程都是先 select 在 update 我以为这是必要流程
la2la
2022-11-28 21:44:14 +08:00
1. MySQL 的存储引擎
la2la
2022-11-28 21:46:24 +08:00
2. 设置的隔离级别

ps: 不要根据现象去推测原理,这种现象或许仅仅是原理的一种表现而已。现象是用来验证原理的。网上有关于 Innodb 引擎的源码级别的教程,看看锁的具体实现呗
zhanglintc
2022-11-28 22:02:33 +08:00
@hhhhhh123 #10 就这一点来说,我表示怀疑。感觉没有可能新窗口中会看到未 commit 的提交。
zhanglintc
2022-11-28 22:03:30 +08:00
对 10 楼的回复“新会话就是 + 1”表示怀疑
hhhhhh123
2022-11-29 09:10:50 +08:00
@zhanglintc 主要是不会贴图片, 不然我就吧图片贴上来。 确确实实+1 。 不过代码就不会。 我也很好奇。 理论上确实不应该拿到未提交数据且更新到数据中了
Dlin
2022-11-29 09:17:51 +08:00
如果真有这种问题,肯定就不是你的问题了。
zhanglintc
2022-11-29 11:17:32 +08:00
@hhhhhh123 #28 图片要传到某个图床,然后在这边贴链接才行。
raysonlu
2022-11-29 15:55:21 +08:00
关于“新会话就是 + 1”也表示怀疑,建议再认真测试一次,在 InnoDB 引擎的表,执行“不会放图片。。。。”后面的代码块的“COMMIT”之前,再确保开了新的会话,直接执行 select (不要 for update ),能把图贴上来,或者语句+结果文字贴上来就行。这种试验,已经给多位新入职同事科普过了。
hhhhhh123
2022-11-29 17:39:59 +08:00
@raysonlu
session1 : SELECT pk_money FROM user_basic_info WHERE uid = 123456803; # pk_money= 496

session2:
```
BEGIN;
set autocommit=0;
select `pk_money` from user_basic_info where uid=123456803 for update ;
update user_basic_info set pk_money=pk_money+1 where uid=123456803;
# 这里没有 commit
```
结果
```
BEGIN
> OK
> Time: 0.047s


set autocommit=0
> OK
> Time: 0.045s


select `pk_money` from user_basic_info where uid=123456803 for update
> Affected rows: 0
> Time: 0.042s


update user_basic_info set pk_money=pk_money+1 where uid=123456803
> Affected rows: 1
> Time: 0.044s

```
再次运行 session1
session1 : SELECT pk_money FROM user_basic_info WHERE uid = 123456803; # pk_money= 497
bruce0
2022-11-29 18:38:55 +08:00
不知道能不能对你起到帮助 https://www.jianshu.com/p/fe708aad6113
zhanglintc
2022-11-29 21:49:59 +08:00
@hhhhhh123 #32 你这俩 session ,是同一个 GUI 工具里的两个不同的 tab 吗?
zhanglintc
2022-11-29 22:05:08 +08:00
这俩“session”里分别执行`select CONNECTION_ID()`感觉会是同一个值?
Dlin
2022-11-29 23:07:52 +08:00
建议用命令行测试
hhhhhh123
2022-11-30 09:22:56 +08:00
@zhanglintc 是啊,navicat 工具 不同的窗口
hhhhhh123
2022-11-30 09:26:45 +08:00
@zhanglintc 不一样 一个 2744 一个 2741
raysonlu
2022-11-30 09:35:20 +08:00
@hhhhhh123 set autocommit=0 在 begin 前
hhhhhh123
2022-11-30 09:39:11 +08:00
@Dlin
你看看 我这语法有问题吗? 应该是这样写的吧?

mysql> begin; set autocommit=0; SELECT pk_money FROM user_basic_info WHERE uid = 123456803 for update ; UPDATE user_basic_info set pk_money=pk_money+1 where uid =123456803;

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+----------+
| pk_money |
+----------+
| 498 |
+----------+
1 row in set (0.00 sec)

Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select pk_money from user_basic_info where uid= 123456803;
+----------+
| pk_money |
+----------+
| 499 |
+----------+
1 row in set (0.00 sec)

mysql>

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/898510

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX