首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL锁定和隔离级别

MySQL锁定和隔离级别
EN

Database Administration用户
提问于 2022-12-28 19:48:43
回答 1查看 153关注 0票数 3

有人能帮我理解MySQL的行为吗?

我试图使用以下语句在表中添加一个新列:

代码语言:javascript
复制
ALTER TABLE `tb_example`
    ADD COLUMN `score` INT NULL,
    ALGORITHM = INPLACE,
    LOCK = NONE;

结果是,整个应用程序开始接收锁定元数据错误,而语句从未完成。

该表非常小;起初我认为操作很重,因为FKs与其他表、索引重建或其他相关。

然后,我试图将隔离级别从改为,一旦我再次运行alter,它几乎立即结束了。

现在我知道锁定与事务所使用的表有关。但有些事情我还没有忘记:

如果行被用于其他读取事务,并且无法获得联机DDL所需的排他锁,那么为什么所有读取事务都被锁定,而不仅仅是DDL操作?我原以为只有DDL操作需要更多的时间才能完成,因为它必须等待其他事务的完成。

非常感谢

EN

回答 1

Database Administration用户

回答已采纳

发布于 2022-12-29 23:27:23

在你的第二次测试中,这个改动很快就完成了,这是一个巧合。事务隔离级别与元数据锁定无关。

这里有一个演示来证明这一点:

窗口1:

代码语言:javascript
复制
mysql> create table tb_example (id serial primary key);
mysql> insert into tb_example () values ();
mysql> begin;
mysql> select * from tb_example;
+----+
| id |
+----+
|  1 |
+----+

我现在在window 1中有一个活动事务快照,这意味着事务保存在该表上的一个元数据锁上。

窗口2:

代码语言:javascript
复制
mysql> set transaction_isolation = 'read-uncommitted';
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE `tb_example`     ADD COLUMN `score` INT NULL,     ALGORITHM = INPLACE,     LOCK = NONE;
(hangs)

窗口1:

代码语言:javascript
复制
mysql> show processlist;
...
| 24 | root            | localhost | test | Query   |       5 | Waiting for table metadata lock | ALTER TABLE `tb_example` ...
...

这表明DDL需要启动表上的元数据锁,而不管事务隔离级别如何。事务隔离级别只影响InnoDB行级锁定,因为InnoDB事务是在存储引擎层中处理的。但是元数据锁定是在MySQL的SQL层处理的,而不是在存储引擎层中处理的。

所以发生的情况是,有一个长期运行的事务在您的表上持有一个元数据锁。所有事务都持有共享元数据锁。因此事务可以并发运行,因为它们不相互阻塞。但是,当您试图更改表时,它请求一个独占元数据锁。也就是说,它必须是唯一持有元数据锁的。它等待所有当前事务完成并释放它们的元数据锁。因此,任何仍然持有自己的元数据锁的事务都将阻塞ALTER (或任何其他DDL)。

然后,由于ALTER语句“在队列中”等待独占元数据锁,因此它阻止请求共享元数据锁的所有后续事务。因此,您在应用程序中看到的即时堆积。

元数据锁请求在lock_wait_timeout秒之后超时,默认为31536000秒或一年。

我相信在您的第二个测试中所发生的事情是,无论什么长时间运行的事务在完成之前阻塞了ALTER,所以没有理由阻止ALTER。它立即进行,在MySQL的最新版本中,添加列是一个瞬间的更改。

票数 2
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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