这个问题困扰我很长时间了,首先要说明的是,只有当数据库为sqlserver时才会出现此问题,当用oracle数据库时,不会出现该问题,费解!
背景:公司项目之前一直是用的oracle,底层用了很多年都相安无事,事实上,公司自己封装的数据库底层是支持oracle和sqlserver双库的,现在因为部分客户无orace正版,只有sqlserver正版,无奈只好使用sqlserver的库,那么问题来了。
公司页面有很多界面是多iframe的结构,当这几个iframe同时加载数据时,调用数据查询方法时,数据返回会有错乱;举例描述如:frame1传sql1应该返回result1,frame2传sql2应该返回result2,但实际情况是,frame1返回的是result2,frame2返回的是result1,当然,如果frame越多,各frame间接收的数据也会有不同的错乱,结果就会导致在绑定列表或取结果集中某字段的时候报错说“找不到字段XXX”,但是也会有frame中取到的是正确的数据集,至于是哪个frame中会取到错误的数据集也不固定,在每次刷新页面的时候都会有变化。今天特定写了个简单的页面,放三个iframe,分别调用底层方法查询数据,确定了此问题。
经过调试代码,发现当页面加载时,三个iframe同时会实例化数据库底层类,这可能是导致数据互窜的根源。
因为将数据库操作底层整体结构全改了是不可能的,有考虑过用lock防止各实例间的互窜,但未见效果。
望各位有经验或有方法的朋友帮忙分析并提供有效的解决办法,不胜感激!!!
有句话叫啥来着,拉不出屎来怪茅厕,这居然也能怪SQL SERVER。
明显问题就是操作SQL SERVER的代码出问题了。
将数据库操作底层整体结构全改了是不可能的。
全改倒是不用的,就是要改错的那一部份就行了。
我没有怪sqlserver的意思,我只是描述现象。不要误解我的意思。
需要怎么调整代码呢?望指教!
@祈祷: 我又不是微软的公关。
你得找出连接ORACLE和连接SQL SERVER,查询数据的方法代码,要不然怎么知道如何调整呢?
@爱编程的大叔: 代码早看过了,现在问题也基本清楚了,就是底层代码共用了全局SqlDataAdapter变量,在并发时数据互窜的问题,就是不知道在保证底层结构不变的情况下(可调整局部代码,不调整底层调用代码),解决这个问题。
@祈祷: 并发连接时,应该可以处理成为每个使用一个全新的Connection,你们的底层不会把这个全部给限制死了吧。
@祈祷: 补充一下,我估计你们的程序员,在使用SQL SERVER的时候,发现过一个错误,
就是多个DATAREADER在并发中出错的问题,然后有提示,使用MARS可以免于出错。
但是,仔细看微软的文档,你们会发现这样一句话:
MARS operations are not thread-safe.
微软在处理MARS上采用的这样的机制:
When a connection is opened with MARS enabled, a logical session is created, which adds additional overhead. To minimize overhead and enhance performance, SqlClient caches the MARS session within a connection. The cache contains at most 10 MARS sessions. This value is not user adjustable. If the session limit is reached, a new session is created—an error is not generated. The cache and sessions contained in it are per-connection; they are not shared across connections. When a session is released, it is returned to the pool unless the pool's upper limit has been reached. If the cache pool is full, the session is closed. MARS sessions do not expire. They are only cleaned up when the connection object is disposed. The MARS session cache is not preloaded. It is loaded as the application requires more sessions.
@祈祷: SqlDataAdapter也敢全局用,如果这样的话里面应该有多个set或table,你取筛选你想要的不就得了
将sqldataadapter加锁。
简单一点,你在获取datatable的时候检测获取的数据是不是你想要的,如果不是就重新执行查询语句,知道是为止。这个好实现吧
谁写的底层!????他要负责
这绝对是你代码的问题。。你可能用了全局的类或者其他,MARS默认是不开启的,你可以开启下,这样的话一个连接可以执行多个命令了
代码有问题的,不可能有这种情况,你取数据不可能会错的,只有一个可能,你用的是静态变量,看看是不是变量是不是static