事务中一次执行多条语句时报错

【 TiDB 版本】v6.5.8
【 Bug 的影响】无法在事务中使用临时表
【可能的问题复现步骤】
C#程序中,伪代码如下

1、创建数据库连接并开启事务
2、定义一个sql语句变量:
CREATE TEMPORARY TABLE tmp_customer_base(
    c_no varchar(20),
    PRIMARY KEY (c_no)
);
INSERT IGNORE INTO tmp_customer_base(c_no) values('11');
3、一次调用执行sql语句变量

开启general log后跟踪到的日志信息如下

[2024/03/29 11:20:19.803 +08:00] [INFO] [session.go:3764] [GENERAL_LOG] [conn=2937701555370986845] [user=root@192.168.135.1] [schemaVersion=10423] [txnStartTS=0] [forUpdateTS=0] [isReadConsistency=false] [currentDB=] [isPessimistic=false] [sessionTxnMode=PESSIMISTIC] [sql="use `tidb_test`"]

[2024/03/29 11:20:19.803 +08:00] [INFO] [session.go:3764] [GENERAL_LOG] [conn=2937701555370986845] [user=root@192.168.135.1] [schemaVersion=10423] [txnStartTS=0] [forUpdateTS=0] [isReadConsistency=false] [currentDB=tidb_test] [isPessimistic=false] [sessionTxnMode=PESSIMISTIC] [sql="SET NAMES utf8mb4;"]

[2024/03/29 11:20:19.803 +08:00] [INFO] [session.go:3764] [GENERAL_LOG] [conn=2937701555370986845] [user=root@192.168.135.1] [schemaVersion=10423] [txnStartTS=0] [forUpdateTS=0] [isReadConsistency=false] [currentDB=tidb_test] [isPessimistic=false] [sessionTxnMode=PESSIMISTIC] [sql="set session transaction isolation level repeatable read;"]

[2024/03/29 11:20:19.804 +08:00] [INFO] [session.go:3764] [GENERAL_LOG] [conn=2937701555370986845] [user=root@192.168.135.1] [schemaVersion=10423] [txnStartTS=0] [forUpdateTS=0] [isReadConsistency=false] [currentDB=tidb_test] [isPessimistic=false] [sessionTxnMode=PESSIMISTIC] [sql="start transaction;"]

[2024/03/29 11:20:23.043 +08:00] [INFO] [conn.go:1181] ["command dispatched failed"] [conn=2937701555370986845] [connInfo="id:2937701555370986845, addr:192.168.135.1:57074 status:11, collation:utf8mb4_general_ci, user:root"] [command=Query] [status="inTxn:1, autocommit:1"] [sql="
    CREATE TEMPORARY TABLE tmp_customer_base(c_no varchar(20), PRIMARY KEY (c_no));
    INSERT IGNORE INTO tmp_customer_base(c_no) values('11');
"] [txn_mode=PESSIMISTIC] [timestamp=448707276245827608] [err="[schema:1146]Table 'tidb_test.tmp_customer_base' doesn't exist"]

[2024/03/29 11:20:23.138 +08:00] [INFO] [session.go:3764] [GENERAL_LOG] [conn=2937701555370986845] [user=root@192.168.135.1] [schemaVersion=10423] [txnStartTS=448707276245827608] [forUpdateTS=448707276245827608] [isReadConsistency=false] [currentDB=tidb_test] [isPessimistic=true] [sessionTxnMode=PESSIMISTIC] [sql=rollback]

尝试进行以下操作,均不报错。

1、当语句分两次调用执行时,不报错。
2、将general log里的sql组合手工执行时,不报错。
3、将连接改为mysql 8.0,不报错。

【看到的非预期行为】
程序抛出如下错误:

Table 'tidb_test.tmp_customer_base' doesn't exist

【期望看到的行为】
正常执行不报错
【相关组件及具体版本】

使用 7.6 tidb 版本 使用mysql 客户端 执行无报错,应该是驱动和TIDB 那块不兼容

应该是和原贴中有位同学说的那样,客户端是一条一条语句发送执行的,这样是没有问题的,程序是按指定内容执行的,我指定的内容里有两条语句,程序就会两条语句一起发送执行,这样是报错的。

要不试试全局临时表,不用在在sql中加建表语句

存在并发情况,全局临时表应该会有冲突吧。 :thinking:

不会的, * 全局临时表的表定义对整个 TiDB 集群可见,表内数据只对当前事务可见,适用于暂存事务内的中间数据。

:thinking:酱紫么?如果是这样的话,那这个表在使用前得加一层逻辑判断是否存在表。

不过,本地临时表这个bug确实需要解决。怀疑这个bug是读已提交的问题,因为加事务后,同一个事务内业务逻辑中取不到事务里更新的数据,只能读到加事务之前的数据。

这个不是临时表的问题,是 tidb_multi_statement_mode 导致的,你创建非临时表也会报这个错误。
目前测试 6.5.8 上存在该问题,master 版本上已经修复了,具体的 pr 需要再找下

2 个赞

:kissing_heart:已经修复了嘛?麻烦找一下pr

跟这个 issue 一样: Renaming a table inside a transaction and using it doesn't work · Issue #39664 · pingcap/tidb · GitHub
修复 pr: server: ignore Preprocess error for the `prefetchPointPlanKeys` optimization by tiancaiamao · Pull Request #39945 · pingcap/tidb · GitHub

2 个赞

:thinking:这个pr是在哪个版本开始修复的?看标签应该是在6.5修复了吧?