首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL设置用户变量锁定行,并且不服从可重复读取

MySQL设置用户变量锁定行,并且不服从可重复读取
EN

Stack Overflow用户
提问于 2022-08-20 13:20:11
回答 1查看 30关注 0票数 0

我遇到了一种"SET @my_var = (SELECT .)“的非法行为在交易中:

  1. 第一个是锁行(这取决于它是否是唯一的索引)。

例子-

代码语言:javascript
复制
START TRANSACTION;

SET @my_var = (SELECT id from table_name where id = 1);

select trx_rows_locked from information_schema.innodb_trx;
ROLLBACKL;

输出是1行锁定,这是奇怪的,它不应该获得一个读取锁。

而且,等效的语句SELECT id INTO @my_var不会产生锁。

UPDATED语句之后(对于2个并发请求),它可能导致死锁。

  1. 在可重复阅读中-

SELECT语句中的SET获取数据的新快照,而不是使用原始快照。

第1场会议:

代码语言:javascript
复制
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;                             
START transaction;         
SELECT data FROM my_table where id = 2; # Output : 2

第2场会议:

代码语言:javascript
复制
UPDATE my_table set data = 3 where id = 2 ;

第1场会议:

代码语言:javascript
复制
 SET @data = (SELECT data FROM my_table where id = 2);
 SELECT @data; # Output : 3, instead of 2
 ROLLBACK;

但是,我希望@data将包含来自第一个快照(2 )的原始值。

如果我使用SELECT data into @data from my_table where id = 2,那么我将得到期望值- 2;

您知道SET = (SELECT ..)SELECT data INTO @var FROM ..不同行为的来源吗?

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2022-08-20 16:11:44

正确--当您在将结果复制到变量或表的上下文中SELECT时,它隐式地工作就像您使用了锁读 SELECT ... FOR SHARE一样。

这意味着它在所检查的行上放置一个共享锁,还意味着该语句只读取最近提交的行版本,就好像您的事务处于读提交隔离级别。

我不知道为什么SELECT ... INTO @var不在MySQL 8.0中执行相同的隐式锁定。我的记忆是,在较早版本的MySQL中,它确实会锁定该查询形式。我已经在手册上找了一份解释,但我还找不到。

其他情况下,隐式锁定SELECT检查的行,从而读取数据,就好像您的事务已被读取提交一样:

  • INSERT INTO <table> SELECT ...
  • UPDATEDELETE多表,即使不更新或删除给定的表,连接的行也会被锁定。
  • 触发器内的SELECT
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73427050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档