我需要每天获取所有过期客户的列表并将它们插入新表中,然后我需要将日期移动一个月,这样它们将在下个月再次处理。

目前我正在连续运行2个SQL查询

insert into history select * from customers where nextdate<CURDATE()
update customers set nextdate=calculation() where nextdate<CURDATE()

但是有时会更新客户,但不会将其插入历史记录。

考虑到更新是在mysql完成选择之前开始运行的。

我正在使用Node js,他正在执行序列化的当前方法是,我正在insert的回调中运行update,但可能在代码实际运行之前先调用insert。

并非每次都发生这种情况,但我认为同时进行存储过程可以有所帮助,任何人都对此有一定的经验?

分析解答

这里有两个问题。首先是您的SELECT和UPDATE不必等待,因为SELECT不会锁定表。您可以通过以下方式强制锁定阅读:

INSERT INTO history SELECT * FROM customers WHERE nextdate<CURDATE() FOR UPDATE;

有关锁定读取的更多信息,请参见https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

第二个问题是您可能还想了解交易,它使您可以发出一批查询,以便使所有查询都得到落实,或者没有一个得到执行。

对于您的代码,您想添加用于发出事务的开始和结束命令:

START TRANSACTION;
INSERT INTO history SELECT * FROM customers WHERE nextdate<CURDATE() FOR UPDATE;
UPDATE customers SET nextdate=calculation() WHERE nextdate<CURDATE();
COMMIT;

有关此机制的所有详细信息,请参见https://dev.mysql.com/doc/refman/5.7/en/commit.html,从MySQL到Postgres到SQLite都支持。