西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴(lài)的軟件下載站!
軟件
軟件
文章
搜索

首頁(yè)西西教程數(shù)據(jù)庫(kù)教程 → 用C# 制作MySQL數(shù)據(jù)庫(kù)批量備份還原工具

用C# 制作MySQL數(shù)據(jù)庫(kù)批量備份還原工具

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:西西整理時(shí)間:2011/12/10 16:09:18字體大。A-A+

作者:西西點(diǎn)擊:333次評(píng)論:0次標(biāo)簽: MySQL

  • 類(lèi)型:電子教程大。8.5M語(yǔ)言:中文 評(píng)分:8.3
  • 標(biāo)簽:
立即下載

   在這篇文章我們學(xué)習(xí)用C#來(lái)操作,并制作一個(gè)備份還原工具。

  我們要操作cmd.exe使用到了Process類(lèi),使用這個(gè)類(lèi)首先要引入命名空間  System.Diagnostics,此類(lèi)提供對(duì)本地和遠(yuǎn)程進(jìn)程的訪問(wèn)并能夠啟動(dòng)和停止本地系統(tǒng)進(jìn)程。

        /// <summary>
        /// 執(zhí)行Cmd命令
        /// </summary>
        /// <param name="workingDirectory">要啟動(dòng)的進(jìn)程的目錄</param>
        /// <param name="command">要執(zhí)行的命令</param>
        public static void StartCmd(String workingDirectory, String command)
        {
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.WorkingDirectory = workingDirectory;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;

            p.Start();
            p.StandardInput.WriteLine(command);
            p.StandardInput.WriteLine("exit");
            p.WaitForExit();
            p.Close();

        }

在看看如何使用上方法:

string appDircectroy="C:\\Program Files\\MySQL\\MySQL Server 5.5\\bin"
string cmd="mysqldump -hlocalhost  -uroot -proot --default-character-set=utf8 --lock-tables --routines --force  --quick Dbname>d:\backup.sql"

  StartCmd(appDircectroy,cmd);

這里我們同Process操作cmd.exe,調(diào)用mysqldump.exe 執(zhí)行命令"-hlocalhost  -uroot -proot --default-character-set=utf8 --lock-tables --routines --force  --quick Dbname>d:\backup.sql"備份數(shù)據(jù)庫(kù)。其實(shí)我們也可以直接通過(guò)Process類(lèi)直接調(diào)用mysqldump.exe進(jìn)程執(zhí)行命令,寫(xiě)法如下:

        /// <summary>
        /// 使用mysqldump執(zhí)行command命令
        /// </summary>
        /// <param name="AppPath">mysqldump.exe的目錄</param>
        /// <param name="command"></param>
       public static void StartMySqldump(string AppPath, string command)
        {
            ProcessStartInfo psi = new ProcessStartInfo(AppPath + @"\mysqldump.exe");
            psi.Arguments = command;
            psi.UseShellExecute = false; psi.RedirectStandardOutput = true;
            psi.RedirectStandardInput = true;
            psi.RedirectStandardError = true;
            psi.CreateNoWindow = true;
            Process pro = Process.Start(psi);
            pro.WaitForExit();
            pro.Close();
        }

 調(diào)用的方法和上面的使用基本一致,就是command命令不需要寫(xiě)mysqldump 改為"-hlocalhost  -uroot -proot --default-character-set=utf8 --lock-tables --routines --force  --quick Dbname>d:\backup.sql" 。

    我再這里使用方法1,比較靈活方便,因?yàn)槲覀冊(cè)虻氖褂靡部梢杂玫酱朔椒▓?zhí)行mysql.exe還原命令,上篇中說(shuō)到還原時(shí),數(shù)據(jù)庫(kù)如何不存在的使用,我們要先創(chuàng)建數(shù)據(jù)庫(kù),再還原,那么就是要執(zhí)行兩天命令,我們可以改一下方法1,使它可以執(zhí)行多條命令,如下:

        /// <summary>
        /// 執(zhí)行Cmd命令
        /// </summary>
        /// <param name="workingDirectory">要啟動(dòng)的進(jìn)程的目錄</param>
        /// <param name="command">要執(zhí)行的命令</param>
        public static void StartCmd(String workingDirectory, String[] commands)
        {
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.WorkingDirectory = workingDirectory;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            p.Start();
            foreach (string cmd in commands)
            {
                p.StandardInput.WriteLine(cmd);
              
            }
            p.StandardInput.WriteLine("exit");
            p.WaitForExit();
            p.Close();

        }

      有了上面的函數(shù),編寫(xiě)一個(gè)winform備份還原工具就比較容易實(shí)現(xiàn)了,但是現(xiàn)在我要備份300多個(gè)數(shù)據(jù)庫(kù),我要生成300多個(gè)數(shù)據(jù)庫(kù)備份文件,當(dāng)然我們也可以通過(guò)命令將300多個(gè)數(shù)據(jù)庫(kù),即所有數(shù)據(jù)庫(kù)(包含mysql自帶的系統(tǒng)庫(kù))備份到一個(gè)文件夾。還有一點(diǎn)要注意就是用戶(hù)體驗(yàn),假如備份的一個(gè)數(shù)據(jù)庫(kù)很大,那么直接調(diào)用就會(huì)吧UI卡死,所以我們要用異步線(xiàn)程來(lái)解決此問(wèn)題,我打算用四個(gè)線(xiàn)程同時(shí)執(zhí)行備份,直到300多個(gè)數(shù)據(jù)庫(kù)執(zhí)行完畢。

   有人可能對(duì)線(xiàn)程不熟悉,不用怕,其實(shí).net提供了一個(gè)異步線(xiàn)程的封裝 BackgroundWorker,用此類(lèi)可以很簡(jiǎn)單實(shí)現(xiàn)。  我們用到BackgroundWorker提供的兩個(gè)事件DoWork和RunWorkerCompleted,DoWork中寫(xiě)線(xiàn)程開(kāi)始要執(zhí)行的任務(wù),RunWorkerCompleted中寫(xiě)線(xiàn)程執(zhí)行的任務(wù)結(jié)束要執(zhí)行的工作。看看簡(jiǎn)單的代碼示例:

BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
 backgroundWorker.RunWorkerAsync(remainDbNames); //remainDbName是list<string>類(lèi)型, 傳入的參數(shù),我保存要備份的庫(kù)的名字,備份一個(gè)庫(kù)就移除一個(gè)庫(kù)

 private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)  {             List<string> names = e.Argument as List<string>; //獲取傳入的參數(shù)ramainDbName

            BackupMany(filePath, names, boolBackdata); //執(zhí)行備份方法             //e.Result = e.Argument.ToString();   //完成任務(wù)時(shí)向RunWorkerCompleted方法傳遞的結(jié)果參數(shù)

  }

   private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)    {

            // writeText(textResult,true,"完成數(shù)據(jù)庫(kù)"+e.Result.ToString()+"備份操作" + Environment.NewLine);

  }

使用就是那么簡(jiǎn)單,下面看看我啟用四個(gè)線(xiàn)程同時(shí)備份:

              //只有在備份按鈕事件中生成個(gè)異步線(xiàn)程即可
                for (int i = 0; i < 4; i++)
                {
                    BackgroundWorker backgroundWorker = new BackgroundWorker();
                    backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
                    backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
                    backgroundWorker.RunWorkerAsync(remainDbNames);
                }

下面看看單個(gè)線(xiàn)程具體如何從remainDbName中取數(shù)據(jù)庫(kù)的名字執(zhí)行備份

    object lockobject = new object(); //備份時(shí)的lock對(duì)象
    delegate void WriteText(TextBox textbox, bool append, string text);
        private void writeText(TextBox textbox, bool append, string msg)
        {
            if (this.InvokeRequired)
            {
                WriteText d = new WriteText(writeText);
                object[] obj = new object[3];
                obj[0] = textbox;
                obj[1] = append;
                obj[2] = msg;
                this.Invoke(d, obj);
            }
            else
            {
                if (append)
                    textbox.AppendText(msg);
                else
                    textbox.Text = msg;
            }
        }
        private void BackupMany(string path, List<string> dbNames, bool backupdata)
        {
            string name = null;
            lock (lockobject)
            {
                if (dbNames.Count > 0)
                {
                    name = dbNames[0];
                    dbNames.RemoveAt(0);
                }
            }
            if (name != null)
            {
                Backup(path, name, backupdata);
                BackupMany(path, dbNames, backupdata);
            }
            else
            {
                timer1.Enabled = false;
                writeText(textResult, true, "全部執(zhí)行完成!");
            }

        }

        private void Backup(string path, string databaseName, bool backupdata)
        {
            try
            {
                writeText(textResult, true, DateTime.Now.ToString() + " 開(kāi)始數(shù)據(jù)庫(kù)" + databaseName + "備份" + Environment.NewLine);
                //String command = "mysqldump --quick --host=localhost --default-character-set=gb2312 --lock-tables --verbose  --force --port=端口號(hào) --user=用戶(hù)名 --password=密碼 數(shù)據(jù)庫(kù)名 -r 備份到的地址";
                //構(gòu)建執(zhí)行的命令
                String directory = path + "\\" + databaseName + ".sql";
                String command;
                if (backupdata)
                {
                    command = string.Format("mysqldump --quick --host={1} --default-character-set={2}  --lock-tables --routines --force --port={3} --user={4} --password={5} {6} -r \"{0}\"",
                            directory, host, characterSet, port, user, password, databaseName);
                }
                else
                {
                    command = string.Format("mysqldump --quick --host={1} --default-character-set={2} -d --lock-tables  --routines --force --port={3} --user={4} --password={5} {6} -r \"{0}\"",
                         directory, host, characterSet, port, user, password, databaseName);
                }
                Cmd.StartCmd(appDirecroty, command);
                writeText(textResult, true, DateTime.Now.ToString() + @" 數(shù)據(jù)庫(kù)已成功備份到 " + directory + " 文件中" + Environment.NewLine);
                counter++;
                writeText(textBox1, false, "共" + totlecount + "個(gè)文件,已完成" + counter + "個(gè)文件");
            }
            catch (Exception ex)
            {
                writeText(txtErr, true, DateTime.Now.ToString() + " 數(shù)據(jù)庫(kù)" + databaseName + "備份失!");
            }
        }


writeText是向TextBox寫(xiě)入文本的方法,因?yàn)楦本(xiàn)程操作主線(xiàn)程生成的控件時(shí),會(huì)有線(xiàn)程安全問(wèn)題,所以要用異步委托。如何你知道這個(gè)怎么用,其實(shí)還有一個(gè)簡(jiǎn)單點(diǎn)的方法,就是把前程安全檢查給關(guān)閉掉,在窗體onload中可以加入Control.CheckForIllegalCrossThreadCalls = false; 這句就可以跨線(xiàn)程操作UI而不會(huì)報(bào)錯(cuò)。
    還原的實(shí)現(xiàn)和備份的操作差不多,這里就不提了。本想上傳個(gè)一下代碼可是找不到上傳的方法。

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過(guò)難過(guò)
    • 5 囧
    • 3 圍觀圍觀
    • 2 無(wú)聊無(wú)聊

    熱門(mén)評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(0)

    昵稱(chēng):
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)