PHP实现同步2个服务器MYSQL表及表结构,表同步,表结构同步

1.第一步先同步表

查询出要当前数据库对比源数据库需要删除的表和需要新建的表,同步表数据
重点语句:

  • SHOW TABLES (显示当前数据库中所有表的名称)
  • DROP TABLE {表名} (删除当前数据库中该表)
  • SHOW CREATE TABLE {表名} (获取创建该表的语句)

2.第二步再对比表结构->同步表结构

查询出两个数据库中表所有的字段,对比不同的表结构
重点语句:

  • SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name IN({表名数据}) AND table_schema = '{数据库名}' (获取当前库所有表的表结构)
  • SELECT COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where ORDINAL_POSITION = {列标识号} and table_schema = '{数据库名}' and table_name = '{表名}' (获取当前库该表的列标识号对应的字段名称)

3.第三步直接上代码

<?php
function dd($arr){
    echo "<pre>";
    var_dump($arr);
    echo "</pre>";
    die();
}

class MysqlSync{

    /**
     * 执行状态记录
     * @var array
     */
    private $stat = array();
    /**
     * 默认值需要加上引号的类型的索引
     * @var array
     */
    private $convert_map = array('varchar', 'char', 'tinytext', 'mediumtext', 'text', 'longtext', 'enum');

    /**
     * 数据库结构同步
     * @param $selfConf
     * @param $sourceConf
     * @return array
     */
    function sync($selfConf, $sourceConf){
        $self = mysqli_connect($selfConf['host'], $selfConf['user'], $selfConf['pwd'], $selfConf['db']);
        $source = mysqli_connect($sourceConf['host'], $sourceConf['user'], $sourceConf['pwd'], $sourceConf['db']);
        //删表 ,建表
        $selfData = $this->getTable($self);     //获取本身,和对比源的结构
        $sourceData = $this->getTable($source);
        $removeList = array_diff($selfData, $sourceData);       //如果自身有,源没有,就删除
        $createList = array_diff($sourceData, $selfData);       //如果源有,自身没有,就新增
        if(!empty($removeList)){        //执行删除操作
            $remove_tab = '';
            foreach($removeList as $val){
                $remove_tab .= "`{$val}`,";
            }
            $remove_tab = trim($remove_tab, ',');
            $remove_sql = "DROP TABLE {$remove_tab}";
            if($self->query($remove_sql)){
                $this->stat['success'][] = $remove_sql;
            }else{
                $this->stat['error'][] = $remove_sql;
            }
        }

        if(!empty($createList)){        //执行新增操作
            foreach($createList as $val){
                $create_sql = "SHOW CREATE TABLE `{$val}`";
                if($sql = $source->query($create_sql)->fetch_row()){
                    if($self->query($sql[1])){
                        $this->stat['success'][] = $sql[1];
                    }else{
                        $this->stat['error'][] = $sql[1];
                    }
                }
            }
        }

        //表结构
        $selfStructure = $this->getStructure($self,$selfConf['db']);
        $sourceStructure = $this->getStructure($source,$sourceConf['db']);
        foreach($sourceStructure as $pKey => $item){     //对比表的字段是否相同
            $val = $selfStructure[$pKey];
            if ($val){
                //dd($item);
                $removeColumn = array_diff_key($val, $item);
                $addColumn = array_diff_key($item, $val);
                if(!empty($removeColumn)){
                    foreach($removeColumn as $removeVal){
                        $removeColumnSql = "ALTER TABLE `{$pKey}` DROP COLUMN `{$removeVal['COLUMN_NAME']}`";
                        if($self->query($removeColumnSql)){
                            $this->stat['success'][] = $removeColumnSql;
                        }else{
                            $this->stat['error'][] = $removeColumnSql;
                        }
                    }
                }
                //dd($addColumn);
                if(!empty($addColumn)){
                    foreach($addColumn as $addVal){
                        $addInfo = "`{$addVal['COLUMN_NAME']}` {$addVal['COLUMN_TYPE']}";
                        //字符编码
                        if ($addVal['CHARACTER_SET_NAME']){
                            $addInfo .= " CHARACTER SET {$addVal['CHARACTER_SET_NAME']}";
                        }
                        //字符编码
                        if ($addVal['COLLATION_NAME']){
                            $addInfo .= " COLLATE {$addVal['COLLATION_NAME']}";
                        }
                        //是否为null
                        if ($addVal['IS_NULLABLE'] == 'NO'){
                            $addInfo .= " NOT NULL";
                        }
                        //默认值
                        if ($addVal['COLUMN_DEFAULT']!==null){
                            if(in_array($addVal['DATA_TYPE'], $this->convert_map)){
                                $addInfo .= " DEFAULT '{$addVal['COLUMN_DEFAULT']}'";
                            }else{
                                $addInfo .= " DEFAULT {$addVal['COLUMN_DEFAULT']}";
                            }
                        }

                        //EXTRA
                        if ($addVal['EXTRA']){
                            $addInfo .= " {$addVal['EXTRA']}";
                        }
                        //备注信息
                        if ($addVal['COLUMN_COMMENT']){
                            $addInfo .= " COMMENT '{$addVal['COLUMN_COMMENT']}'";
                        }
                        if($addVal['ORDINAL_POSITION'] == 1)
                        {
                            $addInfo .= " first";
                        }
                        else
                        {
                            $last_pos = $addVal['ORDINAL_POSITION'] - 1;
                            $last_col = $this->getAlterAfter($source,$sourceConf['db'],$addVal['TABLE_NAME'],$last_pos);
                            $addInfo .= " AFTER `{$last_col[0]['COLUMN_NAME']}`";
                        }
                        $addSql = "ALTER TABLE `{$pKey}` ADD COLUMN {$addInfo}";
                        if($self->query($addSql)){
                            $this->stat['success'][] = $addSql;
                        }else{
                            $this->stat['error'][] = $addSql;
                        }
                    }
                }
            }

        }
        return $this->stat;
    }

