Java 为什么选择等待锁定?

Java 为什么选择等待锁定?,java,mysql,select,locking,innodb,Java,Mysql,Select,Locking,Innodb,在我的应用程序中,有时SELECT语句会运行到java.sql.SQLException:Lock wait timeout extered;尝试重新启动事务异常。遗憾的是,我无法创建一个例子,因为情况非常复杂。所以问题只是关于一般的理解 一点背景信息:我正在使用MySQL(InnoDB)和READ_Committed隔离级别 事实上,我不明白SELECT怎么会在这种设置下运行到锁定超时。我认为SELECT永远不会锁定,因为它只会返回最新的committed状态(由MySQL管理)。不管怎么说,

在我的应用程序中,有时SELECT语句会运行到
java.sql.SQLException:Lock wait timeout extered;尝试重新启动事务
异常。遗憾的是,我无法创建一个例子,因为情况非常复杂。所以问题只是关于一般的理解

一点背景信息:我正在使用MySQL(InnoDB)和READ_Committed隔离级别

事实上,我不明白SELECT怎么会在这种设置下运行到锁定超时。我认为SELECT永远不会锁定,因为它只会返回最新的committed状态(由MySQL管理)。不管怎么说,根据正在发生的事情来看,这似乎是错误的。那么它到底是怎样的呢


我已经读过了,但这并没有给我一点线索。否<代码>选择。。。用于更新或类似的内容。

这可能是由于您的数据库。通常这类问题都是从那方面来的,而不是从访问它的编程方面来的。根据我对db的经验,这些问题通常都是由这方面造成的。最后,编程方面只是“在db中为我获取那个”

我不费吹灰之力就找到了

它基本上解释为:

锁定等待超时
通常发生在事务正在等待已被其他事务锁定的数据行进行更新时

您还应该检查是否存在特定的事务问题,这可能会对您有所帮助,因为尝试更改不同的表可能会导致超时

查询试图更改一个或多个InnoDB表中的至少一行。因为您知道这个查询,所以所有被访问的表都可能是罪魁祸首


为了加快数据库中的查询速度,可以同时执行多个事务。例如,如果有人在一个表上运行select查询,查询公司员工的工资(每个员工由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在以后的尝试中能够成功。

基本上是对的,但在我的情况下,我在使用
选择
时得到了锁。我很清楚它在更改内容时是如何工作的,但如何锁定
选择
?据我所知,这种情况不应该发生。据我所知,如果它在更新时被锁定,因为它已被锁定,那么它可能与select一样工作。它试图选择一个已锁定的事务,因此它正在等待它解锁,因此它将锁定。至少,这对我来说是有意义的。。。您是否检查了该选择之前进行的所有交易@Werzi2001据我所知,“正常”写锁不应影响
SELECT
语句。我还可以在小测试用例中确认这一点。检查所有事务实际上是不可能的,因为它只发生在生产过程中的重载期间。因此可能有数百个相关交易。我想问题可能恰恰是。。。可能会有人担心交易是相关的。。。可能某个事务已访问以进行编辑/更新,并且select正在等待。类似于死锁的东西。就我所知@Werzi2001很抱歉不能为您提供更多帮助。无需道歉。据我目前的理解,
SELECT
不应锁定-无论其他事务如何执行。但是根据@Lukas所写的,这可能是不正确的。这听起来很合理,尽管这让我有点难过。我认为数据库会实现类似“写时复制”的功能,以保留旧状态,直到新状态完全写入且有效。您能提供使用InnoDB产生这种效果的步骤吗?这是一个MVCC实现,在这个实现中,编写者不应该阻止读卡器。我没有观察到像您描述的那样,更新锁定了所有SELECT语句。遗憾的是,我不能提供一个示例,因为整个系统非常复杂,即使这样,它也很少发生。这是不可复制的。我是指Lukas的评论,询问如何在InnoDB中显示阻止并发读取的更新的示例。根据我的经验,在InnoDB中不会发生这种情况。您是否在另一个会话中使用
锁表
?这将导致一个
SELECT
被阻止,当它在
lock\u wait\u timeout
秒后超时时,它将返回您显示的错误。不,我不手动锁定。我知道的唯一其他方法是