tidb update报错

表主键为auto_random ,以主键为条件更新某字段

执行update报错
Error 8216(HY000):Invalid auto random: Explicit insertion on auto_random column is disables. Try to set @@allow_auto_random_explicit_insert = true.

大佬们帮忙看看

AUTO_RANDOM 属性用于自动为每一行生成唯一的随机值,通常用于主键列。默认情况下,TiDB 不允许显式插入或更新带有 AUTO_RANDOM 属性的列,以确保数据的完整性和唯一性。如果尝试显式插入或更新这些列,就会触发 Error 8216 错误。 要解决这个问题,可以临时设置系统变量 @@allow_auto_random_explicit_inserttrue ,以允许显式插入或更新 AUTO_RANDOM 列的值。

其实我手动执行是成功的,但是我的sql在数据库发布平台执行时候是报这个错误的,唯一不同的地方是,发布平台最外层会包一层事务,现在不知道是不是这个原因造成的,我手动执行也没有显式设置这个参数,是成功的。

使用关键字 8216 在日志搜索中搜索,可以看到报错的 SQL ,按道理这个 allow_auto_random_explicit_insert 只影响 INSERT 操作。

我好像知道是为什么了,因为我们的数据库发布平台执行脚本,会有一个dml备份的动作,创建一张备份表,把要更新的数据插入到备份表,insert触发了这个报错

1 个赞


update auto_random列可以,insert显式插入auto_random列不行

对的,是我们平台的问题,自动备份数据导致了insert报错,update本身没问题的

那你allow_auto_random_explicit_insert这个参数不得不开了,如果数据库发布平台需要回滚备份的数据,应该是要把备份表的数据回插到原表吧,你不开这个参数,回插也会报错。。。

更新这个字段是没问题的,但insert不行

主键为这个的话update的话,按道理不能显示修改这个主键。

包括insert也不能显式指定这个主键的值,除非你修改此参数才可以。 ```
SET @@allow_auto_random_explicit_insert = TRUE;

1、需要显示的在会话级别设置参数
mysql> CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b VARCHAR(255));
Query OK, 0 rows affected, 1 warning (0.56 sec)

mysql> INSERT INTO t(a, b) VALUES (1, ‘string’);
ERROR 8216 (HY000): Invalid auto random: Explicit insertion on auto_random column is disabled. Try to set @@allow_auto_random_explicit_insert = true.
mysql> set allow_auto_random_explicit_insert = true;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t(a, b) VALUES (1, ‘string’);
Query OK, 1 row affected (0.02 sec)

mysql> select * from t;
±–±-------+
| a | b |
±–±-------+
| 1 | string |
±–±-------+
1 row in set (0.01 sec)

2、 目前在 TiDB 中使用 AUTO_RANDOM 有以下限制:

  • 要使用显式插入的功能,需要将系统变量 @@allow_auto_random_explicit_insert 的值设置为 1(默认值为 0)。不建议自行显式指定含有 AUTO_RANDOM 列的值。不恰当地显式赋值,可能会导致该表提前耗尽用于自动分配的数值。

3、参考连接: AUTO_RANDOM | TiDB 文档中心 (pingcap.com)

不过这边v8.1的版本测试,update更新是没有问题的,不知道你那是哪个版本,查看下那个版本的官方文档看下:
mysql> select * from t;
±–±-------+
| a | b |
±–±-------+
| 1 | string |
±–±-------+
1 row in set (0.00 sec)

mysql> select @@allow_auto_random_explicit_insert;
±------------------------------------+
| @@allow_auto_random_explicit_insert |
±------------------------------------+
| 0 |
±------------------------------------+
1 row in set (0.00 sec)

mysql> select * from t;
±–±-------+
| a | b |
±–±-------+
| 1 | string |
±–±-------+
1 row in set (0.00 sec)

mysql> update t set a=2 where b=‘string’;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from t;
±–±-------+
| a | b |
±–±-------+
| 2 | string |
±–±-------+
1 row in set (0.01 sec)

1 个赞

是的,类似于这种dml语句触发的备份都会遇到这个问题,在评估是关闭备份还是开启这个参数

对的,可以更新,但是显式指定auto_random字段的值插入不行

不是修改这个主键值,是以这个主键为条件,修改其他字段,但是触发了自动备份,备份用的是insert,导致报错

是的是的,我遇到的就是insert不行 :laughing:

是的,这段文档我看了,后知后觉才想起来,平台开了执行dml前自动备份功能

看了文档,我还没实验update主键字段可不可以,现在是更新其他字段是可以的,但是insert不行,我等下试一下,谢大佬

测试了版本7.5.2,不开参数allow_auto_random_explicit_insert =true的情况下,update主键字段也是可以的。

1 个赞