Я построил эту хранимую процедуру.Предполагается выбрать все незапущенные строки из таблицы, которую мы используем в качестве очереди.Обновите эти строки, чтобы пометить их как «STARTING», чтобы они не были захвачены другим процессором, а затем верните эти строки обратно запрашивающей стороне для обработки.Это работает, но, кажется, создает неприемлемо высокую нагрузку на наши серверы.
Основная причина этой хранимой процедуры - выбор и обновление строк, чтобы мы не получали одну и ту же строку, выбранную несколькими процессорами вв то же время.
Я не администратор баз данных, и мне пришлось на лету изучать некоторые хранимые процедуры и курсоры, поэтому, возможно, я упускаю что-то очевидное для кого-то другого.Я предполагаю, что есть способ сделать это без полной перегрузки наших серверов БД.Любая помощь приветствуется.
Мы используем MySql db 5.6.xx с веб-приложением Java / Tomcat.
CREATE DEFINER=`admin`@`%` PROCEDURE `select_and_start_non_started`(
IN p_companyId INT(11),
IN p_howMany INT,
IN p_instance varchar(50),
IN p_status varchar(50),
IN p_updateBy varchar(50)
)
BEGIN
DECLARE v_currentId INT;
DECLARE v_loopDone INT DEFAULT 0;
DECLARE v_loopCounter INT DEFAULT 0;
DECLARE v_idList VARCHAR(1024) DEFAULT NULL;
DECLARE queue_csr CURSOR FOR
SELECT id FROM queue
WHERE (status in (_utf8'NEW' COLLATE utf8_unicode_ci,
_utf8'RESTARTED' COLLATE utf8_unicode_ci,
_utf8'WAITING' COLLATE utf8_unicode_ci,
_utf8'QUEUED' COLLATE utf8_unicode_ci))
AND if(LENGTH(p_companyId) > 0, companyid=p_companyId, true)
LIMIT p_howMany FOR UPDATE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_loopDone=1;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET autocommit = TRUE;
RESIGNAL;
END;
SET v_idList = "";
SET autocommit = FALSE;
START TRANSACTION;
OPEN queue_csr;
iq_loop:LOOP
FETCH queue_csr INTO v_currentId;
IF v_loopDone THEN LEAVE iq_loop; END IF;
UPDATE queue SET status = p_status COLLATE utf8_unicode_ci, updatedDate=NOW(), updatedBy=p_updateBy, recordStatus=p_instance WHERE id = v_currentId;
SET v_idList = CONCAT(v_idList, ",", v_currentId);
SET v_loopCounter=v_loopCounter+1;
IF v_loopCounter > p_howMany THEN LEAVE iq_loop; END IF;
END LOOP iq_loop;
CLOSE queue_csr;
SET v_loopDone=0;
COMMIT;
SET autocommit = TRUE;
SELECT * FROM queue q WHERE FIND_IN_SET(id, v_idList);
END