问题现象:
开发环境上日志看到写数据失败异常:
org.influxdb.InfluxDBException$FieldTypeConflictException: partial write: field type conflict: input field "-diff_acc_param-EP001_IMP_kWh" on measurement "device_data" is type float, already exists as type integer dropped=1
字段是-diff_acc_param-EP001_IMP_kWh
写入的类型是float,而数据库存在的字段类型是integer,所以写入报错
通过命令SHOW FIELD KEYS FROM device_data 查看数据库字段类型
发现共有10多个字段是integer,而且这些字段绝大部分都是双类型(float+integer)
为什么这么多双类型的字段?
一开始我以为是因为很早的influx版本是不检查字段类型的,所以导致存在双类型
参考:https://github.com/influxdata/influxdb/issues/3519
https://github.com/influxdata/influxdb-java/pull/115
,但是后来我又发现了一个奇怪现象:修改时间戳,写入不同的时间时,有的可以成功有的失败
最后通过分析influxdb源码发现,字段的类型是从fields.idx文件读取,而这个文件是分shard的,所以不同的shard,同一个字段类型可以不同的。当写一个新shard时,这时候字段类型还没有,此时写任何类型都可以成功,并且会决定此shard的类型,后续写就必须保持一致了。所以如果我们写数据时类型没有统一,就会出现双类型,导致后续写入可能会失败。
相关源码:
shard.go : WritePointsWithContext validateSeriesAndFields
Store.go: loadShards
对我们代码的要求:
1.写数据时都按浮点来写,避免写入integer导致后续写入问题。并且对FieldTypeConflictException异常进行捕获,打印日志即可,不要中断主流程。
2.读数据时,要考虑到历史数据可能是integer,所以要对integer进行兼容。读到integer时转为浮点