2016-11-23 41 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

落後