我正在为大型 InnoDB 表上的文件进行 INSERT .. ON DUPLICATE KEY UPDATE
苦苦挣扎。
我的values
表保存属于客户端的每个实体的详细信息。一个实体的特定键只能有一个值。因此,当发生变化时,我们也会更新相同的内容。该表如下所示:
CREATE TABLE `key_values` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`client_id` int(11) NOT NULL COMMENT 'customer/tenant id',
`key_id` int(11) NOT NULL COMMENT 'reference to the keys',
`entity_id` bigint(20) NOT NULL,
`value` text,
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `client_id` (`client_id`,`entity_id`,`key_id`),
KEY `client_id_2` (`client_id`,`key_id`)
) ;
所有写入查询的形式如下:
INSERT INTO `key_values`
(client_id, key_id, entity_id,value)
values
(23, 47, 147, 'myValue'), (...), (...)...
ON DUPLICATE KEY UPDATE value = values(value);
- 该表目前约有 3.5 亿条记录,并且增长速度相当快。
- 对表的写入通常可以通过实时集成进行 插入少于 10 行或从离线源插入 25K 行。
- 对于给定客户端,一次只能运行一个批量操作。这是减少
insert
之间的行锁
- 锁定等待超时时间设置为 50 秒
目前,当离线事件有时(并非总是)发生时,我们会遇到锁定等待超时。如果不避免超时,可以进行哪些更改?
- 目前无法更改设计(分片/分区/集群)。
REPLACE
是另一个候选者,但我不想在生产中向代码中的任何内容授予删除权限。INSERT IGNORE
然后UPDATE
是一个不错的选择,但是它会带来很大的改进吗?
我还有什么其他选择?
预先感谢您的所有建议和回答。
最佳答案
关于锁等待超时,可以通过 mysql 配置设置 innodb_lock_wait_timeout 进行更改除了在 my.cnf 中更改之外,还可以动态修改它(无需重新启动 mysql)。
关于锁等待,mysql 需要考虑的一件事是默认的事务隔离级别,即 REPEATABLE READ。此设置的副作用是,对于您可能期望的读取,会发生更多的锁定(特别是如果您有 SQL Server 背景,其默认 tran iso 级别为 READ COMMITTED)。现在,如果您不需要 REPEATABLE READ,您可以在查询中使用 SET TRANSACTION ISOLATION LEVEL 语法更改 tran iso 级别,或者使用配置设置 transaction-isolation 更改整个服务器的 tran iso 级别。 。我建议使用 READ COMMITTED,并考虑应用程序中是否有其他地方甚至可以接受“脏”读取(在这种情况下,您可以使用 READ UNCOMMITTED。
关于mysql - INSERT ... ON DUPLICATE UPDATE - 锁定等待超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22389099/