【问题标题】:MySQL transactions in a stored procedure存储过程中的 MySQL 事务
【发布时间】:2021-06-02 04:37:59
【问题描述】:

我有一个存储过程,它从多个来源收集数据,转换并最终删除,然后将数据转储到 TableA 在此存储过程运行时,其他用户经常对TableA 执行选择查询,从而导致死锁,从而导致存储过程失败。

我的存储过程在开始时确实使用了SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;,但它似乎不起作用或者我使用错误。

如果不使用READ/WRITE LOCKS,有什么方法可以确保不会发生这种情况?

MySQL 版本:5.7.23-enterprise-commercial-advanced-log

【问题讨论】:

  • 在可能陷入死锁的操作之前立即锁定表,并在之后立即解锁。或者提高事务级别 - 甚至可能直到可序列化。
  • @Akina 你能详细说明一下“增加事务级别”部分吗?

标签: mysql isolation-level database-deadlocks


【解决方案1】:

我有很多 cmets:

  • 我假设您使用的是SELECT ... FOR UPDATE,因为没有可选的锁定子句,SELECT 不会获取行锁,因此不会导致死锁。

  • 没有FOR UPDATE 子句的其他读取查询不需要行锁。它们不会导致死锁。

  • 为了防止死锁,您需要使用原子锁。考虑LOCK TABLES

  • 更改隔离级别对当前运行的事务没有影响。如果您已经有一个事务在进行中,则不能即时更改其隔离级别。对隔离级别的更改仅适用于您随后开始的事务。

  • READ UNCOMMITTED 隔离级别并不能消除查询获取锁的需要,如果它们需要其他隔离级别的锁。

  • 在使用 MySQL 的 20 多年中,我从未发现 READ UNCOMMITTED 的合法用途。我避免它。

【讨论】:

  • 简单的SELECT 导致了这个问题。 LOCK TABLE WRITE 似乎确实解决了这个问题,但这是我最后的手段。我仍然不确定为什么TRANSACTION 没有按预期工作,并且想在这里找出正确的用法(如果存在)。关于您的第四点,为了清楚起见,导致死锁的 SELECT 正在另一个会话中运行。
猜你喜欢
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 2020-07-08
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
相关资源
最近更新 更多