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 不再可能锁定?)
换一种方式。
- 创建临时 table(不是临时 table,而是真正的 table)。根据需要填写。没有其他人知道它在那里,你一直都有。
- 设置自动提交=0; // 或:锁定 TABLE xy 写入,tempxy 读取;
- 从 xy 中删除;
- 插入 xy SELECT * 来自 tempxy;
- 提交工作; // 或者:解锁 TABLES;
- 删除 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');
我有一个使用 mariaDB10.4.10 INNO_DB table 的 Web 应用程序,它每 5 分钟从脚本更新一次。 该脚本的工作方式如下:
从 table XY 创建一个临时文件 table 并将数据从接收到的 csv 文件写入临时文件 table。写入数据后,脚本启动事务,删除 XY table 并将临时 table 重命名为 XY,然后提交事务。
然而,有时用户在使用该应用程序时会收到“XY table 不存在”错误。
我已经尝试在交易中锁定 XY table,但这并没有改变任何事情。
我该如何解决这个问题?是否有任何类型的锁定(我认为 INNO_DB 不再可能锁定?)
换一种方式。
- 创建临时 table(不是临时 table,而是真正的 table)。根据需要填写。没有其他人知道它在那里,你一直都有。
- 设置自动提交=0; // 或:锁定 TABLE xy 写入,tempxy 读取;
- 从 xy 中删除;
- 插入 xy SELECT * 来自 tempxy;
- 提交工作; // 或者:解锁 TABLES;
- 删除 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');