在公司软件产品中,用 ado 通过 存储过程 获取数据存放在 dataset中,我明明获取的是“订单数据”,但得到的却是“库存数据”(不是一直这样,偶尔发生这种情况,且有的客户端发生,有的客户端不发生)
客户端是多线程程序,且界面有不少后台线程在抓取不同的业务数据。(c#,sqlserver 2008,Framework 4.0)
有没有哪个大侠告知一下怎么解决啊,快疯了。。。
可以确认 DBHelper 全是静态方法 ,方法之间没有共享的属性。(就算手工用 SqlCommand写也会出现问题)
怀疑是数据库连接池问题?Ado.net缓存问题?Framework版本问题?
同样的代码,有的好,有的坏,所以排除数据库数据的问题。
硬件机器、操作系统都换过,所以排除硬件问题。
就剩下Framework环境和网络环境问题了。网络方面一直没有发现问题,现在只能从环境和自身代码角度找问题了。
dsPT = this.getPTPlan_Info(connectionString, trainNO, startTime, endTime, areaString);
if (((dsPT == null) || (dsPT.Tables.Count == 0)) || (dsPT.Tables[0].Rows.Count == 0))
{
return null;
}
dsTD = this.getTDPlan_Info(connectionString, trainNO, startTime, endTime, string.Empty);
红色代码标记里面就是访问数据库存储过程了,类似:
SqlParameter[] commandParameters = new SqlParameter[] { new SqlParameter("@TRNO_DEPI", SqlDbType.VarChar, 20), new SqlParameter("@Time_START", SqlDbType.DateTime), new SqlParameter("@Time_END", SqlDbType.DateTime), new SqlParameter("@AREASTR", SqlDbType.VarChar, 0x1f40) };
commandParameters[0].Value = trainNO;
commandParameters[1].Value = startTime;
commandParameters[2].Value = endTime;
commandParameters[3].Value = areaString;
return SqlHelper.ExecuteDataSet(connectionString, CommandType.StoredProcedure, "PR_getTDPlanInfoProcedureName", commandParameters);
得出的结果里面,不是上述业务数据的任何一种,而是其他方面的业务数据。SqlHelper.ExecuteDataSet的代码如下:
public static DataSet ExecuteDataSet(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters) {
DataSet set2 = null;
using (SqlConnection conn = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(); conn.Open();
try {
PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
DataSet dataSet = new DataSet();
adapter.Fill(dataSet, "ds"); cmd.Parameters.Clear();
set2 = dataSet;
}
} finally
{ cmd.Dispose(); conn.Close(); } }
return set2; }
老早的系统,代码写的有点原始,没办法,只能在前人的基础上不停改进,呵呵。
此问题不是一直出现,一天在3个时段出现概率大,其他时段也出现,但没啥规律。
可以debug看看那个dataset是不是有时也存放了库存数据。。很简单的思路!从DB到后台再到客户端三个方面按顺序debug查看下数据到哪出现了问题。。。
每个DataSet都是在方法内临时创建的,用完就丢的,没有任何缓存
生产环境无法Debug,只能谢谢日志、监控工具什么的,测试环境没问题。
这些数据有缓存吗,有的话先不用缓存检测一段时间。
不是“数据库连接池问题”,也不是“Ado.net缓存问题”,更不是“Framework版本问题”,建议从其他角度下手
同样的程序,在另外一台机器完全好使,就这一台老窜,而且不存在缓存,获取数据逻辑都在一个方法里,不涉及任何属性,就是DataSet里面的数据变成了另一个存储过程返回的数据了。除了环-境问题,我实在想不出还有什么可能。
在DotNet开发这么多年,第一次碰到这种问题。跟中奖似的。
@康康: 你一直想这样低成本解决问题的话,
我有一个好方法,
1、让客户把这台电脑扔了。
2、不行的话,你买一台给他。
这是最低成本的解决方法了。
@爱编程的大叔: 机器换过了,我是从上海到乌鲁木齐,来回机票钱都够买的了,呵呵。
@康康: 嫌疑最大的依然是程序中的代码,只不过这台机器的某些环境触发了问题
@康康: 建议把 getTDPlan_Info() 改为静态方法试试
丢代码出来看看吧。如果ado.net在这块有问题那早就玩完了。
之前我也这么认为,所以加了无数日志。知道我每次都把DataSet里的数据都序列化到文件里,然后在写工具查看,才确认数据窜了。
@康康: 连接串呢?
@Daniel Cai: 外面传入的,我记了日志,也对的。
Data Source=ip\\INST1;Initial Catalog=DB_H;uid=sa;pwd=xxx;
用了14年还这样的话,你们公司的考虑下如何找一个能胜任的,或者说高薪的。
最起码目前得花一笔大价钱找个高手,这样问能问出来就奇怪了。
话不要乱说,啥意思嘛。
哥做过的中大型软件怎么也有10几个了,小的软件都记不得的了。
能不能提点有建设性的意见?
@康康: 我的意思不是贬低你啊,就是这东西你可能陷入误区了,然而这种问题
上下文相关性很厉害的,不看着代码,不进行测试跟踪,那就真的只有God能帮你了。
可以很明确的告诉你:
怀疑是数据库连接池问题?Ado.net缓存问题?Framework版本问题?
这些都不是,程序员的问题不要老是想找微软背锅。
@爱编程的大叔: 代码已放出,确认问题的方法我也在前面写了(序列化,再检查)。
我一直呆在客户现场,10.1还不知道怎么过呢,所以我写的绝对是实际情况,当然结论是我的猜测。
如果没有办法,我只能在日志里记录线程ID什么的,再复杂点的只能用WinDbg了(不过用的不熟,怕难以找到问题)
另外,此问题不是一直出现,一天在几个时段出现概率大,其他时段也出现,但没啥规律。
我也不是找谁背黑锅,毕竟人家微软就算有问题,但我的客户也不会管的。
我就想问问是不是有什么补丁我没打的。
@康康: 为什么这个问题不一直出现,而是在几个时段出现的概率大,是不是因为那几个时段用的人多数据并发造成的问题
先说两个问题之外的:
1. 代码能高亮么?
2. 是不是应该加点分?
其次是问题,先从自身找问题,取巧的方法找不到原因,就笨办法分段一点点测试。我的几点看法:
1. 数据不一样较大概率是取数据的时候sql语句错乱,好好监控一下吧
2. 写个方法模拟测试关键点,
3. 分析一下这几个时段的数据
以前不咋在这问问题。加分的事我研究下的。
这个问题我折腾5天四夜了。我们系统全天运行。
问题代码也拿出来放在测试程序跑过,没问题。所以郁闷哪
因为没啥sql语句,都是存储过程,实在想不出咋弄
@康康: 想办法重现吧,抓一下重现时的参数和返回的数据,听你描述出现概率也不小
找一下出现此问题此问题的时候进行过的操作
我们这种吃瓜群众也是蒙,看不出来啥
看起来很奇怪的样子,如果LZ实在找不到原因,建议抛弃DataSet和DataTable。从datareader手写一个一个的映射。然后在观察一段时间。
这个一看就是多线程那里出现了问题,多个客户端请求ID和服务器的响应ID 出现没有对应上的问题。
比如说 A客户端请求 订单数据 ID为5,B客户端请求 库存数据 ID为6。多线程那里肯定是 共享了一个全局变量,多线程修改的时候,导致服务器 本来要给B的数据给成A。