

# Babelfish 中的事务隔离级别
<a name="babelfish-transaction"></a>

Babelfish 支持事务隔离级别 `READ UNCOMMITTED`、`READ COMMITTED` 和 `SNAPSHOT`。从 Babelfish 3.4 版本开始，支持额外的隔离级别 `REPEATABLE READ` 和 `SERIALIZABLE`。PostgreSQL 中相应隔离级别的行为支持 Babelfish 中的所有隔离级别。SQL Server 和 Babelfish 使用不同的底层机制来实现事务隔离级别（阻止并发访问、事务持有的锁、错误处理等）。而且，不同工作负载的并发访问方式可能存在一些细微差异。有关此 PostgreSQL 行为的更多信息，请参阅 [Transaction Isolation](https://www.postgresql.org/docs/current/transaction-iso.html)。

**Topics**
+ [事务隔离级别概述](#babelfish-transaction.overview)
+ [设置事务隔离级别](#babelfish-transaction.setting)
+ [启用或禁用事务隔离级别](#babelfish-transaction.enabling)
+ [比较 Babelfish 与 SQL Server 隔离级别](babelfish-transaction.examples.md)

## 事务隔离级别概述
<a name="babelfish-transaction.overview"></a>

 最初的 SQL Server 事务隔离级别基于保守锁，其中只存在一个数据副本，查询在访问行等资源之前必须锁定这些资源。后来，引入了 `READ COMMITTED` 隔离级别的变体。这使得行版本的使用能够在使用非阻止访问的读取器和写入器之间提供更好的并发性。此外，还提供了一个名为 `SNAPSHOT` 的新隔离级别。它也使用行版本来提供比 `REPEATABLE READ` 隔离级别更好的并发性，方法是避免对读取数据使用共享锁，这些锁一直保留直至事务结束。

与 SQL Server 不同，Babelfish 中的所有事务隔离级别都基于乐观锁（MVCC）。无论底层数据的当前状态如何，每个事务都可以在语句（`READ COMMITTED`）的开头或事务（`REPEATABLE READ`、`SERIALIZABLE`）的开头看到数据的快照。因此，Babelfish 中并发事务的执行行为可能与 SQL Server 不同。

例如，设想有一个隔离级别为 `SERIALIZABLE` 的事务，该事务最初在 SQL Server 中被阻止，但后来成功了。由于与读取或更新相同行的并发事务存在序列化冲突，该事务最终可能会在 Babelfish 中失败。在某些情况下，与 SQL Server 相比，在 Babelfish 中执行多个并发事务可能会产生不同的最终结果。对于使用隔离级别的应用程序，应针对并发场景进行全面测试。


| SQL Server 中的隔离级别 | Babelfish 隔离级别 | PostgreSQL 隔离级别 | 评论 | 
| --- | --- | --- | --- | 
|  `READ UNCOMMITTED`  |  `READ UNCOMMITTED`  |  `READ UNCOMMITTED`  |  `READ UNCOMMITTED` 与 Babelfish 或 PostgreSQL 中的 `READ COMMITTED` 相同  | 
|  `READ COMMITTED`  |  `READ COMMITTED`  |  `READ COMMITTED`  |  SQL Server `READ COMMITTED` 基于保守锁，Babelfish `READ COMMITTED` 基于快照（MVCC）。  | 
|  `READ COMMITTED SNAPSHOT`  |  `READ COMMITTED`  |  `READ COMMITTED`  |  两者都基于快照（MVCC），但并不完全相同。  | 
|  `SNAPSHOT`  |  `SNAPSHOT`  |  `REPEATABLE READ`  |  完全相同。  | 
|  `REPEATABLE READ`  |  `REPEATABLE READ`  |  `REPEATABLE READ`  |  SQL Server `REPEATABLE READ` 基于保守锁，Babelfish `REPEATABLE READ` 基于快照（MVCC）。  | 
|  `SERIALIZABLE`  |  `SERIALIZABLE`  |  `SERIALIZABLE`  |  SQL Server `SERIALIZABLE` 是保守隔离，Babelfish `SERIALIZABLE` 基于快照（MVCC）。  | 

**注意**  
目前不支持表提示，其行为是通过使用 Babelfish 预定义的备用方案 `escape_hatch_table_hints` 来控制的。

## 设置事务隔离级别
<a name="babelfish-transaction.setting"></a>

使用以下命令设置事务隔离级别：

**Example**  

```
SET TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SNAPSHOT | SERIALIZABLE }
```

## 启用或禁用事务隔离级别
<a name="babelfish-transaction.enabling"></a>

在 Babelfish 中，事务隔离级别 `REPEATABLE READ` 和 `SERIALIZABLE` 默认处于禁用状态，您必须使用 `sp_babelfish_configure` 将 `babelfishpg_tsql.isolation_level_serializable` 或 `babelfishpg_tsql.isolation_level_repeatable_read` 备用方案设置为 `pg_isolation` 来显式启用它们。有关更多信息，请参阅 [使用转义孵化管理 Babelfish 错误处理](babelfish-strict.md)。

以下是通过设置各自的备用方案来启用或禁用在当前会话中使用 `REPEATABLE READ` 和 `SERIALIZABLE` 的示例。（可选）包括 `server` 参数，用于为当前会话以及所有后续新会话设置备用方案。

 仅允许在当前会话中使用 `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ`。

**Example**  

```
EXECUTE sp_babelfish_configure 'isolation_level_repeatable_read', 'pg_isolation'
```

 允许在当前会话和所有后续新会话中使用 `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ`。

**Example**  

```
EXECUTE sp_babelfish_configure 'isolation_level_repeatable_read', 'pg_isolation', 'server'
```

 禁止在当前会话和后续新会话中使用 `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ`。

**Example**  

```
EXECUTE sp_babelfish_configure 'isolation_level_repeatable_read', 'off', 'server'
```

 仅允许在当前会话中使用 `SET TRANSACTION ISOLATION LEVEL SERIALIZABLE`。

**Example**  

```
EXECUTE sp_babelfish_configure 'isolation_level_serializable', 'pg_isolation'
```

 允许在当前会话和所有后续新会话中使用 `SET TRANSACTION ISOLATION LEVEL SERIALIZABLE`。

**Example**  

```
EXECUTE sp_babelfish_configure 'isolation_level_serializable', 'pg_isolation', 'server'
```

 禁止在当前会话和后续新会话中使用 `SET TRANSACTION ISOLATION LEVEL SERIALIZABLE`。

**Example**  

```
EXECUTE sp_babelfish_configure 'isolation_level_serializable', 'off', 'server'
```