Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从包含数百万条记录的表中删除_Sql_Mysql - Fatal编程技术网

Sql 从包含数百万条记录的表中删除

Sql 从包含数百万条记录的表中删除,sql,mysql,Sql,Mysql,我试图找到一种方法,在一个包含数百万条记录的InnoDB表上执行条件删除,而不锁定它(因此不会关闭网站) 我试图在mysql.com上查找信息,但没有结果。关于如何继续的任何提示?如果它适合您的应用程序,那么您可以限制要删除的行数,并设置一个cronjob以重复删除。例如: DELETE FROM tab WHERE .. LIMIT 1000 我发现在类似的情况下,这是一个很好的折衷方案。我认为不锁定就删除是不可能的。也就是说,我不认为锁定要删除的记录是一个问题。锁定其他行将是一个问题 我在

我试图找到一种方法,在一个包含数百万条记录的InnoDB表上执行条件删除,而不锁定它(因此不会关闭网站)


我试图在mysql.com上查找信息,但没有结果。关于如何继续的任何提示?

如果它适合您的应用程序,那么您可以限制要删除的行数,并设置一个cronjob以重复删除。例如:

DELETE FROM tab WHERE .. LIMIT 1000

我发现在类似的情况下,这是一个很好的折衷方案。

我认为不锁定就删除是不可能的。也就是说,我不认为锁定要删除的记录是一个问题。锁定其他行将是一个问题

我在这里找到了一些关于这个主题的信息:

我的建议是,尝试执行一百万次单行删除。我认为,如果您在一个事务中完成所有这些操作,那么性能应该不会受到太大的影响。所以你会得到这样的结果:

START TRANSACTION;

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

COMMIT;
您可以通过执行以下操作来生成所需的stations

SELECT CONCAT('DELETE FROM tab WHERE id = ', id)
FROM   tab
WHERE  <some intricate condition that selects the set you want to delete>
选择CONCAT('DELETE FROM tab WHERE id=',id)
从选项卡
哪里
因此,与此方法相比,该方法的优势在于:

DELETE FROM tab 
WHERE  <some intricate condition that selects the set you want 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;
create procedure delete\u last\u year\u data()
开始
声明del_row varchar(255);
声明完成INT默认值为0;
声明select CONCAT的del_行光标('DELETE FROM table_name WHERE id=',id)
从表\u名称
创建时间为<'2018-01-01 00:00:00';
为未找到的集合声明CONTINUE处理程序done=1;
打开delu行;
重复
将删除行提取到删除行中;
如果不这样做
然后
设置@del=del_行;
从@del准备stmt;
执行stmt;
解除分配准备stmt;
如果结束;
直到完成为止重复;
关闭Delu行;

end/

此表上有很多索引吗?为将处理条件的列编制索引。然后在站点的流量较低时执行删除操作(可能是@night)。另请参阅其中提到的间隙锁定。我认为这种方法的问题是,在隔离集合后评估限制。因此,应用了
其中的
,这可能会锁定恰好与要删除的行在同一范围内的行。然后只删除有限数量的记录,这一事实不会改变记录已被锁定的事实。这种方法所做的是保持事务大小较小,这也是很好的。但据我所知,这并不能防止假锁。@Roland:你可能是对的。此解决方案可能并不理想,但在实践中效果很好(有限删除速度很快,因此锁会在很短的时间间隔内保持,限制参数可以调整到实际数据)。在使用这种方法之前,我做了一些基准测试,所有有限删除的累积时间比单个非有限删除完成的时间要短(但此时,它使用了MySQL 3.x和MyISAM表)。它仍然可以工作,但在当前MySQL和InnoDB表上进行基准测试将为细节带来一些启发。是的,我认为可以肯定地说,您描述的场景,与同时具有多版本并发控制和行级锁定功能的InnoDB引擎相比,该产品9年以上旧版本上的表锁定MyISAM引擎可能确实有所不同:p+1,有希望的解决方案!你曾经在实践中使用过这种方法吗?@frunsi:我承认我没有。通常,我不会对删除一百万行有太大的问题,但我管理的系统不会同时受到许多用户的攻击。