这个场景有两个方面:
- 为什么添加列会导致发生数据移动操作?
- 行级安全性带来的危险是什么?
最小化/避免数据移动
通常,添加新列不需要数据移动。如果添加到表定义的末尾,这可以通过 ALTER TABLE ADD COLUMN 操作来完成,SSDT 足够聪明,可以为您执行此操作。但是,如果添加到表的中间,则默认行为是执行完整的数据移动,这在大型表上可能会非常昂贵。为了避免这种情况:
- 始终尝试在可能的情况下将列添加到末尾。
- 如果这是不可能的,最新版本的 SSDT 和 SqlPackage 有一个
IgnoreColumnOrder
标志,它将把表中间的列添加视为添加到末尾。这可能会导致一些复杂性(例如,模式比较也必须设置此设置,否则它会显示源项目和表的数据库版本之间的差异),但通常值得这样做,以避免在部署期间不必要的数据移动
处理行级安全 (RLS) + 数据移动
如果您确实需要进行导致数据移动的更改,RLS 的风险是您的用户无权访问表中的所有行。由于数据移动将数据复制到临时表,然后删除原始表并进行重命名,因此您将丢失用户看不到的任何行。
解决方案是设置/p:AllowUnsafeRowLevelSecurityDataMovement
标志,但要验证您的用户不属于任何行级过滤方案。一个好的做法是仅将这些方案应用于具有有限权限的用户(例如您的应用程序角色),而在部署时使用具有更大权限的角色(管理员角色)。如果你这样做,你可以安全地部署,但至少有一个标志来警告这个/避免意外的数据丢失。