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

时间:2011-05-05 17:52:57

标签: mysql locking innodb

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

某些(但不是所有)行都被另一个表的外键引用。

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

将我想要的行复制到备用表也失败了,锁定超时。

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

DELETE FROM mytable WHERE uid_pk = 1 LIMIT 1;

......就在这一点上,我已经没有想法了。

编辑:为了它的价值,我一直在我的开发系统上完成这个工作,所以现在我只是在实际使用数据库所以不应该在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$$

注意,尝试放弃FK也会超时。

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

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

  1. 停止使用MySQL Workbench(他们的硬编码执行超时为30秒)
  2. 打开命令提示符
  3. 使用ALTER TABLE
  4. 重命名“完整”表
  5. 使用原始表名和结构
  6. 创建一个空表
  7. 重新启动MySQL
  8. 使用SET AUTOCOMMIT = 0
  9. 关闭'autocommit'
  10. 一次删除有限数量的行,每次成功后都会增加限制
  11. 做了一个COMMIT;在关闭自动提交之后的删除语句之间真的让我进入了一个大事务
  12. 整个努力看起来有点像这样:

    ALTER TABLE `ep411`.`tunknowncustomer` RENAME TO  `ep411`.`tunknowncustomer2`;
    

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

    delimiter $$
    
    CREATE TABLE `tunknowncustomer` (
        ...
     ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
    

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

    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;
    

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

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

    不是一个优雅的解决方案,并没有解决为什么从大表中删除一行甚至失败的原因,但至少我得到了我想要的结果!

相关问题