# [Critical Bug] 20210917 - TiSpark 批量写入功能导致数据不一致问题

## Issue

我们最近在 oncall 中发现了数个 TiSpark batch write 功能问题，可能导致插入数据后， TiKV/TiFlash 查询结果不正确。

### 问题现象

1. 使用 TiSpark 写入功能插入数据后，分别使用 set session tidb_isolation_read_engines = "tikv" ; select count(*) from table; 以及 set session tidb_isolation_read_engines = "tiflash"; select count(*) from table;在 TiKV, TiFlash 侧计算数据行数，TiFlash 的结果小于 TiKV 的结果。
2. 使用 TiSpark 写入带索引的数据，当部分 Spark Task 失败时，TiKV 的行数将可能少于原表的结果。

### 触发条件

1. 使用 TiSpark 写入数据时，该写入表存在 TiFlash 副本。
2. 使用 TiSpark 写入带索引的数据时，部分 Spark Task 失败。

## Root Cause

1. TiFlash 需要从 region 的 start key 中解码出 handle 信息，用于分发来自 TiDB 的请求。在 TiSpark Batch Write 中调用了 PD 的 Region Split API，没有对 start key 做出此保证。这个行为导致 TiFlash 下推查询时，丢失部分在 region 边界上的行。
2. TiSpark 写入带索引的数据时，需要对原表数据及插入部分的索引数据做合并/删除。当部分 Spark Task 失败时，部分合并/删除数据可能丢失，造成数据不一致。

## Diagnostic Steps

### oncall 问题

[ONCALL-3099](https://internal.pingcap.net/jira/browse/ONCALL-3099)

[ONCALL-3641](https://internal.pingcap.net/jira/browse/ONCALL-3641)

[ONCALL-3728](https://internal.pingcap.net/jira/browse/ONCALL-3728)

#### 相关详细文档

[https://github.com/pingcap/tispark/pull/2102](https://github.com/pingcap/tispark/pull/2102)

## Resolution

### 受影响的版本

[v2.4.0, v2.4.1] [v2.3.0, v2.3.16]

### 修复版本

v2.5.0 v2.4.2 v2.3.17

## Workaround

1. 暂停使用 TiSpark Batch Write 功能。
2. 若已经使用 TiSpark 写入数据，需要重新使用 jdbc 写入。
