从大型MySql表中删除单行会导致"锁定超时"

Roc*_*joe 10 mysql innodb locking

我正在运行MySql 5.0.22并且有一个非常笨重的表,包含大约500万行.

某些但不是所有行都由另一个表的外键引用.

到目前为止,所有剔除未引用行的尝试都失败了,每次都会导致锁定超时.

将我想要的行复制到备用表也会因锁定超时而失败.

可疑的是,即使是一个应该像下面那样立即完成的声明也会因"锁定超时"而失败:

DELETE FROM mytable WHERE uid_pk = 1 LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

......就在这时,我已经没有想法了.

编辑:为了它的价值,我一直在我的开发系统上完成这个工作,所以现在只有我实际上在使用数据库所以不应该在我正在运行的SQL之外进行任何锁定.

任何MySql专家都有关于如何驯服这个流氓表的建议?

编辑#2:根据要求,表格结构:

CREATE TABLE `tunknowncustomer` (
  `UID_PK` int(11) NOT NULL auto_increment,
  `UNKNOWNCUSTOMERGUID` varchar(36) NOT NULL,
  `CREATIONDATE` datetime NOT NULL,
  `EMAIL` varchar(100) default NULL,
  `CUSTOMERUID` int(11) default NULL,
  PRIMARY KEY  (`UID_PK`),
  KEY `IUNKNOWCUST_CUID` (`CUSTOMERUID`),
  KEY `IUNKNOWCUST_UCGUID` (`UNKNOWNCUSTOMERGUID`),
  CONSTRAINT `tunknowncustomer_ibfk_1` FOREIGN KEY (`CUSTOMERUID`) REFERENCES `tcustomer` (`UID_PK`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
Run Code Online (Sandbox Code Playgroud)

注意,试图放弃FK也会超时.

小智 5

我对 innodb 表有同样的问题。优化表更正了它。


Roc*_*joe 1

好吧,我终于找到了一种方法,可以从我的大型 InnoDB 表中删除不需要的行!我是这样做的:

  1. 停止使用 MySQL Workbench(它们的硬编码执行超时为 30 秒)
  2. 打开命令提示符
  3. 使用 ALTER TABLE 重命名“完整”表
  4. 使用原始表名称和结构创建一个空表
  5. 重启MySQL
  6. 使用 SET AUTOCOMMIT = 0 关闭“自动提交”
  7. 一次删除有限数量的行,每次成功后都会增加我的限制
  8. 做了 COMMIT;在删除语句之间,因为关闭自动提交确实让我陷入了一个大事务中

整个工作看起来有点像这样:

ALTER TABLE `ep411`.`tunknowncustomer` RENAME TO  `ep411`.`tunknowncustomer2`;
Run Code Online (Sandbox Code Playgroud)

...奇怪的是,重命名表是唯一会立即完成的 ALTER TABLE 命令。

delimiter $$

CREATE TABLE `tunknowncustomer` (
    ...
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
Run Code Online (Sandbox Code Playgroud)

...然后重新启动,以防我之前失败的尝试可能会阻止完成任何新工作...

SET AUTOCOMMIT = 0;

delete from tunknowncustomer2 where customeruid is null limit 1000;

delete from tunknowncustomer2 where customeruid is null limit 100000;

commit;

delete from tunknowncustomer2 where customeruid is null limit 1000000;

delete from tunknowncustomer2 where customeruid is null limit 1000000;

commit;
Run Code Online (Sandbox Code Playgroud)

...一旦我一次删除 100k,InnoDB 的执行时间就会随着每个成功的命令而下降。我假设 InnoDB 开始对大型扫描进行预读。进行提交会重置预读数据,因此我将 COMMIT 间隔为每 200 万行,直到作业完成。

我通过将剩余的行复制到“空”克隆表中,然后删除旧的(重命名的)表来完成任务。

这不是一个优雅的解决方案,它没有解决为什么从大表中删除一行会失败的任何原因,但至少我得到了我正在寻找的结果!