在一个数据咀嚼应用程序中,实际上每天处理数十万条记录,我曾在一个非常蓝的月亮中获得例外:
精确值' 105'小于0或大于允许的最大值 精度为38。
......其中的价值m 105'可以是任何东西。奇怪的是,重新处理记录总能解决问题。因为这是一个很大的应用程序,所以很难排除故障/调试,并且问题永远不会重现。
我们使用SQL Server 2014 STD,应用程序使用Dapper以C#(。Net 4.6.2)编写。该应用程序使用decimal
来保存(货币)金额并再次使用dapper插入这些值,如下所示:
decimal mydecimal = 123.45m;
connection.Execute(@"insert into [foo] (
[bar], [baz]
) values (
@bar, @baz
)", new { bar = 123, baz = mydecimal }
);
没有什么特别的事情发生(尽管使用了交易,并且比这个简化的代码还要多一点)。但是,我不明白的是,我们甚至都没有指定确切的十进制选项' (例如decimal(18,9)
)。 mydecimal
的实际值由外部(WCF)服务确定,该服务计算该值并将其返回给应用程序,然后该应用程序执行insert语句。该值传递为decimal
,即使在应用程序和WCF服务之间也是如此。数据库中的相关字段定义为money
,因为我们只需要4位小数,而不关心其余的小数。这里要注意的真实情况是,每天可以处理数十万条记录,并且(间歇性地)失败的记录在重试时始终有效。'老实说,我甚至不知道哪里开始寻找解决方案。我怀疑 Dapper有某事来处理它,因为它参数化了查询但是我遇到了死胡同。另一个,我认为不太可能怀疑可能是外部WCF服务;即使它应该两次返回相同的值(并且我确定它确实是99.999%),第一次计算可能会有微小的差异,第二次计算可能会导致{{ 1}}有一些非常具体的值导致这个问题。这意味着,例如,值为decimal
的第一个(失败)时间和值为1.234578900000001
的第二个(后续)时间。但话说回来,由于我们每天处理类似记录的 lot ,我会更频繁地失败 way 。
任何人都可以与此相关吗?有没有人遇到类似的问题?
我确实发现了this个问题(没有答案)和this question(这是一个简单的PEBKAC RTFM)而且我当然知道SQL服务器的(默认)精度是38;它只是我们甚至不在应用程序的任何地方指定/使用精度。
现在我将进一步调查Matthew Watson's suggestion多线程环境中可能发生的读取/写入错误,这是有道理的,因为应用程序是多线程的。