简体   繁体   English

从具有数百万条记录的表中删除

[英]Deleting from table with millions of records

I'm trying to find a way to do a conditional DELETE on an InnoDB table which contains millions of records, without locking it (thus not bringing the website down).我试图找到一种方法对包含数百万条记录的 InnoDB 表执行条件 DELETE,而不锁定它(因此不会关闭网站)。

I've tried to find information on mysql.com, but to no avail.我试图在 mysql.com 上查找信息,但无济于事。 Any tips on how to proceed?有关如何进行的任何提示?

I don't think it is possible to delete without locking.我认为不加锁就可以删除。 That said, I don't think locking the record you want to delete is a problem.也就是说,我认为锁定要删除的记录不是问题。 What would be a problem is locking other rows.锁定其他行会出现问题。

I found some information on that subject here: http://dev.mysql.com/doc/refman/5.0/en/innodb-locks-set.html我在这里找到了有关该主题的一些信息: http : //dev.mysql.com/doc/refman/5.0/en/innodb-locks-set.html

What I would suggest, is to try and do a million single row deletes.我的建议是尝试进行一百万次单行删除。 I think that if you do all those in a single transaction, performance should not hurt too much.我认为如果你在一个事务中完成所有这些,性能应该不会受到太大影响。 so you would get something like:所以你会得到类似的东西:

START TRANSACTION;

DELETE FROM tab WHERE id = 1;
..
..
DELETE FROM tab WHERE id = x;

COMMIT;

You can generate the required statments by doing something like您可以通过执行类似的操作来生成所需的语句

SELECT CONCAT('DELETE FROM tab WHERE id = ', id)
FROM   tab
WHERE  <some intricate condition that selects the set you want to delete>

So the advantage over this method instead of doing:所以优于这种方法而不是这样做:

DELETE FROM tab 
WHERE  <some intricate condition that selects the set you want to delete>

is that in the first approach you only ever lock the record you're deleting, whereas in the second approach you could run the risk of locking other records that happen to be in the same range as the rows you are deleteing.是在第一种方法中,您只锁定要删除的记录,而在第二种方法中,您可能会冒着锁定恰好与要删除的行在同一范围内的其他记录的风险。

If it fits your application, then you could limit the number of rows to delete, and setup a cronjob for repeating the deletion.如果它适合您的应用程序,那么您可以限制要删除的行数,并设置一个重复删除的 cronjob。 Eg:例如:

DELETE FROM tab WHERE .. LIMIT 1000

I found this to be good compromise in a similar scenario.我发现在类似的情况下这是一个很好的妥协。

I use procedure to delete我用程序删除

create procedure delete_last_year_data() 
begin
  DECLARE del_row varchar(255);
  DECLARE done INT DEFAULT 0;

  declare del_rows cursor for select CONCAT('DELETE FROM table_name WHERE id = ', id)
                            from table_name 
                            where created_time < '2018-01-01 00:00:00';
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  open del_rows;

  repeat
    fetch del_rows into del_row;
    if not done
    then
      set @del = del_row;
      prepare stmt from @del;
      execute stmt;
      DEALLOCATE PREPARE stmt;
    end if;
  until done end repeat;

  close del_rows;

end //结尾 //

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM