2016-11-22 61 views
1

存儲過程不時掛起。任何建議?存儲過程掛起

BEGIN 
DECLARE bookId int; 

SELECT IFNULL(id,0) INTO bookId FROM products 
    WHERE 
     isbn=p_isbn 
    and stoc>0 
    and status='vizibil' 
    and pret_ron=(SELECT MAX(pret_ron) FROM products 
    WHERE isbn=p_isbn 
        and stoc>0 
        and status='vizibil') 
    ORDER BY stoc DESC 

LIMIT 0,1; 

IF bookId>0 THEN 
UPDATE products SET afisat='nu' WHERE isbn=p_isbn; 
UPDATE products SET afisat='da' WHERE id=bookId; 
SELECT bookId INTO obookId; 
ELSE 

SELECT id INTO bookId FROM products 
    WHERE 
     isbn=p_isbn 
    and stoc=0 
    and status='vizibil' 
    and pret_ron=(SELECT MAX(pret_ron) FROM products 
        WHERE isbn=p_isbn 
         and stoc=0 
         and status='vizibil') 
LIMIT 0,1; 
UPDATE products SET afisat='nu' WHERE isbn=p_isbn; 
UPDATE products SET afisat='da' WHERE id=bookId; 
SELECT bookId INTO obookId; 
END IF; 

END 

當它掛起它它: | 23970842 |用戶名| sqlhost:54264 |數據庫|查詢| 65 |發送數據| SELECT IFNULL(ID,0)INTO BOOKID FROM產品WHERE ISBN = NAME_CONST( 'p_isbn',_ utf8'973-679-50 | 0.000 |

| 1133136 |用戶名| SQLHOST:52466 |數據庫_emindb |查詢| 18694 |發送數據| SELECT IFNULL(ID,0)INTO BOOKID FROM產品WHERE ISBN = NAME_CONST( 'p_isbn',_ utf8'606-92266- | 0.000 |

回答

1

首先,我想提的Percona toolkit ,這對調試死鎖和掛起事務非常有用,其次,我猜想在掛起時,有多個線程執行這個相同的過程,我們需要知道的是,在掛起時獲取哪些鎖。MySQL命令SHOW INNODB STATUS爲您提供了詳細信息。在下一次「掛起」中,運行此命令。

我差點忘了提工具innotop,這是類似的,但更好的:https://github.com/innotop/innotop

接下來,我假設你是InnoDB引擎。在這種情況下,由於範圍鎖定,REPEATABLE READ的默認事務隔離級別可能過高,因此您可以考慮嘗試READ COMMITTED以獲取過程主體(SET開始時讀取已提交,最後返回到REPEATABLE READ)。

最後,也許最重要的是,請注意您的過程使用可能相同的p_isbn值在同一個表上執行SELECT和UPDATE(以混合順序)。想象一下,如果這個過程同時運行 - 這是一個完美的死鎖設置。