如何锁定 InnoDB 表以防止在复制该表时进行更新?

2023-12-01

我想暂时锁定一个表以防止其他并发进程对其进行更改。原因是该表将被复制到临时表,进行更改,然后复制回来(实际上原始表被删除,新表被重命名)。然后,在所有这些完成之后,我想解锁该表,并希望在锁定恢复期间尝试进行任何操作。

我还需要能够从已锁定的表中读取数据以构建新表。

这是我尝试过的,但它似乎不起作用。

$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT);

$mysqli->autocommit(false)

// create a table to hold parts to keep
$q1 = "CREATE TABLE new_table LIKE my_table;";
$res1 = $mysqli ->query($q1);       

// Lock table to avoid concurrent update issues
$q2 = "LOCK TABLE my_table WRITE;";
$res2 = $mysqli ->query($q2);           

// Insert data to keep into new table   
$q3 = "INSERT INTO new_table SELECT * FROM my_table WHERE some_id IN (SELECT ID FROM table2)";
$res3 = $mysqli ->query($q3);

// drop original table
$q4 = "DROP TABLE my_table;";
$res4 = $mysqli ->query($q4);

// rename new table
$q5 = "RENAME TABLE new_table TO my_table;";
$res5 = $mysqli ->query($q5);

$mysqli ->commit(); // commit changes and re-enable autocommit

$q = "UNLOCK TABLES;";
$res = $mysqli ->query($q); 

为了测试,使用 PHPmyadmin,我发出了“SET AUTOCOMMIT=0; LOCK TABLE my_table WRITE;”查询,然后尝试从 my_table 中删除某些内容,我能够这样做。我想阻止这个。此外,发出 lock 语句后,过程的其余部分将失败,并且不会发生任何更改。


很抱歉回答太长,但这需要分多个部分来回答。

1. 关于锁定 InnoDB 表LOCK TABLES一般来说

Using LOCK TABLES与 InnoDB 确实有效,并且可以通过连接到同一服务器的 MySQL CLI 的两个实例进行演示(由mysql-1 and mysql-2)在下面的例子中。由于对客户的影响,通常应该在任何类型的生产环境中避免它,但有时它可能是唯一的选择。

创建一个表并用一些数据填充它:

mysql-1> create table a (id int not null primary key) engine=innodb;
Query OK, 0 rows affected (0.02 sec)

mysql-1> insert into a (id) values (1), (2), (3);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

锁定表:

mysql-1> lock tables a write;
Query OK, 0 rows affected (0.00 sec)

尝试插入自mysql-2,它将挂起等待锁:

mysql-2> insert into a (id) values (4);

现在解锁表mysql-1:

mysql-1> unlock tables;
Query OK, 0 rows affected (0.00 sec)

最后mysql-2解锁并返回:

Query OK, 1 row affected (6.30 sec)

2.使用phpMyAdmin进行测试

您使用 phpMyAdmin 的测试方法无效,因为 phpMyAdmin 不会在其 Web 界面的查询之间维持与服务器的持久连接。为了使用任何类型的锁定LOCK TABLES, START TRANSACTION等等,您需要在持有锁的同时保持连接。

3. 锁定工作期间需要的所有表

MySQL 锁定表的方式,一旦你使用过LOCK TABLES要显式锁定任何内容,您将无法访问在此期间未显式锁定的任何其他表LOCK ... UNLOCK会议。在上面的示例中,您需要使用:

LOCK TABLES my_table WRITE, new_table WRITE, table2 READ;

(我假设table2子选择中使用的不是拼写错误。)

4. 原子表交换使用RENAME TABLE

另外,我应该注意,使用替换现有表DROP TABLE其次是RENAME TABLE将导致该表短暂不存在,这可能会让希望该表存在的客户端感到困惑。一般来说,这样做会更好:

CREATE TABLE t_new (...);
<Populate t_new using some method>
RENAME TABLE t TO t_old, t_new TO t;
DROP TABLE t_old;

这将执行两个表的原子交换。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何锁定 InnoDB 表以防止在复制该表时进行更新? 的相关文章

