c# – 使用datareader读取数百万个数据时,如何避免数据库连接丢
我有一个从数据库表中读取数据的类库.现在这个数据库表是客户端数据库,我的应用程序只有连接字符串和sql查询来打开连接,执行sql查询,读取数据并执行一些操作.
这个操作是什么,它有点复杂(基本上是业务规则). 现在,用户以特定格式提交sql查询,我的类库知道从sql查询结果中选择哪些列. 我不知道我的类库会处理的记录数.它也可能是100,200或数百万的数据. 目前,类库正在处理驻留在oracle上的9000万个数据.我正在使用SQLDATAREADER读取此数据. 现在的问题是避免内存异常我正在使用sql数据读取器读取数据但是逐个读取9千万个数据,然后对每个记录执行一些操作,连接将保持打开状态,目前我面临的问题是连接丢失: ORA-03135: connection lost contact 1解决方案可能是读取块中的数据,但正如我所说,我不知道我可能正在处理的记录数量,并且SQL查询不在我手中,因为它是由我的类库提取的用户提交的. 有什么办法可以避免连接问题吗? 更新: public class LongRunningTask : IDisposable { public void Start(DbConnection connection,string sql) { using (var cmd = connection.CreateCommand()) { cmd.CommandText = sql; cmd.CommandTimeout = 0; connection.Open(); using (var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { //read 1 by 1 record and pass it to algorithm to do some complex processing } } } } 算法并不慢,这不是问题.主要问题是读取部分,如果当前来自ORACLE的数据为9千万,则速度很慢. 我已经测试了针对SQL SERVER的1亿个数据,我没有遇到过这个问题(虽然有时会出现传输层错误),尽管这个过程花费了很多时间.我只是在使用ORACLE时遇到了这个问题. 解决方法
将数据读取器打开数小时并不是一个好主意.即使一切配置正确,线路上某处也可能出现瞬态错误(如您提到的传输层错误).
您可以在客户端代码中添加重试逻辑,以使其更加健壮.执行此操作的一种方法是跟踪上次处理的记录,并尝试在连接失败时重新连接并从该位置“恢复”. private const int MAX_RETRY = 10; private const int RETRY_INTERVAL_MS = 1000; private string lastProcessedPosition = null; public void Start(string connectionString,string sql) { var exceptions = new List<Exception>(); for (var i = 0; i < MAX_RETRY; i++) { try { if (Process(connString,sql,lastProcessedPosition)) return; } catch(Exception ex) { exceptions.Add(ex); } System.Threading.Thread.Sleep(RETRY_INTERVAL_MS); } throw new AggregateException(exceptions); } 您的Process()方法将重新连接并跳过已处理的行: public bool Process(string connString,string sql,string resumeFromPosition = null) { using ()// init your connection,command,reader { if (resumeFromPosition != null) { while (dr.Read() && dr.ToPositionString() != resumeFromPosition) { // skipping already processed records } } while (dr.Read) { // Do your complex processing // You can do this every N records if accuracy is not critical lastProcessedPosition = dr.ToPositionString(); } } return true; } dr.ToPositionString()是一种扩展方法,您可以根据表模式创建一行唯一的行. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |