今天电脑刚好出了点问题,正在郁闷中。。。这样也就有时间总结一下这两个月来我做的主要工作:
刚到公司经理就交给我一个以前老同事做过的一个项目让我重做一遍,做一个数据库同步软件。
首先看了一下同事做的软件源码。发现他实现数据库同步的核心在于读取数据库中的所有表,然后用tablediff对表进行比较,具体做法是用tablediff的方式,对每个表产生一个带tablediff函数的批处理文件,对于有内容不同的表产生一个sql日志,然后同步数据库执行sql日志中的内容。
写博客截图太麻烦了。。。。
不截图了
这就是相关的截图了,对数据库了解的朋友知道用tablediff的方式比较数据表将占用大量的CPU资源,当同步间隔时间设为1秒时cpu该程序占用cpu大概在10%左右。 相关的核心代码: BatHelper.cs:生成批处理文件 using System; using System.Diagnostics; using System.IO; using System.Text; using System.Threading; namespace Synchro { /// <summary> /// .bat Helper /// </summary> class BatHelper { #region private constant // debug folder private static readonly string WorkPath = System.Windows.Forms.Application.StartupPath; // TableDiff folder private static readonly string TableDiffPath = WorkPath + "//COM"; // bat folder private static readonly string BatFilePath = WorkPath + "//bat"; #endregion // check bat/cfg/sql/log folders public static bool WorkFolderExist() { bool bret = true; bool bConfig = false; bool bbat = false; bool bsql = false; bool blog = false; // bat/cfg/sql exists or not DirectoryInfo[] directories = new DirectoryInfo(WorkPath).GetDirectories(); foreach (DirectoryInfo info in directories) { if (info.Name == "bat") { bbat = true; bret = false; } else if (info.Name == "cfg") { bConfig = true; bret = false; } else if(info.Name == "sql") { bsql = true; bret = false; } else if(info.Name == "log") { blog = true; bret = false; } } // bat/cfg/sql/lgo not exists ,create() DirectoryInfo directoryInfo; if(!bbat) { directoryInfo = new DirectoryInfo(WorkPath + "//bat"); directoryInfo.Create(); } if (!bConfig) { directoryInfo = new DirectoryInfo(WorkPath + "//cfg"); directoryInfo.Create(); } if (!bsql) { directoryInfo = new DirectoryInfo(WorkPath + "//sql"); directoryInfo.Create(); } if(!blog) { directoryInfo = new DirectoryInfo(WorkPath + "//log"); directoryInfo.Create(); } return bret; } // 根据表名创建对应的批处理文件 public static void CreateTableDiffBat(string tableName) { if(tableName == null ||tableName.Trim() == "") return; string serverSrc = ""; string uidSrc = ""; string pwdSrc = ""; string databaseSrc = ""; string serverDes = ""; string uidDes = ""; string pwdDes = ""; string databaseDes = ""; // select ServerCfg.xml cfgfile bool ret = XmlHelper.SelectServerSetConfig(ref serverSrc, ref uidSrc, ref pwdSrc, ref databaseSrc, ref serverDes, ref uidDes, ref pwdDes, ref databaseDes); if (!ret) { throw new Exception(@"加载配置文件“/cfg/ServerCfg.xml”失败"); } // 拼接字符串创建 "tableName.bat"形式文件 System.IO.StreamWriter sw = new StreamWriter(BatFilePath + "//" + tableName + ".bat", false, Encoding.Default); sw.WriteLine("cd "+TableDiffPath); StringBuilder content = new StringBuilder(); content.Append("tablediff -sourceserver "); content.Append("/""); content.Append(serverSrc); content.Append("/""); content.Append(" -sourcedatabase "); content.Append("/""); content.Append(databaseSrc); content.Append("/""); content.Append(" -sourcetable "); content.Append("/""); content.Append(tableName); content.Append("/""); content.Append(" -sourceschema /"dbo/""); content.Append(" -sourcepassword "); content.Append("/""); content.Append(pwdSrc); content.Append("/""); content.Append(" -sourceuser "); content.Append("/""); content.Append(uidSrc); content.Append("/""); content.Append(" -destinationserver "); content.Append("/""); content.Append(serverDes); content.Append("/""); content.Append(" -destinationdatabase "); content.Append("/""); content.Append(databaseDes); content.Append("/""); content.Append(" -destinationtable "); content.Append("/""); content.Append(tableName); content.Append("/""); content.Append(" -destinationschema /"dbo/" "); content.Append("-destinationpassword "); content.Append("/""); content.Append(pwdDes); content.Append("/""); content.Append(" -destinationuser "); content.Append("/""); content.Append(uidDes); content.Append("/""); content.Append(" -bf /"50000/" "); content.Append(" -f "); content.Append("/""); content.Append(DbHelper.SqlFilePath + "//" + tableName); content.Append("/""); sw.WriteLine(content.ToString()); sw.Close(); } // exec "tableName.bat" public static bool ExecTableDiffBat(string tableName) { try { DbHelper.FileDelete(tableName); ProcessStartInfo p = new ProcessStartInfo("cmd.exe"); p.UseShellExecute = false; p.RedirectStandardError = true; p.CreateNoWindow = true; p.Arguments = "/c " + BatFilePath + "//" + tableName.Trim() + ".bat"; //p.WorkingDirectory = "c://"; Process process = Process.Start(p); do { Thread.Sleep(500); } while (!process.HasExited); process.Close(); return true; } catch(Exception e) { //string Synchrolog = LogHelper.LogFilePath + "//Synchro_" + DateTime.Now.ToString("yyyy-MM-dd").Trim() + ".log"; //LogHelper.AppendLog(Synchrolog,"执行["+tableName+".bat]文件出错。 "+e.Message); return false; } } // exists *.bat file public static bool FileExist(string fileName) { return File.Exists(BatFilePath + "//" + fileName + ".bat"); } // delete all *.bat files public static bool RemoveAll() { FileInfo[] fileInfos = new DirectoryInfo(BatFilePath).GetFiles(); foreach (FileInfo info in fileInfos) { info.Delete(); } return true; } public static void RemoveSqlFile(string tableName) { int i = 0; while (true) { string sqlFileN = DbHelper.SqlFilePath + "//" + tableName + "." + i.ToString() + ".sql"; if (File.Exists(sqlFileN)) { DbHelper.ExecDataDiffSqlFile(sqlFileN); } i++; if(i==21) break; } } } } 比较数据表,与同步数据表主函数: // preview compare . private bool PreviewCompare(string tableName) { DataTable dtSrt = DbHelper.GetSpaceUsedSrc(tableName); if (dtSrt != null && dtSrt.Rows.Count > 0) { txtTabNmSrc.Text = dtSrt.Rows[0]["name"].ToString().Trim(); txtRowSrc.Text = dtSrt.Rows[0]["rows"].ToString().Trim(); txtDataSrc.Text = dtSrt.Rows[0]["data"].ToString().Trim(); } DataTable dtDes = DbHelper.GetSpaceUsedDes(tableName); if (dtDes != null && dtDes.Rows.Count > 0) { txtTabNmDes.Text = dtDes.Rows[0]["name"].ToString().Trim(); txtRowDes.Text = dtDes.Rows[0]["rows"].ToString().Trim(); txtDataDes.Text = dtDes.Rows[0]["data"].ToString().Trim(); } int srcCount = DbHelper.GetTableCountSrc(tableName); int desCount = DbHelper.GetTableCountDes(tableName); if (srcCount != -1 && desCount != -1) { txtRowSrc.Text = srcCount.ToString(); txtRowDes.Text = desCount.ToString(); if (srcCount == desCount) { return true; } else { return false; } } if(txtRowSrc.Text!=txtRowDes.Text) { return false; } //if(txtDataSrc.Text!= txtDataDes.Text) //{ // return false; //} return true; } 功能说明: 自动实时同步设置的实时同步表。 自动在设置时刻数据库数据整体同步。 一天内可以设置多个数据库整体同步的时刻。 提供相同表数据差异对比工具,并可以进行数据同步数据。 配置说明: 1.配置同步数据库信息。 2.配置需要实时同步的表及时间间隔。 3.配置数据库整体同步的时间。 4.完成以上配置,运行。 注意: 同步时间间隔设置过小,可能导致CPU占用率过高。 工作目录下,请勿修改“COM”文件夹名,也不要删除该文件。