代码之家  ›  专栏  ›  技术社区  ›  kasdega

Mysql存储过程更新并返回匹配行的列表

  •  0
  • kasdega  · 技术社区  · 6 年前

    这个存储过程的主要原因是选择和更新行,这样我们就不会同时得到多个处理器选择的同一行。

    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
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Tano Fotang    6 年前

    作为第一步,

    1. 在列上有“索引”可能会有所帮助:status和 公司ID。如果没有索引,可以使用以下方法创建索引:

      alter table select_and_start_non_started add index (status);
      alter table select_and_start_non_started add index(companyid);
      
    2. p\u companyId是一个整数,所以我不知道为什么要计算它的长度。无论如何,由于LENGTH(p\u companyId)是一个常量,因此您可能希望将其保存在一个变量中,而不是为每一行调用它:

    declare v_companyid_len int;
    set v_companyid_len=LENGTH(p_companyId);
    BEGIN
    DECLARE queue_csr CURSOR FOR .... AND if(v_companyid_len>0 ...