有效复制/复制/备份数据库表 - mysql

时间:2012-12-26 09:14:06

标签: php mysql database duplicates

原因:我被分配运行一些推进网站的脚本,它是一个梦幻的足球网站,并且该网站的几个瞬间位于不同的域中。有些人拥有超过8万用户,每个用户应该拥有一个由15名玩家组成的团队。因此,一些表具有No.users x No.players行。

然而,有时脚本失败并且结果被破坏,因此在执行脚本之前我必须备份10个有问题的表。尽管如此,我仍然需要备份表以保持用户操作的历史记录。因为足球比赛可能持续50周以上。

任务:使用php脚本复制数据库表。当我开始时,我习惯使用 sqlyog 备份表格。它是有效的,但它耗费时间,因为我必须等待每个表重复。此外,对于大型表, sqlyog 应用程序在复制大型表时崩溃,这可能非常烦人。

当前解决方案:我创建了一个简单的应用程序,其界面可以完成工作并且运行良好。它由三个文件组成,一个用于数据库连接,第二个用于数据库操作,第三个用于用户界面,并使用第二个文件的代码。  问题是,有时它会在复制表格过程中陷入困境。

目标:创建一个管理员使用的应用程序,以方便使用mysql + php备份数据库。

我的问题:如何确保重复脚本肯定会完全备份表而不会挂起服务器或中断脚本

在这里,我将包含我的复制功能代码,但基本上这些是我认为问题所在的两个关键线:

//duplicate tables structure 
 $query = "CREATE TABLE $this->dbName.`$newTableName` LIKE $this->dbName.`$oldTable`";

//duplicate tables data
  $query = "INSERT INTO $this->dbName.`$newTableName` SELECT * FROM $this->dbName.`$oldTable`";

其余代码仅用于在发生错误时进行验证。如果您想查看整个代码,请成为我的客人。这是功能:

private function duplicateTable($oldTable, $newTableName) {

        if ($this->isExistingTable($oldTable))
        {
            $this->printLogger("Original Table is valid -table exists- : $oldTable ");
        }
        else
        {
            $this->printrR("Original Table is invalid -table does not exist- : $oldTable ");
            return false;
        }


        if (!$this->isExistingTable($newTableName))// make sure new table does not exist alrady 
        {
            $this->printLogger("Distination Table name is valid -no table with this name- : $newTableName");

            $query = "CREATE TABLE $this->dbName.`$newTableName` LIKE $this->dbName.`$oldTable`";
            $result = mysql_query($query) or $this->printrR("Error in query. Query:\n $query\n Error: " . mysql_error());
        }
        else
        {
            $this->printrR("Distination Table is invalid. -table already exists- $newTableName");
            $this->printr("Now checking if tables actually match,: $oldTable => $newTableName \n");
            $varifyStatus = $this->varifyDuplicatedTables($oldTable, $newTableName);
            if ($varifyStatus >= 0)
            {
                $this->printrG("Tables match, it seems they were duplicated before $oldTable => $newTableName");
            }
            else
            {
                $this->printrR("The duplicate table exists, yet, doesn't match the original! $oldTable => $newTableName");
            }

            return false;
        }

        if ($result)
        {
            $this->printLogger("Query executed 1/2");
        }
        else
        {
            $this->printrR("Something went wrong duplicateTable\nQuery: $query\n\n\nMySql_Error: " . mysql_error());
            return false;
        }


        if (!$this->isExistingTable($newTableName))//validate table has been created
        {
            $this->printrR("Attemp to duplicate table structure failed $newTableName table was not found after creating!");
            return false;
        }
        else
        {
            $this->printLogger("Table created successfully: $newTableName");
            //Now checking table structure 
            $this->printLogger("Now comparing indexes ... ");
            $autoInc = $this->checkAutoInc($oldTable, $newTableName);
            if ($autoInc == 1)
            {
                $this->printLogger("Auto inc seems ok");
            }
            elseif ($autoInc == 0)
            {
                $this->printLogger("No inc key for both tables. Continue anyways");
            }
            elseif ($autoInc == -1)
            {
                $this->printLogger("No match inc key!");
            }

            $time = $oldTable == 'team_details' ? 5 : 2;
            $msg = $oldTable == 'team_details' ? "This may take a while for team_details. Please wait." : "Please wait.";

            $this->printLogger("Sleep for $time ...\n");
            sleep($time);
            $this->printLogger("Preparing for copying data ...\n");
            $query = "INSERT INTO $this->dbName.`$newTableName` SELECT * FROM $this->dbName.`$oldTable`";
            $this->printLogger("Processing copyign data query.$msg...\n\n\n");
            $result = mysql_query($query) or $this->printrR("Error in query. Query:\n $query\n Error: " . mysql_error());

            // ERROR usually happens here if large tables
            sleep($time); //to make db process current requeste.
            $this->printLogger("Query executed 2/2");
            sleep($time); //to make db process current requeste.

            if ($result)
            {
                $this->printLogger("Table created ($newTableName) and data has been copied!");
                $this->printLogger("Confirming number of rows ... ");

                /////////////////////////////////
                // start checking count
                $numRows = $this->checkCountRows($oldTable, $newTableName);

                if ($numRows)
                {
                    $this->printLogger("Table duplicated successfully ");
                    return true;
                }
                else
                {
                    $this->printLogger("Table duplicated, but, please check num rows $newTableName");
                    return -3;
                }
                // end of checking count
                /////////////////////////////////
            }//end of if(!$result) query 2/2
            else
            {
                $this->printrR("Something went wrong duplicate Table\nINSERT INTO $oldTable -> $newTableName\n\n$query\n mysql_error() \n " . mysql_error());
                return false;
            }
        }
    }

你注意到这个函数只是复制一个表,这就是为什么有另一个函数从用户获取一个表数组并将表名数组一个接一个地传递给duplicateTable()。 此问题应包含任何其他功能,请告知我们。

一个解决方案出现在我的脑海中,将逐个复制表添加任何改进,我不确定插入是如何工作的,但也许如果我可以插入让我们说25%一次可能有帮助?

2 个答案:

答案 0 :(得分:2)

  

但是,有时脚本会失败,结果会被破坏,   因此,在执行之前,我必须备份10个有问题的表   脚本。

您可能需要在此处使用其他解决方案:transactions。您需要将故障脚本中使用的所有查询汇总到事务中。如果事务失败,则所有数据将与操作开始时的数据相同。如果查询得到正确执行 - 你没事。

答案 1 :(得分:1)

你为什么每次都复制这张桌子.. CLUSTERS 是一个很好的选择,它可以以分布式方式制作表的重复副本,并且更加可靠和安全。