/// <summary>备份一批表到另一个库</summary> /// <param name="tables">表名集合</param> /// <param name="connName">目标连接名</param> /// <param name="syncSchema">同步架构</param> /// <returns></returns> public IDictionary <String, Int32> SyncAll(IDataTable[] tables, String connName, Boolean syncSchema = true) { if (connName.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(connName)); } if (tables == null) { throw new ArgumentNullException(nameof(tables)); } using var span = Tracer?.NewSpan("db:SyncAll", connName); var dic = new Dictionary <String, Int32>(); if (tables.Length == 0) { return(dic); } // 同步架构 if (syncSchema) { DAL.Create(connName).SetTables(tables); } try { foreach (var item in tables) { try { dic[item.Name] = Sync(item, connName, false); } catch (Exception ex) { if (!IgnoreError) { throw; } XTrace.WriteException(ex); } } } catch (Exception ex) { span?.SetError(ex, null); throw; } return(dic); }
/// <summary>同步单表数据</summary> /// <remarks> /// 把数据同一张表同步到另一个库 /// </remarks> /// <param name="table">数据表</param> /// <param name="connName">目标连接名</param> /// <param name="syncSchema">同步架构</param> /// <returns></returns> public virtual Int32 Sync(IDataTable table, String connName, Boolean syncSchema = true) { if (connName.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(connName)); } if (table == null) { throw new ArgumentNullException(nameof(table)); } using var span = Tracer?.NewSpan("db:Sync", $"{table.Name}->{connName}"); var dal = DAL.Create(connName); var writeDb = new WriteDbActor { Table = table, Dal = dal, IgnorePageError = IgnorePageError, Log = Log, Tracer = Tracer, // 最多同时堆积数页 BoundedCapacity = 4, TracerParent = span, }; var extracer = GetExtracter(table); // 临时关闭日志 var old = Dal.Db.ShowSQL; Dal.Db.ShowSQL = false; Dal.Session.ShowSQL = false; var total = 0; var sw = Stopwatch.StartNew(); try { // 表结构 if (syncSchema) { dal.SetTables(table); } foreach (var dt in extracer.Fetch()) { var row = extracer.Row; var count = dt.Rows.Count; WriteLog("同步[{0}/{1}]数据 {2:n0} + {3:n0}", table.Name, Dal.ConnName, row, count); // 进度报告、消费数据 OnProcess(table, row, dt, writeDb); total += count; } // 通知写入完成 writeDb.Stop(-1); } catch (Exception ex) { span?.SetError(ex, table); throw; } finally { Dal.Db.ShowSQL = old; Dal.Session.ShowSQL = old; } sw.Stop(); var ms = sw.Elapsed.TotalMilliseconds; WriteLog("同步[{0}/{1}]完成,共[{2:n0}]行,耗时{3:n0}ms,速度{4:n0}tps", table.Name, Dal.ConnName, total, ms, total * 1000L / ms); // 返回总行数 return(total); }