C# Value was either too large or too small for an Int32

C#程序遇到报错:Value was either too large or too small for an Int32

这是个常见的数据类型转换报错,如果出现在程序开发过程中,这个问题很容易定位。但是在长期没有进行程序更新的生产环境中突然出现,排查思路就很重要,记录一下这个问题的排查过程吧。

一、概述

成产环境近期(约1个月)无程序更新的情况下大面积开始出现以上报错,多个业务逐步受到影响。起初看到异常,没有怀疑代码的问题,因为近期没有程序更新,所以主观上开始排查数据库中多个数据源新产生的异常数据,包括从视图、DBLinks获取的新数据。

二、排查数据库

先排查了最开始出现错误时刻的数据,发现了2种异常数据,还都是异常的日期。

但很快这方面的原因就排除了,有两点:1、日期字段中虽然数据异常,但是格式仍然正确(YYYY-MM-DD HH24:MI:SS)。2、程序内部对日期数据有toString()的处理,因此不可能出现上文中......too small for an Int32 和数字类型相关的报错。

三、排查代码

重新看下报错日志,根据代码行定位,找到了对应的方法,是一个对数据库表数据和实体类进行转换的方法。再仔细看看这个写法Int32.Parse(......),就应该意识到和Int32数据类型转换时,数据太大或太小从而导致溢出有关了。 将该数据的转换改为Int64.Parse,即可解决该问题。

在这里提一下int32这个数据类型,在C#中,int int32类型的数据范围是固定的,也就是 -2,147,483,6482,147,483,647,即 -2^31 2^31 - 1

int64、long、decimal......则可以表示更大的范围,以int64为例,可以表示 -2^63 ( -9,223,372,036,854,775,808) 2^63-1(+9,223,372,036,854,775,807 )。因此在程序设计时,变量的定义除了考虑性能,还应该充分考虑实际业务的增量。

四、重新排查数据来源,确定问题

根据业务很容易排查到源头,REC_ID来自业务表的主键。果然,查看了下MAX(REC_ID)已经超过了Int32的上限。Oracle中该字段使用了Number类型存储,远远超过Int32的上限,因此该数据在Oracle中无异常,但是在程序代码中就无法正常转换了。

总结:在程序设计时,变量的定义除了考虑性能,还应该充分考虑实际业务的增量,特别是作为主键的变量,20亿的增量4年就达到了,是否说明在架构设计时就考虑不周,有严重缺陷呢?

相关推荐
闲人不梦卿5 分钟前
数据库安全和事务以及sql
数据库·sql
@22069 分钟前
银河麒麟系统离线环境下用docke方式部署(Postgres、Nginx、Redis、JDK)
运维·数据库·redis·nginx
阿坤带你走近大数据29 分钟前
oracle的varchar2(200)和mysql的varchar(200) 最大支持的字节数和字符数都一样吗
数据库·mysql·oracle
马克学长33 分钟前
SSM新能源汽车销售管理系统gooct(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·汽车·ssm框架·新能源汽车销售管理·车辆库存
小蜗的房子34 分钟前
Oracle 19C RAC Public IP单网卡改为bond模式操作指南
运维·网络·数据库·sql·tcp/ip·oracle·oracle rac
不吃饭的猪40 分钟前
nacos默认数据库密码查询
数据库
You丶小明快跑1 小时前
部署redis 集群和redis常用命令
数据库·redis·缓存
lkbhua莱克瓦241 小时前
进阶-InnoDB引擎-架构
数据库·mysql·架构·innodb·内存结构
十里八乡有名的后俊生1 小时前
PostgreSQL 常用关键字速查
数据库
马克学长2 小时前
SSM学生出国境学习交流管理87153(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·学习·ssm 框架·学生出国境管理·在线申请