├── README.md ├── config.php └── mysqldiff.php /README.md: -------------------------------------------------------------------------------- 1 | phpmysqldiff - A PHP Console Tool 2 | ========================= 3 | 4 | A mysql table diff tool written in php. 5 | 6 | Requirements 7 | ------------ 8 | 9 | * MySQL 10 | * PHP 11 | 12 | Installation 13 | ------------ 14 | ``` 15 | git clone https://github.com/exinnet/mysqldiff.git 16 | cd mysqldiff 17 | vi config.php # config mysql connection info 18 | ``` 19 | 20 | Usage 21 | ------------- 22 | 23 | ```bash 24 | php mysqldiff.php 25 | ``` 26 | 27 | Custom 28 | -------- 29 | you would like to adjust some params to make it suited for your server. 30 | 31 | * Config mysql connection 32 | ```php 33 | vi config.php 34 | 35 | return [ 36 | "master" => [ 37 | "host" => "127.0.0.1", 38 | "user" => "root", 39 | "pwd" => "root", 40 | "db" => "test", 41 | ], 42 | "slave" => [ 43 | "host" => "127.0.0.1", 44 | "user" => "root", 45 | "pwd" => "root", 46 | "db" => "test2", 47 | ], 48 | ]; 49 | ``` 50 | 51 | Contributors 52 | ---------- 53 | - [exinnet](https://github.com/exinnet) 54 | - [koiding](https://github.com/koiding) 55 | - [liheng666](https://github.com/liheng666) 56 | 57 | Todo List 58 | ---------- 59 | 60 | - 自主选择需要新增的表 61 | - 自主选择需要新增的列 62 | - 调研master上是否可能有删除表/列的情况 63 | - Web操作界面 64 | - 执行结果生成报告(本地文件/邮件通知) 65 | - 代码优化,错误,异常的处理,超时处理,单元测试 66 | 67 | Discussing 68 | ---------- 69 | - [submit issue](https://github.com/exinnet/mysqldiff/issues/new) 70 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | [ 4 | "host" => "127.0.0.1", 5 | "port" => "3306", 6 | "user" => "root", 7 | "pwd" => "root", 8 | "db" => "test", 9 | ], 10 | "slave" => [ 11 | "host" => "127.0.0.1", 12 | "port" => "3306", 13 | "user" => "root", 14 | "pwd" => "root", 15 | "db" => "test2", 16 | ], 17 | ]; 18 | -------------------------------------------------------------------------------- /mysqldiff.php: -------------------------------------------------------------------------------- 1 | conn['master'] = $dbh_conn_master; 28 | $this->conn['slave'] = $dbh_conn_slave; 29 | } 30 | 31 | public function listTables() 32 | { 33 | $sql = 'SHOW TABLES;'; 34 | $query_master = $this->conn['master']->query($sql); 35 | $query_slave = $this->conn['slave']->query($sql); 36 | $query_master = $query_master->fetchAll(PDO::FETCH_COLUMN); 37 | $query_slave = $query_slave->fetchAll(PDO::FETCH_COLUMN); 38 | return [$query_master, $query_slave]; 39 | } 40 | 41 | public function getCreateTableSql($table) 42 | { 43 | $sql = 'SHOW CREATE TABLE `' . $table . '`;'; 44 | $query = $this->conn['master']->query($sql); 45 | $row = $query->fetch(PDO::FETCH_ASSOC); 46 | $this->create_table_sqls[$table] = $row['Create Table']; 47 | return $this->create_table_sqls[$table]; 48 | } 49 | 50 | public function addTables($table) 51 | { 52 | $_sql = $this->getCreateTableSql($table); 53 | $ret = $this->conn['slave']->exec($_sql); 54 | if ($ret !== 0) { 55 | $this->error_add_tables[] = $table; 56 | } 57 | $this->success_add_tables[] = $table; 58 | } 59 | 60 | public function repairTable($table) 61 | { 62 | $this->getCreateTableSql($table); 63 | 64 | $_sql = 'DESC ' . $table; 65 | 66 | $stmt = $this->conn['master']->prepare($_sql); 67 | $stmt->execute(); 68 | $master_table_fields = $stmt->fetchAll(); 69 | $master_table_fields = array_column($master_table_fields, 'Field'); 70 | 71 | $stmt = $this->conn['slave']->prepare($_sql); 72 | $stmt->execute(); 73 | $slave_table_fields = $stmt->fetchAll(); 74 | $slave_table_fields = array_column($slave_table_fields, 'Field'); 75 | 76 | foreach ($master_table_fields as $field) { 77 | if (!in_array($field, $slave_table_fields)) { 78 | $_str = $this->create_table_sqls[$table]; 79 | $pattern = sprintf('/`%s`.*?(?=,\s|\s\))/s', $field); 80 | preg_match($pattern, $_str, $matchs); 81 | 82 | $tmp = $matchs[0] . ';'; 83 | $repair_sql = sprintf('ALTER TABLE `%s` ADD %s', $table, $tmp); 84 | 85 | $ret = $this->conn['slave']->exec($repair_sql); 86 | if ($ret !== 0) { 87 | $this->error_repair_tables[] = $table; 88 | } 89 | $this->success_repair_tables[] = $table; 90 | } 91 | } 92 | 93 | $_sql = "SHOW CREATE TABLE `$table`"; 94 | $stmt = $this->conn["slave"]->query($_sql); 95 | $row = $stmt->fetch(PDO::FETCH_ASSOC); 96 | $slave_create_sqls = $row["Create Table"]; 97 | $pattern = "/(UNIQUE|PRIMARY|) KEY(.*?)\)/m"; 98 | preg_match_all($pattern, $this->create_table_sqls[$table], $match_master); 99 | preg_match_all($pattern, $slave_create_sqls, $match_slave); 100 | $exist_key_slave = array_flip($match_slave[0]); 101 | foreach ($match_master[0] as $item) { 102 | if (!isset($exist_key_slave[$item])) { 103 | $repair_sql = sprintf("ALTER TABLE `%s` ADD %s", $table, $item); 104 | $ret = $this->conn['slave']->exec($repair_sql); 105 | if ($ret !== 0) { 106 | $this->error_repair_tables[] = $table; 107 | } 108 | $this->success_repair_tables[] = $table; 109 | } 110 | } 111 | } 112 | 113 | public function run() 114 | { 115 | list($master_tables, $slave_tables) = $this->listTables(); 116 | 117 | foreach ($master_tables as $table) { 118 | if (!in_array($table, $slave_tables)) { 119 | $this->addTables($table); 120 | } 121 | else 122 | { 123 | $this->repairTable($table); 124 | } 125 | } 126 | } 127 | 128 | public function getAddTables() 129 | { 130 | return [array_unique($this->success_add_tables), array_unique($this->error_add_tables)]; 131 | } 132 | 133 | public function getRepairTables() 134 | { 135 | return [array_unique($this->success_repair_tables), array_unique($this->error_repair_tables)]; 136 | } 137 | 138 | } 139 | 140 | $conf = require dirname(__FILE__) . '/config.php'; 141 | 142 | $md = new MysqlDiff($conf); 143 | $md->run(); 144 | 145 | list($success_add_tables, $error_add_tables) = $md->getAddTables(); 146 | list($success_repair_tables, $error_repair_tables) = $md->getRepairTables(); 147 | 148 | echo sprintf("Success add tables:\t%s\n", implode(',', $success_add_tables)); 149 | echo sprintf("Error add tables:\t%s\n", implode(',', $error_add_tables)); 150 | 151 | echo sprintf("Success repair tables:\t%s\n", implode(',', $success_repair_tables)); 152 | echo sprintf("Error repair tables:\t%s\n", implode(',', $error_repair_tables)); 153 | --------------------------------------------------------------------------------