文章瀏覽數、商品點擊數等高頻更新場景,若採用單表單行 UPDATE article SET view=view+1 WHERE id=?,InnoDB 會對該行加排他鎖,導致序列化,高併發下嚴重阻塞。
CREATE TABLE article_view (
article_id INT PRIMARY KEY,
view INT NOT NULL DEFAULT 0
) ENGINE=InnoDB;
缺點:熱點行鎖競爭,TPS 受限。
將計數器移出主表,減少主表鎖爭用,但熱點行問題未解。
CREATE TABLE article_view (
article_id INT NOT NULL,
pond TINYINT NOT NULL COMMENT '桶編號 0-99',
view INT NOT NULL DEFAULT 0,
PRIMARY KEY (article_id, pond)
) ENGINE=InnoDB;
pond = FLOOR(RAND() * 100) 隨機選桶。SELECT SUM(view) FROM article_view WHERE article_id = ?。INSERT INTO article_view (article_id, pond, view)
VALUES (123, FLOOR(RAND()*100), 1)
ON DUPLICATE KEY UPDATE view = view + 1;
利用唯一鍵衝突自動轉更新,避免應用層 SELECT→判斷→INSERT/UPDATE 的競態條件。
| 方案 | 寫入並發 | 讀取總數 | 複雜度 |
|---|---|---|---|
| 單行 | 低 (序列化) | O(1) | 低 |
| 100 桶 | 高 (鎖分散) | O(100) 聚合 | 中 |