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

- 简体中文
- English

划线反馈

# max_allowed_packet 与 SQL 长度的关系

更新时间：2023-12-06 11:16

适用版本： V2.1.x、V2.2.x、V3.1.x、V3.2.x 内容类型：TechNote  

租户变量 `max_allowed_packet` 用于设置最大网络包大小，单位是 Byte。

| 属性 | 描述 |
| --- | --- |
| 参数类型 | int |
| 默认值 | 4194304 |
| 取值范围 | [1024,1073741824] |
| 生效范围 | - Global - Session |
| 是否参与序列化 | 是 |
| 是否可修改 | 该变量可通过 `SET GLOBAL` 语句修改 Global 生效方式下的取值，不可通过 `SET SESSION` 语句修改 Session 生效方式下的取值。Session 值仅支持查看，且 Session 值只能与 Global 值相同。使用时，客户端与 Server 端一般均需要调整。 |

变量 `max_allowed_packet` 用于设置客户端与服务端（OBSERVER）传送网络包时允许的最大网络包大小。以 JDBC 为例，当应用使用 JDBC 与 OceanBase 租户建立连接后，JDBC 会向 OceanBase 主动查询该变量的值，从而控制可传输数据的最大长度。 ​ 例如，当 `max_allowed_packet = 1024`、应用端使用 OBClient 连接 OceanBase、使用 PrepareStatement 执行 SQL 时，由于 MySQL 协议规定在传输 PrepareStatement SQL 类型的报文时，需要向该 SQL 中添加 `？` 字符，用于标识该 SQL 为 PrepareStatement 类型，因此该 SQL 可允许的最大长度为 `max_allowed_packet - 1 = 1023`，若超过该长度，则会直接由 JDBC 抛出错误。

```
query size(1024) >= max_allowed_packet(1024)。

```

需要注意以下：

- 租户变量 `max_allowed_packet` 设置不合理将会导致各种隐形的问题。
 - 设置最大网络包大小的变量 `max_allowed_packet` 使用默认值 4194304 字节时， 若想使用 `REPEAT()`、`RPAD()` 等函数生成长度超过该变量值的目标字符串时，MySQL 模式下会返回 null，Oracle 模式下会返回 VARCHAR 类型的最大长度 32767，与这个参数关系不大。
 - 对于 MySQL 模式来讲，若向 LONGTEXT 类型的列中插入超长的字符串时，在某些情况下会发生错误并禁止插入。

## 相关案例

### length 函数与 max_allowed_packet

在使用字符串函数时（如 `REPEAT()`、`RPAD()` 等），若预计其生成的目标字符串长度 > `max_allowed_packet` 值，如果是 MySQL 模式则相关函数返回结果为 null；如果是 Oracle 模式，则与 `max_allowed_packet` 没有直接关系。

例如在 MySQL 模式下如下示例：当 `max_allowed_packet = 2^22`（默认值）时，执行以下 SQL 会返回 `null：select length(repeat('z', pow(2, 23))) from dual`。

```
<mysql:5.6.25:test>select length(repeat('z',pow(2,23))) from dual;
+-------------------------------+
| length(repeat('z',pow(2,23))) |
+-------------------------------+
|                          NULL |
+-------------------------------+
1 row in set, 1 warning (0.001 sec)

<mysql:5.6.25:test>show warnings;
+---------+------+-----------------------------------------------------------------------------+
| Level   | Code | Message                                                                     |
+---------+------+-----------------------------------------------------------------------------+
| Warning | 1301 | Result of repeat() was larger than max_allowed_packet (4194304) - truncated |
+---------+------+-----------------------------------------------------------------------------+
1 row in set (0.003 sec)

<mysql:5.6.25:test>select @@max_allowed_packet;
+----------------------+
| @@max_allowed_packet |
+----------------------+
|              4194304 |
+----------------------+
1 row in set (0.001 sec)

```

