我正在解决MySQL错误“尝试获取锁时发现死锁;尝试重新启动事务”。
我将不得不更新程序以允许死锁。该SELECT
语句是否可能产生死锁错误?我知道这只是一个读锁,因此多个选择不会有问题,但是如果存在INSERT
,UPDATE
或DELETE
语句(对于联接可能有子查询)和SELECT
语句(对于联接或子查询可能)怎么办?
有没有可能是错误将在被抛出SELECT
,而不是INSERT
,UPDATE
或DELETE
。
我正在解决MySQL错误“尝试获取锁时发现死锁;尝试重新启动事务”。
我将不得不更新程序以允许死锁。该SELECT
语句是否可能产生死锁错误?我知道这只是一个读锁,因此多个选择不会有问题,但是如果存在INSERT
,UPDATE
或DELETE
语句(对于联接可能有子查询)和SELECT
语句(对于联接或子查询可能)怎么办?
有没有可能是错误将在被抛出SELECT
,而不是INSERT
,UPDATE
或DELETE
。
Answers:
您问题标题的直接答案是“否”。
SELECT查询可以对gen_clust_index(也称为聚簇索引)执行锁定。
这是我与@RedBlueThing一起积极询问的三个DBA Stack Exchange 问题。@RedBlueThing找到了解决他的问题的方法。
只是为了使您的问题更直观,当您仔细查看这些答案时(不要看上去太深,即使我自己眼花con乱的答案也令人头晕),应该很快就会发现SELECT查询可以锁定数据。
更新2011-08-08 16:49 EDT
您问了一个变体问题:“在选择条件下,InnoDB死锁异常是否可能被SELECT抛出”,答案可能是“是”。那是什么情况?如果由于错误而仅回滚单个SQL语句,则可以保留该语句设置的某些锁。发生这种情况是因为InnoDB以某种格式存储行锁,使得以后无法知道哪个语句设置了哪个锁。
根据该陈述,导致这种情况的事件顺序理论上可以如下:
就个人而言,最后的陈述使我感到恐惧。对于MySQL来说,将这个怪癖告知每个人本来很好。但是,该声明来自MySQL文档。(哦,是的,Oracle拥有InnoDB)
今年早些时候,我了解到Percona有一个不错的Nagios支票,可以发现这些讨厌的锁藏在睡眠连接的后面。您现在要做的就是从该链接运行代码:
SELECT COALESCE(MAX(IF(p.command = 'Sleep', p.time, 0)), 0) AS idle_in_trx
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS AS w
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX AS b ON b.trx_id = w.blocking_trx_id
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX AS r ON r.trx_id = w.requesting_trx_id
LEFT JOIN INFORMATION_SCHEMA.PROCESSLIST AS p ON p.id = b.trx_mysql_thread_id;
这仅适用于MySQL 5.5+。如果您使用的是MySQL 5.1或更低版本,则必须终止所有睡眠连接以释放锁。
for update
,当然使用时除外),这不是真的吗?
select
可以锁定行或以任何方式被DML在另一笔交易中阻止。就Oracle而言,这当然是正确的,据我所知,对于InnoDB也是如此。当然,该select
语句实际上是通过函数或其他某种绕行路线进行DML 的情况除外。