为什么 MySQL 在存储过程中禁止 LOCK TABLES?

Jef*_*eff 5 mysql stored-procedures locking

我已经通读了 MySQL 参考手册的几个部分,虽然它反复声明LOCK TABLES不能在存储过程中使用,但我从未找到其背后推理的解释。

Jef*_*eff 1

太长了;博士

禁止它们是为了防止您无意中导致您可能不希望发生的提交(例如,通过在事务中间调用存储过程)。

从(现已弃用)MySQL 邮件列表复制:

以下是肖恩·格林对我在那儿发的帖子的回答,以及他对同一线程中另一张帖子的回复:

你好杰夫,

2018 年 8 月 13 日 12:05,jeff@stripped 写道:

您好,我已经阅读了参考手册的几页,并且看到了几个例子,其中指出存储过程中不允许锁定表(和解锁表),但到目前为止,我还没有找到解释为什么这样。有人可以启发我吗?

谢谢

通常,该列表比这更具响应性。这是一个非常简单的问题,通常有人会在我需要介入作为后盾之前处理这些问题。

无法在存储程序中执行 LOCK TABLE 命令的关键在于: https: //dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html

LOCK TABLES 不是事务安全的,并且在尝试锁定表之前隐式提交任何活动事务。

存储的程序在启动它们的事务范围内执行。这确定了哪些行集对例程“可见”,并设置了在需要时可以提交或回滚的边界。

(一个简单的例子)

* your session: START TRANSACTION
* your session: ...other data activity ...
* your session (INSERT ... )
   * causes an INSERT trigger to fire
     * which calls a stored procedure
Run Code Online (Sandbox Code Playgroud)

如果该存储过程或触发器调用 LOCK TABLE 命令,它将强制提交您在那一刻之前一直在其中工作的现有事务。即使后面的步骤需要您发出 ROLLBACK 命令,您半完成的工作也将完全提交。

请注意,即使您不在多语句事务中,由用户命令调用或在用户命令范围内执行的任何存储程序都是该小型(自动提交)事务的一部分。

这有帮助吗?

--
Shawn Green
MySQL 高级首席技术支持工程师
Oracle USA, Inc. - 硬件和软件,旨在协同工作。
办公室:田纳西州布朗特维尔


你好摩根斯,

2018 年 8 月 18 日下午 2:32,莫根斯·梅兰德写道:

伙计们,

我想我很久以前就记得这件事了。

您可以要求锁,如果安全的话会得到同意。

比如,如果您的目标表上有待处理的事务,您将得到“否”。

但话又说回来。我可能是错的,肖恩是这方面的权威。

您的锁定请求将等到所有现有读取器或写入器(取决于您请求的锁定类型)完成使用您想要锁定的表。推而广之,这意味着您想要锁定的表上的任何活动事务也需要在您的请求获得批准之前提交或回滚。针对该表的任何新操作都会在您的 LOCK 请求之后排队。这让不止一位 DBA 感到困惑,因为他们没有意识到 LOCK 会成为如此严格的瓶颈。

这些类型的全表锁存在于各个存储引擎或事务控制代码的阻塞/锁定协调之上。它们在我们代码的“服务器层”中进行管理。

这种范围分离是在同一数据管理流程中混合事务性表和非事务性表通常不受欢迎的原因之一。要么是全事务型(InnoDB),要么不是。该行为将更容易预测,从而允许您的开发人员放心地使用事务控制命令(BEGIN/COMMIT/ROLLBACK/...)或 LOCK 命令。

您的,
--
Shawn Green
MySQL 高级首席技术支持工程师
Oracle USA, Inc. - 集成云应用程序和平台服务
办公室:田纳西州布朗特维尔