因此，若想使用字符串函数生成很长的字符串时，需要保证 `max_allowed_packet` 的值 >= 该目标字符串的长度。如下示例：设置`max_allowed_packet值为pow(2,24)`，SQL 正常执行。

```
<mysql:5.6.25:test>select @@max_allowed_packet;
+----------------------+
| @@max_allowed_packet |
+----------------------+
|             16777216 |
+----------------------+
1 row in set (0.001 sec)

<mysql:5.6.25:test>select length(repeat('z',pow(2,23))) from dual;
+-------------------------------+
| length(repeat('z',pow(2,23))) |
+-------------------------------+
|                       8388608 |
+-------------------------------+
1 row in set (0.127 sec)

```

### LONGTEXT 字段与 max_allowed_packet

LONGTEXT 作为 OceanBase 数据库 MySQL 模式支持的大对象数据类型，其定义的最大有效长度为 50331648 或 48M 个字符，其可插入的最大有效长度同时也间接地受 `max_allowed_packet` 的约束。 ​ 在使用 SQL 向 LONGTEXT 类型列中插入目标字符串时，该 SQL 长度首先也需满足 `max_allowed_packet` 的约束，只有满足该约束的情况下，该 SQL 才能顺利传输至 OceanBase 数据库，之后再检查该 SQL 是否满足“插入 LONGTEXT 类型列的目标字符串长度 < 50331648 ”的约束。  
 ​ 例如，在默认启用严格 SQL 模式的 OceanBase 数据库 MySQL 模式中，插入 LONGTEXT 列的目标字符串由应用直接生成，其长度为 length，携带该目标字符串的 INSERT SQL 使用 OBClient 驱动、PrepareStatement 方式执行，该 SQL 的长度为 L。

- 若 L + 1 < max_allowed_packet：此时该 SQL 长度首先满足了 `max_allowed_packet` 的约束。
     - 当 length < 50331648 时，满足了“插入 LONGTEXT 类型列的目标字符串长度 < 50331648 ”的约束，成功插入。
     - 当 length >= 50331648 时，不满足“插入 LONGTEXT 类型列的目标字符串长度 < 50331648 ”的约束，故而报错 `Data too long for column ...`。
 - 若 L + 1 >= max_allowed_packet：此时 SQL 长度首先不满足 `max_allowed_packet` 的约束，直接抛出错误 `query size >= max_allowed_packet`，插入失败。

如下示例：

```
<mysql:5.6.25:test>select @@max_allowed_packet;
+----------------------+
| @@max_allowed_packet |
+----------------------+
|             50331648 |
+----------------------+
1 row in set (0.001 sec)

<mysql:5.6.25:test>insert into t1 values (1,repeat('z',50331647));
Query OK, 1 row affected (2.157 sec)

<mysql:5.6.25:test>select length(r1) from t1;
+------------+
| length(r1) |
+------------+
|   50331647 |
+------------+
1 row in set (0.064 sec)

<mysql:5.6.25:test>insert into t1 values (2,repeat('z',50331649));
Query OK, 1 row affected, 1 warning (0.006 sec)

<mysql:5.6.25:test>show warnings;
+---------+------+------------------------------------------------------------------------------+
| Level   | Code | Message                                                                      |
+---------+------+------------------------------------------------------------------------------+
| Warning | 1301 | Result of repeat() was larger than max_allowed_packet (50331648) - truncated |
+---------+------+------------------------------------------------------------------------------+
1 row in set (0.034 sec)

<mysql:5.6.25:test>select length(r1) from t1;
+------------+
| length(r1) |
+------------+
|   50331647 |
|       NULL |
+------------+
2 rows in set (0.002 sec)

```

## 适用版本

OceanBase 数据库 V2.x 和 V3.x 版本。

Previous

[如何配置 OceanBase 数据库的 socket 级故障检测超时时间](https://www.oceanbase.com/knowledge-base/oceanbase-database-20000010168)

Next

[如何配置读写分离集群](https://www.oceanbase.com/knowledge-base/oceanbase-database-20000000168) ![有帮助](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) 咨询热线
