2016-11-23 63 views
0

我感兴趣的是能够增量更新表Totals表中的一行,从Values表的计数或总和没有阻止插入ValuesMySQL更新总计表与计数和游标没有锁定值表

这个想法是收集ID大于总检查点的所有值,然后更新总数和检查点。这将创建一个快照到Totals。下面是表:

Table: Totals 
Create Table: CREATE TABLE `Totals` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `count` int(11) NOT NULL DEFAULT '0', 
    `values_checkpoint` int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

Table: Values 
Create Table: CREATE TABLE `Values` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `total_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `total_id_id` (`total_id`,`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

查询相结合的快照和值可能看起来像这样:

SELECT t.count + count(v.total_id),max(v.id) 
FROM `Totals` t 
JOIN `Values` v ON v.total_id = t.id AND v.id > t.values_checkpoint 
WHERE t.id = 1; 

问题带有更新Totals行。

将此直接转换为更新将不起作用,因为MySQL不允许更新中的聚合方法。

加入子查询将不起作用,因为它不能相互关联,我需要id > t.values_checkpoint的WHERE子句。

设置t.countt.values_checkpoint分别是行不通的,因为它可以在REPEATABLE READ块插入到Values,并在READ COMMITTED

的唯一方式,他们不会是一致的,我可以弄清楚如何使这项工作是启动事务和SELECT ... FOR UPDATE总行以获取可以在Join子查询中使用的values_checkpoint。这并不理想,因为我需要在开启交易的情况下留下锁。

是否有更新t.countt.values_checkpoint单个更新语句和Values单个选择?

回答

0

而不是从你“停止”的地方一路走到最后,限制它不超过1000行。这将使干扰保持较少的时间。 (如果需要,使用少于1000的值)。预先计算(在交易之外)一个'良好'的停止点也可能是好事。

SELECT @stop := LEAST(t.values_checkpoint + 1000, MAX(v.id)) 
    FROM ... 

然后继续执行查询;想必IODKU就足够了(并始终做到更新方):

INSERT INTO Totals (id, count, values_checkpoint) 
    SELECT t.count + count(v.total_id), max(v.id) 
     FROM `Totals` t 
     JOIN `Values` v ON v.total_id = t.id 
       AND v.id > t.values_checkpoint 
       AND v.id <= @stop 
     WHERE t.id = 1 
    ON DUPLICATE KEY UPDATE 
     count = VALUES(count), 
     values_checkpoint = VALUES(values_checkpoint); 

然后做更新足够频繁,这样你很少被1000

落后