Mariadb,锁定 table 以进行替换?

Maria DB, locking table for replacement?

我有一个使用 mariaDB10.4.10 INNO_DB table 的 Web 应用程序,它每 5 分钟从脚本更新一次。 该脚本的工作方式如下:

从 table XY 创建一个临时文件 table 并将数据从接收到的 csv 文件写入临时文件 table。写入数据后,脚本启动事务,删除 XY table 并将临时 table 重命名为 XY,然后提交事务。

然而,有时用户在使用该应用程序时会收到“XY table 不存在”错误。

我已经尝试在交易中锁定 XY table,但这并没有改变任何事情。

我该如何解决这个问题?是否有任何类型的锁定(我认为 INNO_DB 不再可能锁定?)

换一种方式。

  1. 创建临时 table(不是临时 table,而是真正的 table)。根据需要填写。没有其他人知道它在那里,你一直都有。
  2. 设置自动提交=0; // 或:锁定 TABLE xy 写入,tempxy 读取;
  3. 从 xy 中删除;
  4. 插入 xy SELECT * 来自 tempxy;
  5. 提交工作; // 或者:解锁 TABLES;
  6. 删除 TABLE tempxy;

这样,其他客户将在第 5 点之前看到旧的 table,然后他们将开始看到新的 table。

如果您使用 LOCK,客户将从第 2 点停到第 5 点,这可能会很糟糕,具体取决于所需时间。

在第 3 点,在某些情况下,您可以通过仅删除 tempxy 中 不是 的行和 运行 INSERT ON DUPLICATE 来优化内容第 4 点的关键更新。

有趣的是,我 另一个有点像你的问题。

自动递增

为防止自增列溢出,可以将COMMIT WORK替换为ALTER TABLE xy AUTO_INCREMENT=。这是一个肮脏的 hack,依赖于 MySQL/MariaDB 中的这个 DDL 命令将 执行一个隐式 COMMIT,紧接着是 DDL 命令本身 。如果没有其他人插入 table,它是完全安全的。如果其他人在您的脚本是 运行 的同一时间插入 table,它 应该 在 MySQL 5.7 和派生版本中是安全的; 它可能不会出现在其他版本和口味中,例如MySQL 8.0 或 Percona.

实际上,您使用从 1 开始的新自动增量填充 tempxy(因为刚刚创建了 tempxy),然后执行 DELETE/INSERT,并将自动增量计数器更新为您刚刚创建的行数已插入。

为了完全确定,您可以在 DDL 命令周围使用协作锁,一方面,其他任何想要执行 INSERT 的人:

script thread                              other thread

SELECT GET_LOCK('xy-ddl', 30);
                                           SELECT GET_LOCK('xy-ddl', 30);
ALTER TABLE `xy` AUTO_INCREMENT=12345;     # thread waits while
                                           # script thread commits
                                           # and runs DDL
SELECT RELEASE_LOCK('xy-ddl');             # thread can acquire lock
                                           INSERT INTO ...
DROP TABLE tempxy;                         # Gets id = 12346
                                           SELECT RELEASE_LOCK('xy-ddl');