PostgreSQLのカウンターの同時増分


9

アイテムのリストとその使用法で構成されるプロジェクトの統計表を維持する必要があります(ページビューをカウントするWebサイトのようなものを考えてください)。アイテムがインスタンス化されるたびに、特定のアイテムの使用量を増やす必要があります。

私の最初の実装は:

statistics(
  id      integer NOT NULL,
  name    character varying(255) NOT NULL,
  usage   integer NOT NULL DEFAULT 0,
);


UPDATE statistics 
  SET usage = usage + 1
WHERE name = '<name>';

私の懸念は、パフォーマンスと並行性についてです。更新プロセスは数十(おそらく80〜120)デバイスによってインスタンス化され、1秒あたり数回発生する可能性があるため、私の質問は次のとおりです。

1)このメソッドは同時実行性を維持しますか?(つまり、複数のデバイスが「同時に」更新を要求した場合、すべての要求がカウントされますか?)

2)結果を達成するための最良の方法を提案できますか?更新の書き込みには負荷がかかると思いますが、読み取りの方がはるかに頻繁です。値を増やす特定の機能はありますか?私は「シーケンス」を見ていますが、それが正しい方法であるかどうかはわかりません...

アドバイスをよろしくお願いします

回答:


5

2番目の更新は、同じ行の前の更新がコミットされるのを待ちますが、その後、コミットされた値を確認します。

2つの同時トランザクションが同じ行を初期値0で更新すると想定します。

時間トランザクション1 T1値トランザクション2 T2値
-------------------------------------------------- ------------
1つの更新... 1 0
2 1更新..「未定義」
                                (待つ) 
3コミット1 2
4 1コミット2
5 2 2 

「T1値」と「T2値」は、そのトランザクションが見る値を意味します。

「互換性のない」変更(たとえば、1つのトランザクションがusage列をインクリメントするのではなく特定の値に設定するトランザクション)がある状況を確実に把握したい場合は、すべてのトランザクションを「シリアライズ可能」分離レベルに置くことができます。ただし、その場合はエラー処理を準備する必要があります。

異なる名前への更新は、待機せずに同時に実行できます(異なる行が影響を受けるため)。

SELECTsがブロックされることはありませんが、コミットされた値のみが表示されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.