SQL热点行更新问题_热点数据拆分策略

4次阅读

SQL热点行更新问题_热点数据拆分策略

热点行更新卡住,本质是大量请求挤在同一条数据上抢锁。拆分不是为了“看起来分散”,而是把物理竞争点变多,让并发压力自然摊薄。

按业务维度做逻辑分桶

比如商品库存,不直接改 stock 字段,而是建一张分片表:
CREATE table product_stock (product_id int, bucket_id TINYINT, stock INT, PRIMARY KEY(product_id, bucket_id));
每次扣减时随机选一个 bucket(如 bucket_id = FLOOR(RAND() * 16)),更新对应分片。查总数时用 SUM() 汇总。这种方式改动小、见效快,适合秒杀、计数类场景。

用版本号+重试规避写冲突

对不能拆分的单行数据,改用乐观锁:在表里加 version 字段,更新时带上旧版本号校验。
UPDATE items SET stock = stock – 1, version = version + 1 WHERE id = 1001 AND version = 5;
如果返回影响行数为 0,说明已被其他事务抢先修改,应用层捕获后自动重试。适合读多写少、冲突概率不高的热点

冷热分离,把高频更新字段单独拎出来

例如用户积分表,把 total_pointspending_points 拆成两个字段或两张表。实时操作只写 pending 表(可分片),再由定时任务每分钟合并一次到主表。这样主表更新频率从每秒几百次降到每分钟一次,锁压力大幅下降。

慎用“全量覆盖”式更新

避免在高并发下执行类似 UPDATE t SET a=…, b=…, c=… WHERE id=xxx 的全字段更新。哪怕只改一个字段,InnoDB 仍会锁整行、写 redo/undo 日志。应明确只更新必要字段,并确保 WHERE 条件走索引,减少锁范围和日志开销。

text=ZqhQzanResources