我感兴趣的是能够使用Totals
表中的计数或总和逐步更新Values
表中的行而不阻止插入Values
。
我们的想法是收集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.count
和t.values_checkpoint
将无效,因为它可以阻止Values
中REPEATABLE READ
的插入,并且READ COMMITTED
< / p>
我能弄清楚如何使这项工作的唯一方法是启动事务并SELECT ... FOR UPDATE
总行以获取可在Join子查询中使用的values_checkpoint。这并不理想,因为我需要在交易开启时挂锁。
是否可以使用单个更新语句和t.count
上的单个SELECT更新t.values_checkpoint
和Values
?
答案 0 :(得分:0)
而不是从你离开的地方出发&#34;一直到最后,限制它不超过1000行。这将使干扰保持较短的时间。 (如果需要,少用1000个。)预先计算(在交易之外)一个好的&#39;也可能是好的。停止点。
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。