困扰了半年之久的Oracle简单查询导致一定概率一直不会返回
因为问题“太简单”,反而有必要啰嗦一下,交代一下事情的原委:
1、一程序中启用了3个线程(线程1、2、3),每个线程连接到一个数据库,需要一直轮询,检测到有需要处理的数据就处理一下。
2、每次启动该程序,有一定概率出现线程1执行到一个固定查询的时候一直不会返回,导致该进程内后续代码不会执行。
写了一个类,提供一个函数用以根据一个SQL返回一个表:
public DataTable GetTable(OracleConnection conn,string SQL,string tableName)
{
try
{
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
}
catch
{
return null;//数据库打开出错,跳出
}
OracleDataAdapter myAdapter;
DataSet myData = new DataSet();
try
{
myAdapter = new OracleDataAdapter(SQL, conn);
myAdapter.SelectCommand.CommandTimeout = 10;//10秒的超时,假设不加这行,就永远永远也不会往下执行
myAdapter.Fill(myData, tableName);
return myData.Tables[tableName];
}
catch (Exception ex) //出错了
{
}
finally
{
}
}
这个代码的优劣不是本次请教的重点,因为很多地方都使用了这个函数,至少是能得到结果的。
出现这个问题,我一直在思考,问题可能出现在两点:
1、查询语句有问题,写得不好,不合理。
2、查询的表有问题
查询语句如下:
select distinct t1.big_bar_cd from v_largesmallcode t1 where t1.small_bar_code in (select t.barcode from t_commoninoutth t where t.status='0')
这个语句看起来有点别扭,但是放到PLSQL里面去执行是一点问题也没有的,基本不要时间。括号里面的部分,t_commoninoutth是本地数据库A里面的表,括号里面的部分大部分时候是返回0行,查询不会返回的时候也不是因为这个表数据多。
但是v_largesmallcode是一个很大的视图,这个视图是在数据库A中通过oracle dblink连接到数据库B的视图。
背景交代完毕,我困惑有几点:
1、极端情况下即使数据过大、锁表等等一切因素,那也应该会报超时,或者说,锁表因素解除后,总会返回的吧,但事实上是永远也不会返回。myAdapter.SelectCommand.CommandTimeout = 10这句完全是无奈之举。
2、极端情况下,到数据库B的dblink断了,那也总有恢复的一天,也不应该是永远也不会返回。
3、概率,启动程序,发现线程不会继续了,也就是查询不会返回了,关掉,再开,可能就正常了。
这个问题困扰了很久,如鲠在喉,只能靠设置超时来勉强用着。