    /**
     * 获取表结构
     * @param $resource
     * @param $db
     * @return array
     */
    function getStructure($resource, $db){
        $table_str = '';
        $info = array();
        $sql_table = 'SHOW TABLES';
        $res_table = $resource->query($sql_table);
        while($row_table = $res_table->fetch_assoc()){
            $table_str .= "'" . current($row_table) . "',";
        }
        $table_str = trim($table_str, ',');
        $column_sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name IN({$table_str}) AND table_schema = '{$db}'";
        $column_res = $resource->query($column_sql);
        if($column_res) {
            while ($row_column = $column_res->fetch_assoc()) {
                $info[] = $row_column;
            }
            return $this->gen($info);
        }else{
            return array();
        }
    }

    /**
     * 获取字段排序
     * @param $resource
     * @param $db
     * @param $table
     * @param $lastPos
     * @return array
     */
    function getAlterAfter($resource,$db,$table,$lastPos){
        $info = [];
        $column_sql = "SELECT COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where ORDINAL_POSITION = {$lastPos} and table_schema = '{$db}' and table_name = '{$table}'";
        $column_res = $resource->query($column_sql);
        if($column_res) {
            while ($row_column = $column_res->fetch_assoc()) {
                $info[] = $row_column;
            }
        }
        return $info;
    }
    /**
     * 获取表列表
     * @param $resource
     * @param $db
     * @return array
     */
    function getTable($resource){
        $table_arr = [];
        $sql_table = 'SHOW TABLES';
        $res_table = $resource->query($sql_table);
        while($row_table = $res_table->fetch_assoc()){
            $table_arr []= current($row_table);
        }
        return $table_arr;
    }

    /**
     * 数据排序处理
     * @param $array
     * @return array
     */
    function gen($array){
        $data = array();
        foreach($array as $key => $item){
            if(!array_key_exists($item['TABLE_NAME'], $data)) {
                foreach ($array as $value) {
                    if ($value['TABLE_NAME'] == $item['TABLE_NAME']) {
                        $data[$item['TABLE_NAME']][$value['COLUMN_NAME']] = $value;
                    }
                }
            }
        }
        return $data;
    }

}

$sync = new MysqlSync();
$selfConf = array(      //待同步数据库
    'host'  => 'localhost',
    'user'  => 'root',
    'pwd'   => 'root',
    'db'    => 'yinghuo'
);
$sourceConf = array(        //同步来源数据库
    'host'  => 'localhost',
    'user'  => 'root',
    'pwd'   => 'root',
    'db'    => 'tp'
);
$res = $sync->sync($selfConf, $sourceConf);
dd($res);

4.有优化的地方请及时评论,我要更新

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。