在我的應用程序中,我遇到了有時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
提交
取消