随机推荐

  • config.exceptions_app 无法在 Rails 中工作

    我正在尝试为所有 404 和 500 错误呈现自定义错误页面 所以我在ErrorController类中定义了两个方法not found和internal server error class ErrorController lt Appl
  • 在代理处理程序中,如何区分获取属性(var)与调用方法?

    我有以下代码 其中我使用代理对象 代理 来尝试捕获方法调用和属性访问 例子 https jsfiddle net r8j4fzxL 2 function use strict console clear some empty class w
  • Lisp 中的 setq 和 defvar

    我看到实用 Common Lisp uses defvar db nil 用于设置一个全局变量 使用不是可以吗setq为了同样的目的 使用的优点 缺点是什么defvar vs setq 引入变量的方法有多种 DEFVAR and 定义参数介
  • 为什么两个表之间的完全外连接结果中有NULL?

    我试图从两个表中获取唯一值 这两个表都只有一列称为域 DDL create table domains 1 domain varchar create table domains 2 domain varchar DML insert in
  • 使用htaccess将目录传递给GET参数而不重写url

    我想传递 而不是重定向 这样的东西 http www example com 有 可选 传递给脚本http www example com index php http www example com foo 有 可选 传递给脚本http
  • Python 等语言如何克服 C 的整数数据限制?

    使用 C Python 和 Scheme 中的阶乘程序进行一些随机实验 我发现了这个事实 在 C 中 使用 unsigned long long 数据类型 我可以打印的最大阶乘为 65 即 9223372036854775808 即指定的
  • 实施重试例程

    我有以下想法 是否可以在 python 中实现重试例程 这是我所做的一个简单示例 我想要一个更灵活的解决方案 独立于功能 因此 将removeFile 与任何其他函数切换 并摆脱main 中的while 循环 import os impor
  • 显示git中每个分支的最新提交

    有没有办法显示git中每个分支的最新提交 我在 git 中有一个代码库 我已经设置了一段时间了 其中有几个分支用于不同的功能 我需要进去更新 排除一些代码的问题 但是我选择将它们命名得太笼统 现在我不知道我最后在处理哪一个 甚至不知道哪一个
  • 不能直接使用Function.prototype.call

    function f a return a f 1 gt 1 f call null 1 gt 1 Function prototype call f null 1 gt undefined 为什么最后一行返回undefined 我以为它们
  • 批处理脚本列出本地硬盘驱动器,然后在每个驱动器上执行 dir 命令

    我尝试根据这个主题制作一个脚本 用于查找已安装设备的驱动器号的批处理脚本 但并没有真正的成功 这是脚本 SETLOCAL EnableDelayedExpansion for f usebackq tokens 1 i in fsutil
  • 无法通过多处理同时调用多个函数

    我试图弄清楚如何在同一时间多次运行相同的函数 我可以使用基于其他问题的多处理来实现一些东西 但不幸的是它不能按我想要的方式工作 实际上 当我运行它时 我得到类似这样的东西 函数在每个其他函数之后运行 Worker1 0 1 1 1 2 1
  • delphi中的多种形式

    在我的Delphi项目中 我想要一个 设置 按钮 单击该按钮时 会打开第二个表单 我认为这是正确的术语 我本质上想要打开一个新窗口 进行设置 当用户完成更改此新表单上的设置后 我希望单击按钮即可关闭该表单 用户输入的设置也需要能够被第一个
  • UITextView最大高度

    I use a UITextView在我的应用程序中 我根据文本的大小设置它的框架 然而 如果UITextView size height大于 8192 0 文本就会消失 Does UITextView有最大高度吗 EDIT 我很感谢到目前
  • Android TrafficStats.getTotalRxBytes() 低于预期

    我正在尝试获取真实的流量统计数据 但是 TrafficStats getTotalRxBytes 小于每个已安装应用程序的 TrafficStats getUidRxBytes 之和 我通过每 30 秒运行一次这段代码 在 Wi Fi 网络
  • 如何将数据从免安装应用程序恢复到已安装的应用程序?

    应用安装后保留用户状态 https developer android com topic instant apps ux best practices html keep user state after app installation
  • 通过 Swig 在 C++ 和 Lua 之间传递变量

    我正在开发一个包含大量类 150 的 C 项目 每个类都有 10 到 300 个字段左右 我真的希望能够提供一个用于测试目的的脚本接口 以便我可以编写不需要任何重新编译的回调代码 我想在 Lua 中执行此操作 因为我对它的 C API 比对
  • 以编程方式扩展 BIML 文件

    有没有人尝试过以编程方式将 BIML 文件编译成 dtsx 包 我目前正在 C NET 中编写一个应用程序 用户可以在其中更新元数据 更新此数据后 需要重新编译 BIML 文件 因为重新编译时将添加 删除 SSIS 包 在另一个SO问题中
  • 使用“rle”函数和“dplyr”“group_by”命令来映射分组变量

    我有一个包含三列的数据框 其信息类似于下面给出的数据框 现在我希望根据列中的信息提取信息搜索模式a 基于少数开发人员 thelatemail 和 David T 的支持 我能够识别该模式rle函数 请看这里 使用 rle 函数识别模式 现在
  • 正则表达式 match() 在 FF/Chrome 中有效,但在 IE 8 中无效

    我有以下 jQuery 调用 它在 FF Chrome 中返回匹配项 但在 IE 8 中返回 null 这是小提琴如果您想亲自尝试一下 这是不可解决的 不灵活的 任性的代码 var m somediv text match d d sof
  • 如何锁定 InnoDB 表以防止在复制该表时进行更新?

    我想暂时锁定一个表以防止其他并发进程对其进行更改 原因是该表将被复制到临时表 进行更改 然后复制回来 实际上原始表被删除 新表被重命名 然后 在所有这些完成之后 我想解锁该表 并希望在锁定恢复期间尝试进行任何操作 我还需要能够从已锁定的表中