一下代码有些需要改动,有些为自己封装的函数,懒了直接上菜吧。慢慢改,不懂的咨询,看到会回复

 

分了两个文件 都是在模型控制器中

备份类

  1 <?php
  2 namespace app\admin\controller;
  3 use think\Controller;
  4 use think\Db;
  5 
  6 //接口类
  7 class Databackup extends Controller
  8 {
  9 
 10     // 任务--数据备份
 11     public function do_tasks()
 12     {
 13         $this->backup();
 14         action('common/lib/adminLog',['数据备份--成功']);
 15     }
 16 
 17 
 18     // 数据备份
 19     public function backup($sqlfilename='')
 20     {
 21         // 判断文件数量
 22         $L=glob(ROOT_PATH.'data/sqldata/*.sql');
 23         $n=count($L);
 24         if($n>10 && $L)
 25         {
 26             $L=array_reverse($L);
 27             foreach ($L as $k => $v) {
 28                 if($k > 3)
 29                 {
 30                     if(is_file($v))
 31                     {
 32                         unlink($v);
 33                     }
 34                 }
 35             }
 36         }
 37 
 38         // 录入数据表缓存
 39         $run_log = ROOT_PATH . 'data/sqldata/run.log';
 40         $sqlname=$sqlfilename==''?get_random_name():$sqlfilename;//备份文件名
 41         // 文件地址
 42         $path=ROOT_PATH . 'data/sqldata/' . $sqlname . '.sql';
 43         $max_size=512000;//分卷备份 - 文件长度限制(kb)
 44         // 全部备份
 45         $prefix=config('database.prefix');
 46         $sql="SHOW TABLE STATUS LIKE '" . $prefix . "%'";
 47         $ret = Db::query($sql);
 48         $tables=[];
 49         if($ret)
 50         {
 51             foreach ($ret AS $table)
 52             {
 53                 $tableName=$table['Name'];
 54                 $tables[$tableName]=-1;
 55             }
 56         }
 57 
 58         $res=put_tables_list($run_log,$tables);
 59         if($res['code']==0)
 60         {
 61             action('common/lib/adminLog',['数据备份----'.$res['msg']]);
 62             return $this->error($res['msg']);
 63         }
 64 
 65 
 66 
 67         // 备份数据
 68         $res=dump_table($run_log, $path,$max_size);
 69         if(IS_CLI==false && $sqlfilename=='')
 70         {
 71             if($res['code']==0)
 72             {
 73                 action('common/lib/adminLog',['数据备份----'.$res['msg']]);
 74                 return $this->error($res['msg']);
 75             }else{
 76                 action('common/lib/adminLog',['数据备份--成功']);
 77                 return $this->success('备份成功');
 78             }
 79         }else{
 80             return $res;
 81         }
 82         
 83     }
 84     
 85     
 86 }
 87 
 88 
 89 
 90 
 91 // 创建备份文件名
 92 function get_random_name()
 93 {
 94     $str = date('YmdHis').'_';
 95 
 96     for ($i = 0; $i < 6; $i++)
 97     {
 98         $str .= chr(mt_rand(97, 122));
 99     }
100 
101     return $str;
102 }
103 
104 
105 
106 
107 /**
108  *  生成备份文件头部
109  *
110  * @access  public
111  * @param   int     文件卷数
112  *
113  * @return  string  $str    备份文件头部
114  */
115 function make_head()
116 {
117     $version = Db::query('SELECT VERSION() AS ver');
118     FLog($_SERVER);
119     /* 系统信息 */
120     $sys_info['os']         = PHP_OS;
121     $sys_info['web_server'] = isset($_SERVER['HTTP_ORIGIN'])?$_SERVER['HTTP_ORIGIN']:'http://basesc.net';
122     // $sys_info['server_ip'] = $_SERVER['SERVER_ADDR'];
123     $sys_info['php_ver']    = PHP_VERSION;
124     $sys_info['mysql_ver']  = $version[0]['ver'];
125 
126     $sys_info['date']       = date('Y-m-d H:i:s');
127 
128     $head = "-- sjx v1.x SQL Dump Program\r\n".
129              "-- " . $sys_info['web_server'] . "\r\n".
130              "-- \r\n".
131              "-- DATE : ".$sys_info["date"]."\r\n".
132              "-- MYSQL SERVER VERSION : ".$sys_info['mysql_ver']."\r\n".
133              "-- PHP VERSION : ".$sys_info['php_ver']."\r\n";
134 
135     return $head;
136 }
137 
138 /**
139  *  备份一个数据表
140  *
141  * @access  public
142  * @param   string      $path       保存路径表名的文件
143  * @param   int         $vol        卷标
144  *
145  * @return  array       $tables     未备份完的表列表
146  */
147 function dump_table($path, $sqlpath,$max_size)
148 {
149     $sql_num=0;
150 
151     $tables = get_tables_list($path);
152 
153     if ($tables === false)
154     {
155         return false;
156     }
157 
158     if (empty($tables))
159     {
160         return $tables;
161     }
162 
163     $sql_head = make_head();
164 
165 
166     foreach($tables as $table => $pos)
167     {
168 
169         if ($pos == -1)
170         {
171             /* 获取表定义,如果没有超过限制则保存 */
172             $table_df = get_table_df($table, true);
173 
174             if ($sql_num == 0)
175             {
176                 /* 第一条记录,强制写入 */
177                 $sql_head .= $table_df;
178                 $sql_num +=2;
179                 $tables[$table] = 0;
180             }else
181             {
182                 $sql_head .= $table_df;
183                 $sql_num +=2;
184                 $pos = 0;
185             }
186         }
187 
188         /* 尽可能多获取数据表数据 */
189         $post_pos = get_table_data($table);
190 
191         if ($post_pos['code'] == -1)
192         {
193             /* 该表已经完成,清除该表 */
194             unset($tables[$table]);
195         }else if($post_pos['code']==0)
196         {
197             unset($tables[$table]);
198             $sql_head.=$post_pos['html'];
199         }
200         else
201         {
202             /* 该表未完成。说明将要到达上限,记录备份数据位置 */
203             $tables[$table] = $post_pos;
204             $sql_head.=$post_pos['html'];
205             break;
206         }
207 
208     }
209 
210     $sql_head .= '-- END sjx v1.x SQL Dump Program ';
211 
212     @file_put_contents($sqlpath, $sql_head);
213 
214     $res=put_tables_list($path, $tables);
215     if($res['code']==0)
216     {
217         return ['code'=>0,'msg'=>$res['msg']];
218     }else{
219         return ['code'=>1,'msg'=>'','data'=>$tables];
220     }
221 }
222 
223 /**
224  *  将数据表数组写入指定文件
225  *
226  * @access  public
227  * @param   string      $path    文件路径
228  * @param   array       $arr    要写入的数据
229  *
230  * @return  boolen
231  */
232 function put_tables_list($path, $arr,$data=[])
233 {
234     if (is_array($arr))
235     {
236 
237         if($data)
238         {
239             $msg="/* \r\n";
240             foreach ($data as $k1 => $v1) {
241                 $msg .= $k1 . ': ' . $v1 . ";\r\n";
242             }
243             $msg.="*/ \r\n";
244             $str = $msg;
245         }else{
246             $str = '';
247         }
248 
249         
250         foreach($arr as $key => $val)
251         {
252             $str .= $key . ': ' . $val . ";\r\n";
253             
254         }
255 
256         @file_put_contents($path, $str);
257         return ['code'=>1];
258     }
259     else
260     {
261         return ['code'=>0,'msg'=>'It need a array'];
262     }
263 }
264 
265 /**
266  *  将文件中数据表列表取出
267  *
268  * @access  public
269  * @param   string      $path    文件路径
270  *
271  * @return  array       $arr    数据表列表
272  */
273 function get_tables_list($path)
274 {
275     if (!file_exists($path))
276     {
277         echo $path . ' is not exists';
278         return false;
279     }
280 
281     $arr = array();
282     $str = @file_get_contents($path);
283 
284     if (!empty($str))
285     {
286         $tmp_arr = explode("\n", $str);
287         foreach ($tmp_arr as $val)
288         {
289             $val = trim ($val, "\r;");
290             if (!empty($val))
291             {
292                 list($table, $count) = explode(':',$val);
293                 $arr[$table] = $count;
294             }
295         }
296     }
297 
298     return $arr;
299 }
300 
301 
302 /**
303  *  获取指定表的定义
304  *
305  * @access  public
306  * @param   string      $table      数据表名
307  * @param   boolen      $add_drop   是否加入drop table
308  *
309  * @return  string      $sql
310  */
311 function get_table_df($table, $add_drop = false)
312 {
313     $charset=config('database.charset');
314 
315     if ($add_drop)
316     {
317         $table_df = "DROP TABLE IF EXISTS `$table`;\r\n";
318     }
319     else
320     {
321         $table_df = '';
322     }
323 
324     $tmp_arr = Db::query("SHOW CREATE TABLE `$table`");
325     $tmp_sql = $tmp_arr[0]['Create Table'];
326     // $tmp_sql = substr($tmp_sql, 0, strrpos($tmp_sql, ")") + 1); //去除行尾定义。
327     // $table_df .= $tmp_sql . " ENGINE=MyISAM DEFAULT CHARSET=" . str_replace('-', '', $charset) . ";\r\n";
328 
329     $table_df .= $tmp_sql.";\r\n";
330 
331     return $table_df;
332 }
333 
334 /**
335  *  获取指定表的数据定义
336  *
337  * @access  public
338  * @param   string      $table      表名
339  * @param   int         $pos        备份开始位置
340  *
341  * @return  int         $post_pos   记录位置
342  */
343 function get_table_data($table)
344 {
345     $offset=300;
346     $post_pos=0;
347 
348     /* 获取数据表记录总数 */
349     $total = Db::query("SELECT COUNT(*) as count FROM $table");
350     $total=$total[0]['count'];
351 
352     if ($total == 0)
353     {
354         /* 无须处理 */
355         return ['code'=>-1];
356     }
357 
358     /* 确定循环次数 */
359     $cycle_time = ceil(($total) / $offset); //每次取offset条数。需要取的次数
360 
361     $dump_sql="";
362 
363     /* 循环查数据表 */
364     for($i = 0; $i<$cycle_time; $i++)
365     {
366         
367         /* 获取数据库数据 */
368         $data = Db::query("SELECT * FROM $table LIMIT " . ($offset * $i) . ', ' . $offset);
369         $data_count = count($data);
370 
371 
372         $fields = array_keys($data[0]);
373         $start_sql = "INSERT INTO `$table` ( `" . implode("`, `", $fields) . "` ) VALUES ";
374 
375         $tmp_dump_sql='';
376         /* 循环将数据写入 */
377         for($j=0; $j< $data_count; $j++)
378         {
379             $record = $data[$j];
380 
381             $tmp_dump_sql .= $start_sql." ( '" . implode("', '" , $record) . "' );\r\n";
382             $post_pos++;
383         }
384         if($tmp_dump_sql!='')
385         {
386            $dump_sql .= $tmp_dump_sql;
387         }
388         
389 
390     }
391 
392     if($total==$post_pos)
393     {
394         /* 所有数据已经写完 */
395         return ['code'=>0,'html'=>$dump_sql];
396     }
397 }
View Code

