Mysql - Spring 引导 - 从代码执行存储过程与实际启动之间的未知延迟
Mysql - Spring Boot - Unknown delay between Stored procedure execution from code and actual start
我有一个 Spring 引导应用程序,其中 mysql 作为数据库。为了实现某些要求,我在 MySql 中实现了一个存储过程并通过我的 spring 启动代码触发它。
但是,我观察到的是,在我的 spring 启动代码被触发后,mysql 空闲了大约 90 秒。在该过程执行开始之后。这会减慢系统速度。如果这是预期的或者我做错了什么,有什么建议。
下面是我的 spring 调用过程的代码
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void backFillClosingStock(String dbName, String id_list) throws Exception {
try {
ThreadLocalStorage.setTenantName(dbName);
log.info("Starting backfilling closing stock");
StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery("update_closing_stock");
storedProcedure.registerStoredProcedureParameter("id_list", String.class, ParameterMode.IN);
storedProcedure.setParameter("id_list", id_list );
storedProcedure.execute();
ThreadLocalStorage.setTenantName(null);
log.info("Completed backfilling closing stock");
} catch (Exception e) {
throw new Exception("something went wrong!");
}
下面是我的存储过程。
DELIMITER //
DROP PROCEDURE IF EXISTS update_closing_stock//
CREATE PROCEDURE update_closing_stock(id_list TEXT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE entryid1 decimal;
DECLARE oldClosingStock decimal;
DECLARE newClosingStock decimal;
DECLARE isValueChanged INT DEFAULT 0;
DECLARE cur CURSOR FOR SELECT entryid FROM inward_outward_entries WHERE FIND_IN_SET(productId,id_list)>0 AND is_deleted=0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET autocommit=0;
TRUNCATE temp;
INSERT INTO temp VALUES (CONCAT('Procedure Started ',SYSDATE()));
OPEN cur;
ins_loop: LOOP
FETCH cur INTO entryid1;
IF done THEN
LEAVE ins_loop;
END IF;
SELECT
bs1.closingStock as oldClosingStock,
CASE WHEN bs1.type='Inward' THEN(
(SELECT CASE WHEN SUM(bs2.quantity) IS NULL THEN 0 ELSE SUM(bs2.quantity) END FROM backfill_closing_stock bs2
WHERE bs2.id>=bs1.id AND bs2.type='Inward' AND bs1.Productid=bs2.productid AND bs2.warehouseid=bs1.warehouseid)
-
(SELECT CASE WHEN SUM(bs2.quantity)IS NULL THEN 0 ELSE SUM(bs2.quantity) END FROM backfill_closing_stock bs2
WHERE bs2.id>bs1.id AND bs2.type!='Inward' AND bs1.Productid=bs2.productid AND bs2.warehouseid=bs1.warehouseid)
)
ELSE (
(SELECT CASE WHEN SUM(bs2.quantity) IS NULL THEN 0 ELSE SUM(bs2.quantity) END FROM backfill_closing_stock bs2
WHERE bs2.id>bs1.id AND bs2.type='Inward' AND bs1.Productid=bs2.productid AND bs2.warehouseid=bs1.warehouseid)
-
(SELECT CASE WHEN SUM(bs2.quantity) IS NULL THEN 0 ELSE SUM(bs2.quantity) END FROM backfill_closing_stock bs2
WHERE bs2.id>=bs1.id AND bs2.type!='Inward' AND bs1.Productid=bs2.productid AND bs2.warehouseid=bs1.warehouseid)
)
END AS closingStock
INTO oldClosingStock,newClosingStock
FROM backfill_closing_stock bs1 WHERE bs1.entryid=entryid1;
IF newClosingStock>=0 AND newClosingStock<>oldClosingStock THEN
UPDATE inward_outward_entries SET closingStock = newClosingStock WHERE entryid=entryid1;
END IF;
END LOOP;
CLOSE cur;
TRUNCATE all_inventory_table;
INSERT INTO all_inventory_table SELECT * FROM all_inventory;
SET autocommit=1;
END;
我在第 13 行和第 14 行分别有两个命令。用于截断 table 并向其中插入记录以进行调试。我可以看到 table 立即被截断,但仅在执行 90 秒后才将带有文本“Procedure Started”的记录插入到临时 table 中。不确定哪里出错了
以下是我的日志片段
2022-01-27 09:49:33,165 INFO [Async-1] com.ec.application.service.AsyncServiceInventory: Before Procedure Start -2022-01-27T10:12:58.616
这表明程序是从 spring 在 10:12:58
触发的
但是当我检查临时 table 时,我没有看到在接下来的 90 秒内插入任何记录。在那之后,比如在 10:14:30,我看到一条记录被插入了过去的时间“程序开始于 2022-01-27 10:12:58'”
我不确定这 90 秒发生了什么。有什么建议吗?
TRUNCATE
(和其他 DDL 语句)中断提交——至少在 MySQL 8.0
之前
autocommit=0
是 error-prone -- 如果您稍后忘记 COMMIT
,可能会发生不好的事情。
所以,不要理会 autocommit
并结束 TRUNCATE。然后做
START TRANSACTION;
do all the rest of the work
COMMIT;
但是为了获得真正的性能提升,找到一种重写它的方法,这样您就不需要游标了。光标很慢。
我有一个 Spring 引导应用程序,其中 mysql 作为数据库。为了实现某些要求,我在 MySql 中实现了一个存储过程并通过我的 spring 启动代码触发它。
但是,我观察到的是,在我的 spring 启动代码被触发后,mysql 空闲了大约 90 秒。在该过程执行开始之后。这会减慢系统速度。如果这是预期的或者我做错了什么,有什么建议。
下面是我的 spring 调用过程的代码
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void backFillClosingStock(String dbName, String id_list) throws Exception {
try {
ThreadLocalStorage.setTenantName(dbName);
log.info("Starting backfilling closing stock");
StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery("update_closing_stock");
storedProcedure.registerStoredProcedureParameter("id_list", String.class, ParameterMode.IN);
storedProcedure.setParameter("id_list", id_list );
storedProcedure.execute();
ThreadLocalStorage.setTenantName(null);
log.info("Completed backfilling closing stock");
} catch (Exception e) {
throw new Exception("something went wrong!");
}
下面是我的存储过程。
DELIMITER //
DROP PROCEDURE IF EXISTS update_closing_stock//
CREATE PROCEDURE update_closing_stock(id_list TEXT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE entryid1 decimal;
DECLARE oldClosingStock decimal;
DECLARE newClosingStock decimal;
DECLARE isValueChanged INT DEFAULT 0;
DECLARE cur CURSOR FOR SELECT entryid FROM inward_outward_entries WHERE FIND_IN_SET(productId,id_list)>0 AND is_deleted=0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET autocommit=0;
TRUNCATE temp;
INSERT INTO temp VALUES (CONCAT('Procedure Started ',SYSDATE()));
OPEN cur;
ins_loop: LOOP
FETCH cur INTO entryid1;
IF done THEN
LEAVE ins_loop;
END IF;
SELECT
bs1.closingStock as oldClosingStock,
CASE WHEN bs1.type='Inward' THEN(
(SELECT CASE WHEN SUM(bs2.quantity) IS NULL THEN 0 ELSE SUM(bs2.quantity) END FROM backfill_closing_stock bs2
WHERE bs2.id>=bs1.id AND bs2.type='Inward' AND bs1.Productid=bs2.productid AND bs2.warehouseid=bs1.warehouseid)
-
(SELECT CASE WHEN SUM(bs2.quantity)IS NULL THEN 0 ELSE SUM(bs2.quantity) END FROM backfill_closing_stock bs2
WHERE bs2.id>bs1.id AND bs2.type!='Inward' AND bs1.Productid=bs2.productid AND bs2.warehouseid=bs1.warehouseid)
)
ELSE (
(SELECT CASE WHEN SUM(bs2.quantity) IS NULL THEN 0 ELSE SUM(bs2.quantity) END FROM backfill_closing_stock bs2
WHERE bs2.id>bs1.id AND bs2.type='Inward' AND bs1.Productid=bs2.productid AND bs2.warehouseid=bs1.warehouseid)
-
(SELECT CASE WHEN SUM(bs2.quantity) IS NULL THEN 0 ELSE SUM(bs2.quantity) END FROM backfill_closing_stock bs2
WHERE bs2.id>=bs1.id AND bs2.type!='Inward' AND bs1.Productid=bs2.productid AND bs2.warehouseid=bs1.warehouseid)
)
END AS closingStock
INTO oldClosingStock,newClosingStock
FROM backfill_closing_stock bs1 WHERE bs1.entryid=entryid1;
IF newClosingStock>=0 AND newClosingStock<>oldClosingStock THEN
UPDATE inward_outward_entries SET closingStock = newClosingStock WHERE entryid=entryid1;
END IF;
END LOOP;
CLOSE cur;
TRUNCATE all_inventory_table;
INSERT INTO all_inventory_table SELECT * FROM all_inventory;
SET autocommit=1;
END;
我在第 13 行和第 14 行分别有两个命令。用于截断 table 并向其中插入记录以进行调试。我可以看到 table 立即被截断,但仅在执行 90 秒后才将带有文本“Procedure Started”的记录插入到临时 table 中。不确定哪里出错了
以下是我的日志片段
2022-01-27 09:49:33,165 INFO [Async-1] com.ec.application.service.AsyncServiceInventory: Before Procedure Start -2022-01-27T10:12:58.616
这表明程序是从 spring 在 10:12:58
触发的但是当我检查临时 table 时,我没有看到在接下来的 90 秒内插入任何记录。在那之后,比如在 10:14:30,我看到一条记录被插入了过去的时间“程序开始于 2022-01-27 10:12:58'”
我不确定这 90 秒发生了什么。有什么建议吗?
TRUNCATE
(和其他 DDL 语句)中断提交——至少在 MySQL 8.0
autocommit=0
是 error-prone -- 如果您稍后忘记 COMMIT
,可能会发生不好的事情。
所以,不要理会 autocommit
并结束 TRUNCATE。然后做
START TRANSACTION;
do all the rest of the work
COMMIT;
但是为了获得真正的性能提升,找到一种重写它的方法,这样您就不需要游标了。光标很慢。