这些是InnoDB数据库中非常小的表上的简单UPDATE
。有时,操作似乎锁定,并且不会超时。然后每个后续UPDATE
以超时结束。现在唯一的办法就是让我的ISP重启守护进程。表中的每个字段都用于查询,因此所有字段都被编入索引,包括主要字段。
我不确定导致初始锁定的原因,我的ISP没有提供足够的信息来诊断问题。他们对于让我访问任何设置都很谨慎。
在以前的工作中,我被要求处理类似的信息,但我会做INSERT
。我有一个脚本定期从表中运行DELETE
个旧记录,因此不需要过滤那么多记录。当SELECT
我使用外推技术时,不仅仅有最新的数据是有用的。这种设置坚如磐石,即使在非常繁重的使用情况下也不会挂起。
使用UPDATE
和定期INSERT
替换DELETE
没问题,但它看起来很笨重。有没有人遇到类似的问题并更优雅地修复它?
max_heap_table_size
:16 MiB innodb_buffer_pool_size
:1 GiB 修改:数据库现在失败了; locations
有5条记录。下面的示例错误。
MySQL查询:
UPDATE locations SET x = "43.630181733", y = "-79.882244160", updated = NULL
WHERE uuid = "6a5c7e9d-400f-c098-68bd-0a0c850b9c86";
MySQL错误:
错误#1205 - 超出锁定等待超时;尝试重新启动交易
locations
Field Type Null Default
uuid varchar(36) No
x double Yes NULL
y double Yes NULL
updated timestamp No CURRENT_TIMESTAMP
Indexes:
Keyname Type Cardinality Field
PRIMARY PRIMARY 5 uuid
x INDEX 5 x
y INDEX 5 y
updated INDEX 5 updated
答案 0 :(得分:5)
这是InnoDB的一个已知问题,请参阅MySQL rollback with lost connection。我会欢迎那里提到的像innodb_rollback_on_disconnect
这样的东西。你正在发生的事情是你早期断开连接,就像在网络上发生的那样,如果这发生在修改查询的中间,那么执行该操作的线程将挂起但保留对表的锁定。
现在,直接使用Web服务访问InnoDB很容易受到这些断开连接的影响,除了要求他们为您重启服务之外,您无法在FatCow中做任何事情。您使用MyISAM和低优先级的想法是可以的,并且可能不会出现此问题,但如果您想使用InnoDB,则会推荐类似以下的方法。
1)使用存储过程,然后保证事务运行完成,并且在断开连接时不挂起。这是一项很多工作,但是大大提高了可靠性。
2)不要依赖auto commit
,理想情况下将其设置为零,并使用BEGIN TRANSACTION
和COMMIT
明确地开始和结束每笔交易。
答案 1 :(得分:2)
transaction1> START TRANSACTION;
transaction1> SELECT * FROM t WHERE i > 20 FOR UPDATE;
+------+
| i |
+------+
| 21 |
| 25 |
| 30 |
+------+
transaction2> START TRANSACTION;
transaction2> INSERT INTO t VALUES(26);
transaction2> COMMIT;
transaction1> select * from t where i > 20 FOR UPDATE;
+------+
| i |
+------+
| 21 |
| 25 |
| 26 |
| 30 |
+------+
什么是差距锁?
间隙锁定是锁定索引记录之间的差距。谢谢 这个间隙锁,当你运行两次相同的查询时,你会得到相同的 结果,无论该表上的其他会话修改如何。
这使得读取保持一致,从而进行复制 服务器之间一致。如果您执行SELECT * FROM id> 1000 FOR UPDATE两次,你希望得到两次相同的值。
为了实现这一点,InnoDB锁定了所有索引记录 带有排它锁的WHERE子句和它们之间的间隙 共享间隙锁。
此锁定不仅影响SELECT ... FOR UPDATE。这是一个带有DELETE语句的示例:
transaction1 > SELECT * FROM t;
+------+
| age |
+------+
| 21 |
| 25 |
| 30 |
+------+
启动交易并删除记录25:
transaction1 > START TRANSACTION;
transaction1 > DELETE FROM t WHERE age=25;
此时我们假设只有记录25被锁定。然后,我们尝试在第二个会话中插入另一个值:
transaction2 > START TRANSACTION;
transaction2 > INSERT INTO t VALUES(26);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
transaction2 > INSERT INTO t VALUES(29);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
transaction2 > INSERT INTO t VALUES(23);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
transaction2 > INSERT INTO t VALUES(31);
Query OK, 1 row affected (0.00 sec)
在第一个会话上运行delete语句后,不仅受影响的索引记录已被锁定,而且该记录之前和之后的间隙还有一个共享间隙锁,阻止将数据插入其他会话。
答案 2 :(得分:1)
如果您的UPDATE
字面意思是:
UPDATE locations SET updated = NULL;
您正在锁定表格中的所有行。如果在对所有行保持锁定时放弃事务,当然所有行都将保持锁定状态。 InnoDB在您的环境中并不“不稳定”,它似乎正在按照您的要求进行操作。您不需要放弃开放交易。