2016-11-23 9 views
0

Valuesへの挿入をブロックすることなく、Valuesテーブルのカウントまたは合計でTotalsテーブルの行を増分更新できることに興味があります。ロックの値を持たないcountとcursorを持つMySQLアップデートの合計テーブル

アイデアが総チェックポイントより大きいすべての値を収集し、合計カウントとチェックポイントを更新することです。これにより、スナップショットが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句が必要です。私はこの作業を行う方法を見つけ出すことができる唯一の方法で開始することがREPEATABLE READValuesに挿入をブロックすることができますので、t.countt.values_checkpointを設定

は別に動作しません、そして、彼らはREAD COMMITTED

に一貫性がないであろうトランザクションとSELECT ... FOR UPDATE合計行は、Joinサブクエリで使用できるvalues_checkpointを取得します。これは理想的ではありません。なぜなら、トランザクションを開いた状態でロックをかけたままにする必要があるからです。

t.countt.values_checkpointの両方を1つの更新ステートメントとValuesの1つのSELECTで更新することはありますか?

答えて

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

によって背後に取得しないように十分な頻度で更新を行います
関連する問題