INSERT ... ON DUPLICATE UPDATE - 锁定等待时间

时间:2014-03-13 19:35:18

标签: mysql sql optimization insert-update

我正在努力使用INSERT .. ON DUPLICATE KEY UPDATE来处理大型InnoDB表上的文件。

我的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);
  • 目前该表约有350M记录,并且增长速度非常快。
  • 对表的写入可能经常发生在实时集成中 从离线源插入少于10行或25K的批量。
  • 对于给定的客户端,一次只能运行一个批量操作。这会减少insert
  • 之间的行锁定
  • 锁定等待超时时间设置为50秒

目前,当有时(并非总是)发生离线活动时,我们会获得锁定等待超时。什么可以改变而不避免超时?

  • 目前无法进行设计更改(分片/分区/群集)。
  • REPLACE是另一个候选人,但我不想将生产中的删除权限赋予代码中的任何内容。
  • INSERT IGNORE然后UPDATE是一个很好的候选人,但它会有很大改进吗?

我还有其他选择吗?

提前感谢所有建议和答案。

1 个答案:

答案 0 :(得分:2)

关于锁等待超时,可以通过mysql配置设置innodb_lock_wait_timeout进行更改,除了在my.cnf中更改它之外,可以动态修改(不重启mysql)。

关于锁等待,使用mysql要考虑的一件事是默认事务隔离级别,即REPEATABLE READ。此设置的副作用是,对于您可能期望的读取会发生更多锁定(特别是如果您具有SQL Server背景,其默认转换级别为READ COMMITTED)。现在,如果您不需要REPEATABLE READ,则可以使用SET TRANSACTION ISOLATION LEVEL语法在查询中更改您的tran iso级别,或者使用配置设置transaction-isolation更改整个服务器的tran iso级别。我建议使用READ COMMITTED,并考虑您的应用程序中是否还有其他地方甚至可以接受“更脏”的读取(在这种情况下,您可以使用READ UNCOMMITTED。