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

标签 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%,它可能会有所帮助?

最佳答案

However Sometimes the script fails and the result gets corrupted, therefore I must backup 10 tables in question before i execute the script.

可能您需要在这里使用另一个解决方案:transactions 。您需要将失败脚本中使用的所有查询包装到事务中。如果事务失败,所有数据将与操作开始时相同。如果查询正确执行 - 就OK了。

关于php - 有效地复制/复制/备份数据库表 - mysql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14038348/

相关文章:

php - htaccess URL 重写在 PHP Slim 框架中不起作用

mysql - 在 mysql ( zend_db ) 上构建一个 select distinct

php - 如何使用表单发送所有购物车商品并插入数据库表

mysql - 连接 3 个具有不同列名的表

python - 尝试在 python 中上传到 MySQL 数据库时出现完整性错误

php - 如何使用php计算excel pmt

php - 在单个页面上使用 PHP、AJAX 和 jQuery 的多个上传表单不起作用

php - 我的 sql 查询只返回完全匹配的字符串。有没有办法返回最近的匹配项?

MySQL 表示 : Documentation #2054 - The server requested authentication method unknown to the client

php - 我需要 ON event_sheduler 的 super 权限