---
title: REPEATABLE READ 问题汇总-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 REPEATABLE READ 问题汇总相关的常见问题和使用技巧，帮助您快速解决 REPEATABLE READ 问题汇总的难题。
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# REPEATABLE READ 问题汇总

更新时间：2024-06-17 08:21

适用版本： V3.2.x 内容类型：Troubleshoot  

## 适用版本

OceanBase 数据库 V3.2.x 版本。

## 问题一 set autocommit = 1 未触发隐式提交

### 问题现象

具体问题如下图所示，右侧连接的事务隔离级别为 repeatable read（RR），可以发现 `set autocommit = 1` 未触发隐式提交，因此事务一直复用旧版本读取，从而导致无法获取到最新数据。

![image](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/database/sql/20240611RR001.png)

### 问题原因

`autocommit` 为原生 MySQL 下的变量，在原生 MySQL 下，`set autocommit = 1` 触发隐式提交的条件包含：

- 会话上已开启事务。
 - 会话上的 autocommit 为 0。

由于原生 Oracle 没有 `autocommit`，且 OceanBase 数据库支持 `autocommit`，因此 Oracle 租户下的 `autocommit` 行为可参考原生 MySQL。目前 OceanBase 数据库的具体行为如下。

- 在 V3.x 版本中
     - Oracle 租户：对于一条 SELECT 语句开启的事务，`set autocommit = 1` 不会隐式提交事务，因此下一条 SELECT 语句不会重新获取事务快照，无法读到最新提交的数据。对于非 SELECT 语句开启的事务，`set autocommit = 1` 会隐式提交事务。
     - MySQL 租户：对于 SELECT 和非 SELECT 语句开启的事务，`set autocommit = 1` 都会隐式提交事务。
 - 在 V4.x 版本中
     - Oracle 租户：对于 SELECT 和非 SELECT 语句开启的事务，`set autocommit = 1` 都会隐式提交事务。
     - MySQL 租户：对于 SELECT 和非 SELECT 语句开启的事务，`set autocommit = 1` 都会隐式提交事务。

该问题场景下，会话上的 `autocommit` 为 0（满足第二个条件），但由于 select 不开启事务（Oracle 兼容），导致第一个条件不满足，因此未触发隐式提交。

#### 注意

如果通过 JDBC 连接到 OBServer，且会话上 `autocommit` 为 1，会话上再执行 `commit`，JDBC 不会真实的执行 `commit`。

因此，如果客户端通过 JDBC 连接到数据库，且执行逻辑如下，则会遇到该问题：

前置条件：OceanBase Connector/JDBC 的 url 中增加 `oracleChangeReadOnlyToRepeatableRead=TRUE`（兼容Oracle）。

1. conn.setReadOnly(true)
 2. conn.setAutoCommit(false)
 3. select
 4. conn.setAutoCommit(true)
 5. conn.commit();
 6. 第 2 步至第 5 步循环执行。

### 解决方法及规避方式

为了规避该问题，可以采用如下方法：

1. 去掉 `oracleChangeReadOnlyToRepeatableRead`，此时会话开启 readonly 模式。
 2. 连接上去掉 setReadOnly 操作，避免设置会话事务隔离级别为 RR，从而每个语句都会获取最新的读取版本号。
 3. 调整第 4 步和第 5 步的顺序。先执行 `commit`，再执行 `setAutoCommit(true)`。

## 问题二 JDBC connection.commit 未触发提交

### 问题现象

在执行 JDBC 中 Connection 对象的 commit 函数时，发现当前事务未提交，SQL Audit 中查询不到 COMMIT 请求。 本示例使用 Oracle 租户，简化后的业务场景如下。

```shell
Connection conn = DriverManager.getConnection(url, user, password);
Statement ps = conn.createStatement();
// oracleChangeReadOnlyToRepeatableRead参数会将setReadOnly操作改成设置会话隔离级别为RR
conn.setReadOnly(true);
conn.setAutoCommit(false);
// 执行一条SELECT语句
ps.execute("select * from test where id = xxx");
// commit未能提交事务
conn.commit();

```

### 问题原因

JDBC 驱动会判断当前会话是否处于事务中（是否设置了 in_trans 标记，该标记由 OBServer 返回），只有处于事务中时，conn.commit 才会真正发送 `COMMIT` 命令。

OBServer 判断是否设置 in_trans 标记的逻辑如下：

1. 如果不是只读语句，设置 in_trans。
 2. 如果是只读语句，若该语句满足：(获取了有效的快照) && (autocommit=0) && (事务隔离级别为 RR 或者 Serializable || 租户的 `ob_proxy_readonly_transaction_routing_policy` 配置项为 `true`)，设置 in_trans。
 3. 其他情况不设置 in_trans。

SELECT 语句是只读语句，获取了有效的快照，且业务通过设置 conn.setReadOnly(true) 将隔离级别改为 RR，又设置了 `autocommit=0`，按理说应该会设置 in_trans。

但由于代码缺陷，在实现上述第二点判断逻辑时，对于隔离级别只考虑了 Serializable 的情况，没有考虑 RR 的情况，并且将 `ob_proxy_readonly_transaction_routing_policy` 设置为 `false`，所以最终 in_trans 标记没有被设置，也就导致了 conn.commit 没有提交事务。

### 影响版本

OceanBase 数据库 V3.2.x 版本。

## 问题三

语句重试到超时，报错 4138。

### 问题现象

租户模式为 ready only，事务隔离级别为 REPEATABLE-READ（RR）。 可以通过如下 SQL 查询事务隔离级别：

```shell
obclient> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| VARIABLE_NAME | VALUE |                 |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.003 sec)

```

在 RR 隔离级别下，当语句读取快照过旧，并且历史版本已经被回收的情况下，预期该语句直接返回 -4138 错误码。但该语句将进行重试，重试到语句超时。

### 问题原因

RR 隔离级别下，语句执行过程中 4138 错误码会进行重试。

### 问题的风险及影响

如果语句超时时设置时间较大，语句长时间不结束。

### 解决方法及规避方式

改用 RC 隔离级别。

上一篇

[XA 事务中执行一条带触发器的表上的 DML语句后，再执行 SELECT 语句可能会出现违反 read-consistent 的异常](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000466189)

下一篇

[Location Cache 问题排查](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000903988) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
