存储过程会不时挂起。有什么建议吗?
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 products 哪里 isbn = NAME_CONST(' p_isbn',_ utf8' 973-679-50 | 0.000 |
| 1133136 |用户名| sqlhost:52466 |数据库_emindb |查询| 18694 |发送数据| SELECT IFNULL(id,0)INTO bookId FROM products 哪里 isbn = NAME_CONST(' p_isbn',_ utf8' 606-92266- | 0.000 |
答案 0 :(得分:1)
首先,我想提一下Percona toolkit,它非常适合调试死锁和挂起事务。其次,我猜想在挂起时,有多个线程执行相同的过程。我们需要知道的是,在挂起时获取了哪些锁。 MySQL命令SHOW INNODB STATUS为您提供详细信息。在下一个'挂起',运行此命令。
我几乎忘记提及innotop工具,它类似但更好:https://github.com/innotop/innotop
接下来,我假设你是InnoDB引擎。在这种情况下,REPEATABLE READ的默认事务隔离级别可能因为范围锁定而过高,您可以考虑尝试对程序主体执行READ COMMITTED(SET在开头提交READ COMMITTED并在结束时返回REPEATABLE READ)。
最后,也许最重要的是,请注意您的过程使用相同的p_isbn值在同一个表上执行SELECT和UPDATE(以混合顺序)。想象一下,如果此过程同时运行 - 这是一个完美的死锁设置。