# 如何处理Lance表并发冲突
Lance表采用MVCC（多版本并发控制）机制：每个版本由一个不可变的manifest描述，该manifest引用fragments（数据文件）、indices（索引文件）以及可选的transaction（事务）文件。读操作读取某个特定的manifest版本，因此支持快照读取；写操作通过提交新的manifest来生成新版本，从而实现ACID语义（至少在单表或单数据集的范围内）。Lance的"事务"（transaction）是一次写入、更新、删除或建索引等变更提交（commit）后，生成一个新的表版本。
#### Lance事务提交流程
- 基于某个基线版本（base version）构造事务，例如追加新的fragments、生成新的索引引用等（事务本质是"相对基线manifest的变更"）。
- 写入事务相关的新文件，先把新fragments/ 删除文件 / 索引等写到存储中（这些文件本身是不可变的）。
- 原子提交manifest，最后一步尝试"原子地"写出一个新的manifest文件作为新版本的入口；如果并发写导致原子提交失败，会进入冲突检测/重试/可能的rebase。
 
#### 事务冲突
当两个或多个用户都基于同一个base版本提交时，就会出现冲突窗口：各方均试图将"下一版本"指向各自的新manifest。Lance会在提交阶段检测到这一点，并尝试用事务文件/冲突规则做判断与（有条件的）自动合并或rebase；否则返回提交冲突。
- Lance事务操作类型
  表1Lance事务操作类型说明 
  | 事务名称              | 事务描述                                                  | 涉及语句（如不涉及标注为N/A）                                       |
  |:---|:---|:---|
  | Append             | 将新的分片添加到表中，不会修改现有数据。                                 | INSERT                                                |
  | Delete           | 使用删除向量将行标记为已删除。                                     | N/A                                                   |
  | Overwrite        | 创建或完全用新数据、新schema和新配置覆盖该表。                          | INSERT OVERWRITE、TRUNCATE                             |
  | CreateIndex        | 添加、替换或删除二级索引（向量索引、标量索引、全文检索索引）。                     | CREATE INDEX/DROP INDEX/REBUILD INDEX/OPTIMIZE INDEX |
  | Rewrite        | 对数据进行重组，不改变数据的语义。包括压缩、去重、重排等操作。                     | N/A                                                  |
  | Merge          | 向表中添加新列，从而修改表结构。必须更新所有分片以包含这些新列。                   | ADD COLUMN、ALTER COLUMN TYPE                         |
  | Project        | 从表中删除列，从而修改表结构。这是一个仅涉及元数据的操作；数据文件不会被修改。             | DROP COLUMN、ALTER COLUMN RENAME                        |
  | Restore        | 将表恢复到之前的版本。                                        | N/A                                                   |
  | ReserveFragments  | 预分配分片ID，以便在将来的重写操作中使用。                              | N/A                                                   |
  | Clone            | 创建表的浅拷贝或深拷贝。浅拷贝是仅包含元数据的拷贝，这些拷贝通过base_paths引用原始数据文件。 | N/A                                                    |
  | Update          | 修改行数据值，而不会添加或删除行。                                     | UPDATE                                                 |
  | UpdateConfig     | 修改表配置、表元数据、schema元数据或字段元数据，而不改变数据本身。                | ALTER SET/UNSET                                       |
  | DataReplacement  | 将特定列区域的数据替换为新的数据文件。                                 | N/A                                                   |
  | UpdateMemWalState | 更新MemWal索引（基于预写日志的索引）的状态。                           | N/A                                                    |
  | UpdateBases      | 向表中添加新的基础路径，从而能够引用其他位置的数据文件。                       | N/A                                                   |
     
  

- 事务冲突类型
  表2事务冲突类型说明 
  | 冲突类型                  | 描述                                                    | 当前机制                   |
  |:---|:---|:---|
  | Rebasable Conflict      | 事务可以进行修改以适应并发更改，同时保持其语义意图。事务会进行转换以适应并发修改，然后在提交层自动重试提交。    | 提交层重试提交，如果重试次数消耗完毕则报错。 |
  | Retryable Conflict      | 事务无法进行合并，会返回一个可重试冲突错误，应用层应该重新更新数据后进行重试提交。                | 直接报错。                  |
  | Incompatible Conflict | 事务之间存在根本性冲突，重试会违反操作的假设，或产生与预期语义不同的结果。提交操作失败，并返回不可重试的错误。 | 直接报错。                   |
     
  

- Lance事务冲突矩阵： ![](https://support.huaweicloud.com/devg-aidatalake/zh-cn_image_0000002701306803.png "点击放大")
  注：标"√"代表两类事务为可合并的冲突，"×"表示两类事务为无法解决的冲突，"？"表示两类事务为需要重试的冲突。
  **示例：**
  两个Append事务并发执行时（即同时向该表INSERT数据），互为可合并的冲突，Lance会尝试去合并两个Append的数据以适应并发修改，然后自动重试提交，如果在重试次数消耗完成前合并成功则两个事务并发执行成功且未产生冲突，如果重试次数消耗完仍无法合并则报错。
  
 
