首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL是否保证从读锁到写锁的原子升级?

MySQL是否保证从读锁到写锁的原子升级?
EN

Database Administration用户
提问于 2014-04-23 13:52:42
回答 1查看 985关注 0票数 2

如果客户端会话当前持有读锁(允许并发读取,同时已经阻止写入),然后在同一表(S)上获得写锁,MySQL是否保证锁是连续的?

手册指出:

如果会话在已经持有锁的同时发出锁表语句以获取锁,则在授予新锁之前隐式地释放其现有锁。

据我所见,它没有明确规定从读到写“升级”锁。如图所示

代码语言:javascript
复制
mysql> LOCK TABLE `awesome` READ;
mysql> SELECT ... FROM `awesome` ...
mysql> LOCK TABLE `awesome` WRITE;  # lock continuous, or dropped+reacquired?
mysql> INSERT INTO `awesome` ...
mysql> UNLOCK TABLES;

如果我偏执于文档中的语句,那么我必须假设,在我的会话暂时没有锁的两个锁状态之间会有一个短暂的时刻,在这段时间内,并发会话可能会修改表,从而使它处于与我在SELECT阶段看到的情况不一致的状态。

我不能依赖由重复的密钥冲突引发的异常,因为没有有用的唯一键(如果MySQL甚至支持它,它可能会使表的大小翻两番)。出于同样的原因,事务并不能真正帮助我,但无论如何我都不能使用它们,因为问题中的表格是出于性能原因使用MyISAM引擎的。锁定似乎是我最好的选择,只是文档在转换细节上显得有点显眼。

以及如果表集相同,MySQL如何在内部处理从读锁到写锁的转换?

大木锤的方法当然是在前面发出一个单一的写锁。但很明显,这会迫使所有人都选择等待。OTOH,据我所知,无限数量的会话可以同时读取-锁定同一个表(隐式或显式),而对select性能没有任何影响。读锁所做的唯一一件事就是防止更新击中表,这正是我在第一阶段所需要的。

EN

回答 1

Database Administration用户

回答已采纳

发布于 2014-05-19 10:20:54

实际上,你所引用的手册中的部分就是这样说的:

代码语言:javascript
复制
-- Connection #1
LOCK TABLE mytable READ; -- lock is acquired

-- Connection #2
LOCK TABLE mytable WRITE; -- execution is suspended, lock is NOT acquired

-- Connection #1
LOCK TABLE mytable WRITE; -- execution is suspended
-- READ lock was released, allowing Connection #2 to acquire the WRITE lock
-- Connection #2 resumes

解决方案:切换到InnoDB并使用事务。InnoDB引擎在最近的版本中做了很多改进的性能。

代码语言:javascript
复制
-- Connection #1
BEGIN;
SELECT * FROM mytable LOCK IN SHARE MODE; -- lock is acquired

-- Connection #2
BEGIN;
SELECT * FROM mytable FOR UPDATE; -- execution is suspended, lock is NOT acquired

-- Connection #1
SELECT * FROM mytable FOR UPDATE;
-- deadlock is detected, Connection #2 is rolled back
票数 0
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/63739

复制
相关文章

相似问题

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