在我的应用程序中,我遇到了有时SELECT语句遇到异常的问题。可悲的是,我无法创建一个例子,因为情况非常复杂。所以问题只是关于一般理解。java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction一点背景信息:我正在使用具有READ_COMMITED隔离级别的MySQL(InnoDB)。实际上,我不明白SELECT如何通过该设置遇到锁定超时。我以为SELECT永远不会锁定,因为它只会返回最新的提交状态(由MySQL管理)。无论如何,根据正在发生的事情,这似乎是错误的。那么它到底是怎么回事呢?我已经读过这个 https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html 但这并没有真正给我一个线索。没有或类似的东西被使用。SELECT ... FOR UPDATE
2 回答
一只名叫tom的猫
TA贡献1906条经验 获得超3个赞
为了加快数据库中的查询速度,可以同时执行多个事务。例如,如果有人对公司员工的工资表运行选择查询(每个员工由id标识),而另一个更改了例如已婚人士的姓氏,则可以同时执行这两个查询,因为它们不会干扰。
但在其他情况下,即使是 SELECT 语句也可能会干扰另一个语句。
为了防止SQL事务中的意外结果,事务遵循ACID模型,该模型代表原子性,一致性,隔离性和持久性(有关更多信息,请阅读维基百科)。
假设事务 1 开始计算某些内容,然后想要将结果写入表 A。在编写之前,它会将所有 SELECT 语句锁定到表 A。否则,这会干扰隔离要求。因为如果事务 2 在 1 仍在写入时启动,则 2 的结果取决于 1 已写入的位置和未写入的位置。
现在,它甚至可能产生死锁。例如,在事务 1 可以写入表 A 中的最后一个字段之前,它仍然必须向表 B 写入一些内容,但事务 2 已经阻止了表 B 在从 A 读取后安全地读取表 B,现在你有一个死锁。2 想要从被 1 阻止的 A 读取,因此它等待 1 完成,但 1 等待 2 解锁表 B 自行完成。
为了解决这个问题,一种策略是在某个超时后回滚某些事务。(更多这里)
因此,这可能是您的 select 语句的读取,以获得超过锁定等待超时。
但是死锁通常只是巧合发生的,所以如果事务 2 被迫回滚,事务 1 应该能够完成,以便 2 应该能够在以后的尝试中成功。
添加回答
举报
0/150
提交
取消
