问题历史:
在迁移、迁移和修复业务逻辑时,批量更新数据是非常需要的。典型的例子是:需要在不中断服务、保持可用性和性能的情况下,变更工作表中数千万行的状态。
问题:
普通的UPDATE没有限制时运行缓慢,可能导致锁定升级,锁定表并在出错时导致集体回滚。需要一种方法来最小化对用户的影响,并确保事务性。
解决方案:
代码示例:
-- 每批更新10,000行的示例 WHILE 1 = 1 BEGIN UPDATE TOP (10000) mytable SET status = 'archived', updated = GETDATE() WHERE status = 'active'; IF @@ROWCOUNT = 0 BREAK; END
关键特性:
可以在一个事务中进行批量UPDATE而不锁定表吗?
通常情况下,不能。大型事务会锁定表/页面,并增加锁定和超时的风险。最好使用批处理。
索引的存在会影响批量更新的速度吗?
会。对索引字段的任何更新都需要为每一行重建索引。有时,暂时删除索引是合理的,但这需要深入分析。
在批量更新时,所有行都是原子的更新吗?
不,原子性仅在一个批次的范围内得到保证(行/事务的限制)。如果批次中断,部分行将被更新,部分将不会。对于真正的原子性——只有在一个事务中完成完整的UPDATE,这在处理大规模数据时是危险的。
技术工程师决定在生产数据库中用一个请求更新1000万行:UPDATE mytable SET status = 'archived'。网站“冻结”,回滚花费了几十分钟,性能受影响。
优点:
请求被分成每批10000行,短期事务内的更新在工作时间进行,没有停机。
优点: