How to enforce 2 MySQL queries to run in series

Jew :

I need every day to get a list of all Customers past due and insert them into a new table, then i need to move the dates with one month, so they will be processed next month again.

Currently i am running 2 SQL Queries in series

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

But sometimes customers are updated, but not inserted into history.

In think that the update begin to run before mysql finished the select.

I am using Node js, he current method i am using for serialization, is that i am running the update in the callback from the insert, but probably the insert is called back before the code actually runs.

It doesn't happen every time but i think that making a Stored procedure with both in it can help, anyone had some experience with it?

Mike 'Pomax' Kamermans :

There are two issues here. The first is that your SELECT and UPDATE don't wait for each because SELECT does not lock the table. You can force locked reading by using:

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

See https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html for more information on Locking Reads.

The second is that you probably also want to learn about transactions, which let you issue a batch of queries such that either all of them get committed, or none of them do.

In the case of your code, you want to add the start and end commands for issueing a transaction:

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

See https://dev.mysql.com/doc/refman/5.7/en/commit.html for all the details on this mechanism, which anything from MySQL to Postgres to SQLite supports.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=19494&siteId=1