原作者:赵安琪
基于MogDB版本V2.0.1
问题现象
厂商研发描述Insert SQL在生产上无法执行,而测试环境中同版本的数据库该SQL可以正常运行。
检查SQL后,发现是很简单的insert into values语句,故障点是将 ‘’ 值插入到了numeric数据类型的字段中,提示“invalid input syntax for type numeric”,并且中断SQL执行。属于一个很正常的错误。
但是之后跟研发沟通后,在研发的测试环境中, ‘’ 还真的正常插入到了numeric中,没有任何报错,而且语句也是简单insert into values,没有做任何数据类型转换。
后续通过一系列的排查,发现研发测试环境使用了B - MySQL兼容性模式对数字类型插入空字符串正常,但是在生产环境中,数据库类型为A - Oracle模式,该模式下对于将空字符(‘’)插入到数字类型的字段中,会包括退出。
场景复原
模拟现场如下:
create table t (
id int,,
position numeric(24,2));
insert into t(id,trade_time,position)
values(1,to_date('2022-05-13 11:05:00','YYYY-MM-DD HH24:MI:SS'),'');
ERROR: invalid input syntax for type numeric: ""
LINE 2: ...,to_date('2022-05-13 11:05:00','YYYY-MM-DD HH24:MI:SS'),'');
^
CONTEXT: referenced column: position
处理思路
第一思路是是否发生了自动或者隐式转换,但是翻了整个手册,还是没有发现线索。重新复盘一下故障现象,对将这种字符当做数值型处理隐约有些熟悉,发现在Mysql数据库中,对于一个numeric类型字段,当传入一个字符串时,会自动转换为0。
对应到Mogdb数据库,Mogdb数据库本身支持多数据库兼容模式,兼容模式包括Oracle,MySQL,PostgreSQL。由于测试环境的Mogdb数据库都是PG兼容模式,形成了了思维惯性。一直以为故障时由于发生隐式转换导致的。
在测试环境下,重新建立了一个MySQL兼容库,验证了一下,确认’'可以被插入到numeric字段中,并显示为0,还原了厂商测试现场现象。
场景复现
create database db_mysql DBCOMPATIBILITY='B';
select datname,datcompatibility from pg_database;
c db_mysql
create table t (
id int,
trade_time timestamp(0) without time zone,
position numeric(24,2));
insert into t(id,trade_time,position)
values(1,to_date('2022-05-13 11:05:00','YYYY-MM-DD HH24:MI:SS'),'');
select * from t;
总结
Mogdb支持在创建数据库时,制定兼容数据库类型模式。取值范围为:A - Oracle,B - Mysql,PG - Postgres,在不同的兼容模式下,一些SQL语句的执行模式会略有不同。在系统上线初期一定要协调好兼容模式的使用,在生产及测试库上保持兼容模式的一致。推荐使用A,PG模式,相对来说,两者目前有大量的插件支持,提供了更好的扩展性。
MogDB 是云和恩墨基于opengauss 企业级数据库