问题描述
SQL 执行报错误代码 5001,日志里打印类似如下的报错。
WARN [SQL.PARSER] parse_sql (ob_parser.cpp:814) [3430][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=35] [dc=0] failed to parse the statement(stmt="insert into t12 values (5,current_date(),'test')", parse_result.is_fp_=0, parse_result.is_multi_query_=0, parse_result.yyscan_info_=0x7fb0591bc0e8, parse_result.result_tree_=NULL, parse_result.malloc_pool_=0x7fb14d39da60, message="syntax error, unexpected STRING_VALUE", start_col=1, end_col=50, parse_result.line_=0, parse_result.yycolumn_=51, parse_result.yylineno_=1, parse_result.extra_errno_=0, err_charge_sql_mode=false, sql_mode_=12582912, parse_result.sql_mode_=12582912, parse_result.may_bool_value_=0, ret=-5001)
问题原因
可能是客户端代码转义有异常,把已经写好的 SQL 外层又加了引号 ",导致 OBServer 认为整个 SQL 加上前后的引号都是 SQL 文本,是一个 String,导致解析异常。
这里需要说明的是 gv$sql_audit 里记录的 query_sql 就是完整的 SQL 文本内容,OBServer 不会给它前后加引号,包括上面的日志显示也是一样,stmt= 后面的所有内容均为 SQL 文本内容,OBServer 打印日志的时候也不会加前后引号。
这个问题很容易复现:连接租户并执行加引号的 SQL 即可触发。执行完后,系统租户查询 gv$sql_audit,内容如下。
执行如下查询语句。
obclient [oceanbase]> select * from gv$sql_audit where query_sql like '"insert%';
输出结果如下。
obclient [oceanbase]> select * from gv$sql_audit where query_sql like '"insert%';
+-----------+----------+------------+-------------+-----------------------------------+------------+-----------+-------------+-----------+-------------+---------------------+------------------+-----------+------------+----------------+------------------+----------+----------------------------------+----------------------------------------------------+---------+---------------+-------------+---------------+----------+-------+--------+--------+-----------+----------------------+--------+----+--------+----+--------+----+-------+---------------+-------------+------------+--------------------+-----------------+-----------------------+-------------+-----------+-----------+--------------+-----------------+-------------+------------------+--------------+----------+---------------+------------+-------------+---------------+--------------+-----------------------+-----------------------+-------------------+---------------+---------------+------------------------+-----------------+-----------------------+------------+-----------+------------+-------------------+-------------------------+------------------------+---------------------+-----------------------+-------------------+------------+--------------------+------------+------------------+--------------+-----------------------+---------------+-----------+--------------------+-----------------------+--------------+
| SVR_IP | SVR_PORT | REQUEST_ID | SQL_EXEC_ID | TRACE_ID | SID | CLIENT_IP | CLIENT_PORT | TENANT_ID | TENANT_NAME | EFFECTIVE_TENANT_ID | USER_ID | USER_NAME | USER_GROUP | USER_CLIENT_IP | DB_ID | DB_NAME | SQL_ID | QUERY_SQL | PLAN_ID | AFFECTED_ROWS | RETURN_ROWS | PARTITION_CNT | RET_CODE | QC_ID | DFO_ID | SQC_ID | WORKER_ID | EVENT | P1TEXT | P1 | P2TEXT | P2 | P3TEXT | P3 | LEVEL | WAIT_CLASS_ID | WAIT_CLASS# | WAIT_CLASS | STATE | WAIT_TIME_MICRO | TOTAL_WAIT_TIME_MICRO | TOTAL_WAITS | RPC_COUNT | PLAN_TYPE | IS_INNER_SQL | IS_EXECUTOR_RPC | IS_HIT_PLAN | REQUEST_TIME | ELAPSED_TIME | NET_TIME | NET_WAIT_TIME | QUEUE_TIME | DECODE_TIME | GET_PLAN_TIME | EXECUTE_TIME | APPLICATION_WAIT_TIME | CONCURRENCY_WAIT_TIME | USER_IO_WAIT_TIME | SCHEDULE_TIME | ROW_CACHE_HIT | BLOOM_FILTER_CACHE_HIT | BLOCK_CACHE_HIT | BLOCK_INDEX_CACHE_HIT | DISK_READS | RETRY_CNT | TABLE_SCAN | CONSISTENCY_LEVEL | MEMSTORE_READ_ROW_COUNT | SSSTORE_READ_ROW_COUNT | REQUEST_MEMORY_USED | EXPECTED_WORKER_COUNT | USED_WORKER_COUNT | SCHED_INFO | FUSE_ROW_CACHE_HIT | PS_STMT_ID | TRANSACTION_HASH | REQUEST_TYPE | IS_BATCHED_MULTI_STMT | OB_TRACE_INFO | PLAN_HASH | LOCK_FOR_READ_TIME | WAIT_TRX_MIGRATE_TIME | PARAMS_VALUE |
+-----------+----------+------------+-------------+-----------------------------------+------------+-----------+-------------+-----------+-------------+---------------------+------------------+-----------+------------+----------------+------------------+----------+----------------------------------+----------------------------------------------------+---------+---------------+-------------+---------------+----------+-------+--------+--------+-----------+----------------------+--------+----+--------+----+--------+----+-------+---------------+-------------+------------+--------------------+-----------------+-----------------------+-------------+-----------+-----------+--------------+-----------------+-------------+------------------+--------------+----------+---------------+------------+-------------+---------------+--------------+-----------------------+-----------------------+-------------------+---------------+---------------+------------------------+-----------------+-----------------------+------------+-----------+------------+-------------------+-------------------------+------------------------+---------------------+-----------------------+-------------------+------------+--------------------+------------+------------------+--------------+-----------------------+---------------+-----------+--------------------+-----------------------+--------------+
| 127.x.x.x | 3882 | 7476 | 2338155 | YF2A7F000001-0005FEEA5A78D813-0-0 | 3221875986 | 127.x.x.x | 3642 | 1001 | mysql | 1001 | 1100611139403777 | root | 0 | 127.x.x.x | 1100611139404827 | db_mysql | 6D167DCB947CBE19EDEEB9A3AD04B8B8 | "insert into t12 values (5,current_date(),'test')" | 0 | 0 | 0 | 0 | -5001 | 0 | 0 | 0 | 0 | system internal wait | | 0 | | 0 | | 0 | 0 | 100 | 0 | OTHER | MAX_WAIT TIME ZERO | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1687673106680205 | 240 | 0 | 4 | 33 | 1 | 167 | 20 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -1 | 0 | 0 | 65536 | 0 | 0 | NULL | 0 | 0 | 0 | 2 | 0 | NULL | 0 | 0 | 0 | |
+-----------+----------+------------+-------------+-----------------------------------+------------+-----------+-------------+-----------+-------------+---------------------+------------------+-----------+------------+----------------+------------------+----------+----------------------------------+----------------------------------------------------+---------+---------------+-------------+---------------+----------+-------+--------+--------+-----------+----------------------+--------+----+--------+----+--------+----+-------+---------------+-------------+------------+--------------------+-----------------+-----------------------+-------------+-----------+-----------+--------------+-----------------+-------------+------------------+--------------+----------+---------------+------------+-------------+---------------+--------------+-----------------------+-----------------------+-------------------+---------------+---------------+------------------------+-----------------+-----------------------+------------+-----------+------------+-------------------+-------------------------+------------------------+---------------------+-----------------------+-------------------+------------+--------------------+------------+------------------+--------------+-----------------------+---------------+-----------+--------------------+-----------------------+--------------+
1 row in set (0.080 sec)
适用版本
OceanBase 数据库 V2.x 和 V3.x 版本。
解决方法
去掉发给服务端时 SQL 前后的引号。