调用展示数据表类

  1 <?php
  2 namespace app\admin\controller;
  3 use think\Db;
  4 
  5 
  6 // 数据表接口
  7 class Intdata extends Base
  8 {
  9     public function __construct(){
 10         parent::__construct();
 11     }
 12 
 13 
 14     // 数据表列表--数据优化
 15     public function index()
 16     {
 17         // 将当前数据库的表信息全部展示出来
 18         $prefix=config('database.prefix');
 19         $sql="SHOW TABLE STATUS LIKE '" . $prefix . "%'";
 20         $ret = Db::query($sql);
 21 
 22         $list=[];
 23         $count=count($list);
 24         $num=0;
 25         if($ret)
 26         {
 27             foreach ($ret as $k => $v) {
 28                 $num += $v['Data_free'];
 29                 $type = $v['Engine'];
 30                 $charset = $v['Collation'];
 31                 $list[] = [
 32                     'table' => $v['Name'],
 33                     'type' => $type,
 34                     'rec_num' => $v['Rows'],
 35                     'rec_size' => sprintf(" %.2f KB", $v['Data_length'] / 1024),
 36                     // 'rec_index' => $v['Index_length'],
 37                     'rec_chip' => $v['Data_free'],
 38                     'charset' => $charset
 39                 ];
 40             }
 41         }
 42 
 43         $this->assign('list',$list);
 44         $this->assign('num',$num);
 45         $this->assign('count',$count);
 46         return view();
 47     }  
 48 
 49 
 50     // 数据优化 只针对 engine=MyISAM
 51     public function youhua()
 52     {
 53         $tableName=input('other','');
 54         if($tableName!='')
 55         {
 56             $row = Db::query('OPTIMIZE TABLE ' . $tableName);
 57             if($row[0])
 58             {
 59                 $row=$row[0];
 60                 /* 优化出错,尝试修复 */
 61                 if ($row['Msg_type'] =='error' && strpos($row['Msg_text'], 'repair') !== false)
 62                 {
 63                     Db::query('REPAIR TABLE ' . $tableName);
 64                 }
 65             }
 66             return $this->success('优化成功');
 67         }
 68         $prefix=config('database.prefix');
 69         $sql="SHOW TABLE STATUS LIKE '" . $prefix . "%'";
 70         $tables = Db::query($sql);
 71         if($tables)
 72         {
 73             foreach ($tables AS $table)
 74             {
 75                 $tableName=$table['Name'];
 76                 $row = Db::query('OPTIMIZE TABLE ' . $tableName);
 77                 if($row[0])
 78                 {
 79                     $row=$row[0];
 80                     /* 优化出错,尝试修复 */
 81                     if ($row['Msg_type'] =='error' && strpos($row['Msg_text'], 'repair') !== false)
 82                     {
 83                         Db::query('REPAIR TABLE ' . $tableName);
 84                     }
 85                 }
 86             }
 87         }
 88         
 89 
 90         return $this->success('优化成功');
 91     }
 92 
 93     // 备份
 94     public function backup()
 95     {
 96         action('Databackup/backup');
 97     }
 98 
 99     // 数据备份列表
100     public function backup_list()
101     {
102         // echo '<pre>';
103         $L=glob(ROOT_PATH.'data/sqldata/*.sql');
104         $list=[];
105         if($L)
106         {
107             $L=array_reverse($L);
108             foreach ($L as $k => &$v) {
109                 $info=pathinfo($v);
110                 $time=filectime($v);
111                 $list[]=[
112                     'file_name'=>$info['filename'],
113                     'file_time'=>date('Y-m-d H:i',$time),
114                 ];
115             }
116         }
117         $this->assign('list',$list);
118         return view();
119     }
120 
121     // 文件下载
122     public function getfile_bytes()
123     {
124         $filename=input('filename','');
125 
126         $path=ROOT_PATH.'data/sqldata/'.$filename.'.sql';
127         if(!is_file($path))
128         {
129             return $this->error('指定文件不存在');
130         }
131         $filename.='.sql';
132         action('common/Interfun/download',[$path,$filename]);
133     }
134 
135     // 还原备份数据
136     public function return_data()
137     {
138         $filename=input('other','');
139         $path=ROOT_PATH.'data/sqldata/'.$filename.'.sql';
140 
141         // 还原之前备份
142         action('Databackup/backup',$filename.'_returnBefore');
143 
144         $this->_import($path);
145         action('common/lib/adminLog',['数据还原---文件:'.$filename.'.sql']);
146         return $this->success('还原备份成功','intdata/index');
147     } 
148 
149     
150 
151     // 删除备份数据
152     public function del()
153     {
154         $filename=input('other','');
155 
156         $path=ROOT_PATH.'data/sqldata/'.$filename.'.sql';
157         if(!is_file($path))
158         {
159             return $this->error('指定文件不存在');
160         }else{
161             action('common/lib/adminLog',['备份数据删除']);
162             unlink($path);
163             return $this->success('删除成功');
164         }
165     }
166 
167     /**  
168      * 将sql导入到数据库(普通导入)  
169      *  
170      * @param string $sqlfile  
171      * @return boolean  
172      */  
173     private function _import($sqlfile) {   
174         // sql文件包含的sql语句数组   
175         $sqls = array ();   
176         $f = fopen ( $sqlfile, "rb" );   
177         // 创建表缓冲变量   
178         $create = '';   
179         while ( ! feof ( $f ) ) {   
180             // 读取每一行sql   
181             $line = fgets ( $f );   
182             // 如果包含'-- '等注释,或为空白行,则跳过   
183             if (trim ( $line ) == '' || preg_match ( '/--*?/', $line, $match )) {   
184                 continue;   
185             }
186 
187             // 如果结尾包含';'(即为一个完整的sql语句,这里是插入语句),并且不包含'ENGINE='(即创建表的最后一句),   
188             if (! preg_match ( '/;/', $line, $match ) || preg_match ( '/ENGINE=/', $line, $match )) {   
189                 // 将本次sql语句与创建表sql连接存起来   
190                 $create .= $line;   
191                 // 如果包含了创建表的最后一句   
192                 if (preg_match ( '/ENGINE=/', $create, $match )) {   
193                     // 则将其合并到sql数组   
194                     $sqls [] = $create;   
195                     // 清空当前,准备下一个表的创建   
196                     $create = '';   
197                 }   
198                 // 跳过本次   
199                 continue;   
200             }   
201             $sqls [] = $line;   
202         }   
203         fclose ( $f );   
204         // 循环sql语句数组,分别执行   
205         foreach ( $sqls as $sql ) {   
206             $tables = Db::execute(trim ( $sql ));
207         }   
208         return true;   
209     }   
210 
211 
212 
213     
214     
215     
216 
217     
218     
219 
220 
221     // 批量修改数据表引擎
222     // public function alter_engine()
223     // {
224     //     // 将数据表引擎转化
225     //     $sql="SELECT TABLE_NAME FROM information_schema.TABLES where TABLE_SCHEMA='basesc2' and `ENGINE`='InnoDB' and TABLE_NAME LIKE 'sjx_%';";
226     //     $res = Db::query($sql);
227     //     if($res)
228     //     {
229     //         foreach ($res as $k => $table) {
230     //             $tableName=$table['TABLE_NAME'];
231     //             $tables = Db::execute('alter table '.$tableName.' engine=MyISAM; ');
232     //         }
233     //     }
234     // }
235 
236 
237 
238     
239     
240 }
View Code

 

posted on 2020-10-12 10:42  思君邪  阅读(186)  评论(0编辑  收藏  举报