MySQL-在live server上执行密集查询

MySQL-在live server上执行密集查询,mysql,database,large-data,myisam,large-data-volumes,Mysql,Database,Large Data,Myisam,Large Data Volumes,我在MySQL数据库中更新和插入数百万行时遇到了一些问题。我需要标记表A中的5000万行,将标记的5000万行中的一些数据插入表B,然后再次更新表A中的5000万行。表A中约有1.3亿行,表B中约有8000万行 这需要在实时服务器上进行,而不拒绝从网站访问其他查询。问题是,当此存储过程运行时,来自网站的其他查询最终被锁定,HTTP请求超时 以下是SP的要点,为了便于说明,有点简化: CREATE DEFINER=`user`@`localhost` PROCEDURE `MyProcedure`

我在MySQL数据库中更新和插入数百万行时遇到了一些问题。我需要标记表A中的5000万行,将标记的5000万行中的一些数据插入表B,然后再次更新表A中的5000万行。表A中约有1.3亿行,表B中约有8000万行

这需要在实时服务器上进行,而不拒绝从网站访问其他查询。问题是,当此存储过程运行时,来自网站的其他查询最终被锁定,HTTP请求超时

以下是SP的要点,为了便于说明,有点简化:

CREATE DEFINER=`user`@`localhost` PROCEDURE `MyProcedure`(  
  totalLimit  int
)
BEGIN
  SET @totalLimit = totalLimit; 
  /* Prepare new rows to be issued */
  PREPARE STMT FROM 'UPDATE tableA SET `status` = "Being-Issued" WHERE `status` = "Available" LIMIT ?';
  EXECUTE STMT USING @totalLimit;
  /* Insert new rows for usage into tableB */
  INSERT INTO tableB (/* my fields */)
    SELECT /* some values from TableA */ 
    FROM tableA
    WHERE `status` = "Being-Issued";
  /* Set rows as being issued */
  UPDATE tableB SET `status` = 'Issued' WHERE `status` = 'Being-Issued';
END$$

DELIMITER ;

不管您在做什么,三次处理50万行都会很慢

确保您的更新正在影响较小的不相交集。并逐个执行,而不是在同一事务中执行

如果您已经这样做了,而MySQL行为不正常,请尝试对代码进行以下细微调整:

create a temporary table

begin

insert into tmp_table
select your stuff
limit ?
for update

do your update on A using tmp_table

commit

begin
do your insert on B using tmp_table
do your update on A using tmp_table
commit

这应该能将锁保持最短的时间。

这怎么办?它基本上是在循环中调用原始存储过程,直到达到所需的总量,并且在调用之间有一个睡眠周期(如2秒),以允许其他查询进行处理

increment
是一次要做的量(本例中使用10000)
totalLimit
是要处理的总金额
sleepSec
是两次呼叫之间的休息时间

BEGIN
SET @x = 0;
REPEAT
    SELECT SLEEP(sleepSec);
    SET @x = @x + increment;
    CALL OriginalProcedure( increment );

    UNTIL @x >= totalLimit
END REPEAT;
END$$
显然,如果增量不能被平均整除,它可以使用一些数学来确保增量不会超过总限制,但它似乎是有效的(我所说的“有效”是指允许其他查询仍然从web请求中处理),而且总体上看起来也更快


有什么见解吗?这是个好主意吗?坏主意?

这些表使用哪种数据库引擎?
状态也可以变成
tinyint
char(1)
。更新长字符字段的速度较慢。这些是MyISAM表,而状态字段实际上是一个枚举,有3个可能的值,可以将其分解为更小的进程。实际上,我创建了一个存储过程,在较小的卡盘中多次运行另一个存储过程,它的工作效果似乎要好得多(即:运行原始存储过程以处理10000个数据块,直到总共达到5000000个数据块)。它似乎成功地将锁保持在较短的时间内,并允许处理其他查询。“我实际上创建了一个存储过程,在较小的卡盘中多次运行另一个存储过程”--但这将在一个事务中运行整个过程,不是吗?(这正是我的观点…)嗯,这是有道理的。我主要关心的是把所有东西都锁起来,这样网站就不能使用数据库了。你能看看我发布的答案,让我知道你的想法吗?它似乎工作得很好,但你是对的…因为它仍然在一个存储过程中,它将在一个事务中,但它似乎没有保持低cks在表上(这对我很好)。非常感谢您的帮助!!坦率地说,我不确定MySQL将如何处理它。它可能会起作用。我只知道一个事实,当以这种方式处理时,Postgres将在一个事务中处理整件事情,并相应地锁定事情。(出于充分的理由,他们还没有实现存储过程,特别是异步事务。)