适用于:✅ SQL 分析端点和 Microsoft Fabric 中的数据仓库
与SQL Server中的行为类似,事务允许你控制读取和写入查询的提交或回滚。
Fabric Data Warehouse支持符合 ACID 的事务。 每个事务都是原子的、一致的、隔离的和持久的(ACID)。 单个事务中的所有操作都以原子性的方式处理,要么全部成功,要么全部失败。 如果事务中的任何语句失败,则会回滚整个事务。
显式事务
可以使用显式事务将更改组合在一起,修改存储在仓库中的表中的数据。
例如,可以向多个表提交插入,或者如果出现错误,则不向任何表提交插入。 如果要更改影响三个表的采购订单的详细信息,则可以将这些更改分组到单个事务中。 这意味着当查询这些表时,它们要么全部有更改,要么没有任何更改。 事务是一种常见做法,用于在需要确保多个表中的数据一致时。
可以将标准 T-SQL(BEGIN TRAN和COMMIT TRANROLLBACK TRAN)语法控制机制用于显式事务。 有关详细信息,请参阅: - BEGIN TRANSACTION
- COMMIT TRANSACTION
- ROLLBACK TRANSACTION
例如,Fabric Data Warehouse将这些架构更改视为单个原子单元:
-- Sample Syntax---
BEGIN TRAN;
ALTER TABLE <table_name> ADD <column_name> <type>;
ALTER TABLE <table_name> DROP COLUMN <column_name>;
COMMIT;
如果事务中的任何语句失败,将自动回滚所有架构更改。
Fabric Data Warehouse支持在显式事务中执行以下内容:
CREATE TABLEDROP TABLETRUNCATE TABLECTASsp_rename-
ALTER TABLE添加可为 null 的列 -
ALTER TABLE删除列 -
ALTER TABLE使用PRIMARY KEY关键字添加或删除UNIQUE、FOREIGN KEY和NOT ENFORCED约束 - 多个
ALTER TABLE语句 -
ALTER TABLE关于分布式临时表的
跨数据库查询事务支持
Microsoft Fabric 中的仓库支持在同一工作区内跨多个仓库进行事务,包括从 Lakehouse 的 SQL 分析终结点 读取数据。 有关示例,请参阅 编写跨数据库 SQL 查询。
了解 Fabric Data Warehouse 中的锁定和阻塞
无论查询是涉及一行还是多行,Fabric Data Warehouse都使用表级锁定。 下表提供了不同 T-SQL 操作所使用的锁列表。
| 语句类型 | 已锁定 |
|---|---|
| DML | |
| SELECT | Schema-Stability (Sch-S) |
| INSERT | 意向独占 (IX) |
| DELETE | 意向独占 (IX) |
| UPDATE | 意向独占 (IX) |
| 合并 | 意向独占 (IX) |
| 复制到 | 意向独占 (IX) |
| DDL | |
| 创建表格 | 架构修改(Sch-M) |
| 修改表 | 架构修改(Sch-M) |
| DROP TABLE | 架构修改(Sch-M) |
| TRUNCATE TABLE | 架构修改(Sch-M) |
| 创建表以选择 | 架构修改(Sch-M) |
| 创建表作为克隆 | 架构修改(Sch-M) |
可以使用动态管理视图 (DMV) sys.dm_tran_locks 查询当前持有的锁。
有关锁、锁升级和锁兼容性的详细信息,请参阅 事务锁定和行版本控制指南。
快照隔离
Fabric Data Warehouse对所有事务强制实施快照隔离。 快照隔离是一种基于行的隔离级别,它为数据提供事务级的一致性,并使用存储在 tempdb 中的行版本来选择要更新的行。 该事务使用事务开始时存在的数据行版本。 这可确保每个事务在与事务开始时的数据一致的一致性快照上进行操作。
在快照隔离中,事务中的查询会依据事务开始时的数据库状态查看相同的版本或快照。 在快照隔离中,修改数据的事务不会阻止读取数据的事务,而读取数据的事务不会阻止写入数据的事务。 这种乐观的非阻塞行为也大大减少了复杂事务的死锁的可能性。
如果使用 T-SQL 更改隔离级别,则会在查询执行时忽略更改,并应用快照隔离。
在快照隔离中,写写冲突或更新冲突是可能发生的。有关详细信息,请参阅Fabric Data Warehouse中的了解写写冲突。
模式锁
架构锁可防止 DDL 语句发生冲突,例如在事务中更新行时更改表的架构。 请注意,DDL操作,例如架构更改和迁移,可能会阻止或被正在进行的读取负载所阻止。
- 在数据定义语言(DDL)操作期间,数据库引擎使用架构更改的
Sch-M锁。 在锁被持有期间,Sch-M该锁会阻止对表的所有并发访问,直到释放锁。 - 在数据操作语言(DML)操作期间,数据库引擎使用架构稳定性(
Sch-S)锁。 获取Sch-M锁的操作会被Sch-S锁阻止。 在编译查询时,其他事务会继续运行,但 DDL 操作会被阻止,直到它们能够获得对架构的独占访问权限。 - 在事务持续期间,DDL操作还会在与目标表关联的系统视图中的行上获取一个排他锁(
X),例如sys.tables和sys.objects。 这会阻止SELECT、sys.tables和sys.objects上的并发语句。
避免阻止的最佳做法
- 避免长时间运行的事务,或在并发活动较少或没有的期间进行计划。
- 仅在维护窗口期间安排DDL操作,以将阻塞降至最低。
- 虽然可以在显式用户事务 (
BEGIN TRAN) 内执行 DDL 语句,但它们在并发工作负荷中应谨慎使用。 由于锁定行为,事务中的 DDL 可以阻止对受影响表的并发 DML 或 SELECT 操作,以及对诸如sys.tables或sys.objects等系统目录视图的 SELECT 查询。 若要监视和排查潜在的锁冲突,请使用sys.dm_tran_locks。 - 监控仓库中的锁定和冲突。
- 使用 sys.dm_tran_locks 检查当前锁。
了解Fabric Data Warehouse中的写写冲突
当两个事务尝试UPDATE、DELETE、MERGE或TRUNCATE同一个表时,可能会发生写入-写入冲突。
写入冲突或更新冲突在表级别是可能的,因为Fabric Data Warehouse使用表级锁定。 如果两个事务尝试修改同一表中的不同行,它们也可能发生冲突。
写写冲突主要来自两种情况:
- 用户引发的工作负荷冲突
- 多个用户或进程同时修改同一个表。
- 可以在 ETL 管道、批处理更新或重叠事务中发生。
- 系统引发的冲突
- 后台系统任务(如自动数据重整)会重写质量不佳的文件。
- 这些可能会与用户事务冲突,尽管数据压缩抢占会主动阻止此类型的写写冲突。
如果发生写写冲突,你可能会看到错误消息,例如:
- 错误 24556:由于更新冲突导致快照隔离事务中止。 使用快照隔离在数据库 '%.*ls' 中直接或间接访问表 '%.*ls' 时,如果该表中的行已被另一个并发事务删除或更新,则可能导致更新冲突。 请重试该交易。
- 错误 24706:由于更新冲突而中止的快照隔离事务。 不能使用快照隔离在数据库 '%.*ls' 中直接或间接访问表 '%.*ls' 来更新、删除或插入已由另一个事务修改或删除的行。 请重试交易。
如果遇到这些错误消息,一个或多个事务成功,并且一个或多个冲突的事务失败。 重试失败的交易。
注释
即使MERGE事务仅导致追加更改,它们仍然会导致写写冲突。 当事务影响与其他并发 DML 事务不同的行时 MERGE ,如果 MERGE 不是第一个提交事务,则可能会遇到此错误:“由于更新冲突而中止的快照隔离事务”。
避免写入-写入冲突的最佳做法
为了避免写写冲突:
- 避免在同一个表上同时执行
UPDATEDELETEMERGE操作。- 请特别注意多步骤事务中的
UPDATE,DELETE,MERGE操作。
- 请特别注意多步骤事务中的
- 在所有应用程序和查询中使用重试逻辑。
- 在存储过程和 ETL 管道中实现重试逻辑。
- 在管道或应用中添加延迟的重试逻辑,以处理暂时性冲突。
- 使用指数退避策略来避免重试风暴加剧暂时性网络中断。 有关详细信息,请参阅 重试模式。
- Fabric Data Warehouse后台数据压缩服务的写写冲突是可能的,但通常由 Data compaction preemption 功能阻止。
表和 Parquet 文件锁定
两个或多个并发事务更新表中一行或多行时产生的冲突将在事务结束时进行评估。 第一个提交的事务将成功完成,而其他事务将回滚并会返回一个错误。 这些冲突在表级别进行评估,而不是在单个 Parquet 文件级别。
INSERT 语句始终会创建新的 parquet 文件,这意味着与其他事务(DDL 除外)的冲突更少,因为表的架构可能会更改。
限制
- 不支持分布式事务,例如
BEGIN DISTRIBUTED TRANSACTION。 - 不支持保存点。
- 不支持命名事务。
- 不支持加标记的事务。
- 目前,仓库中的 T-SQL 功能有限。 有关当前不可用的 T-SQL 命令列表,请参阅 Fabric Data Warehouse 的 T-SQL 外围应用。
- 如果事务将数据插入空表并在回滚前发出 SELECT,则自动生成的统计信息仍可能反映未提交的数据,从而导致统计信息不准确。 不准确的统计信息可能导致查询计划和执行时间未优化。 如果在大型 INSERT 后使用 SELECT 回滚事务,请更新 SELECT 中提及列的统计信息。