SqlDump.class.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Fanwe 方维直播系统
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2011 http://www.fanwe.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Author: 云淡风轻(1956838968@qq.com)
  8. // +----------------------------------------------------------------------
  9. //数据库全库导出,导入的操作类
  10. import("Think.Db.Db");
  11. class SqlDump extends Think
  12. {
  13. private $db;
  14. private $max_size; //分卷的最大文件大小
  15. public function __construct()
  16. {
  17. $this->db = Db::getInstance();
  18. $this->max_size = conf("DB_VOL_MAXSIZE");
  19. }
  20. /**
  21. * 生成备份文件头部
  22. *
  23. * @access public
  24. * @param int 文件卷数
  25. *
  26. * @return string $str 备份文件头部
  27. */
  28. private function make_head($vol)
  29. {
  30. /* 系统信息 */
  31. $sys_info['os'] = PHP_OS;
  32. $sys_info['web_server'] = $_SERVER["SERVER_SOFTWARE"];
  33. $sys_info['php_ver'] = php_sapi_name();
  34. $sys_info['mysql_ver'] = mysql_get_server_info();
  35. $sys_info['date'] = date('Y-m-d H:i:s');
  36. $head = "-- fanwe SQL Dump Program\r\n".
  37. "-- " . $sys_info['web_server'] . "\r\n".
  38. "-- \r\n".
  39. "-- DATE : ".$sys_info["date"]."\r\n".
  40. "-- MYSQL SERVER VERSION : ".$sys_info['mysql_ver']."\r\n".
  41. "-- PHP VERSION : ".$sys_info['php_ver']."\r\n".
  42. "-- Vol : ".$vol."\r\n\r\n\r\n";
  43. return $head;
  44. }
  45. /**
  46. * 分卷导出
  47. *
  48. * @return boolean
  49. */
  50. public function dump()
  51. {
  52. $dumptime = get_gmtime(); //当前导出的时间
  53. $tables_all = $this->db->getTables();
  54. $tables = array();
  55. foreach($tables_all as $table)
  56. {
  57. if(preg_match("/".conf('DB_PREFIX')."/",$table))
  58. {
  59. array_push($tables,$table);
  60. }
  61. }
  62. $vol = 1;
  63. $dumpsql_vol = $this->make_head($vol); //每一卷的SQL语句
  64. $dumpfile = array();
  65. foreach ($tables as $key=>$tbname)
  66. {
  67. $modelname=str_replace(conf('DB_PREFIX'),'',$tbname);
  68. $tbname_o = $tbname;
  69. $tbname = str_replace(conf('DB_PREFIX'),'%DB_PREFIX%',$tbname);
  70. $dumpsql_vol .= "DROP TABLE IF EXISTS `$tbname`;\r\n"; //用于表结构导出处理的Sql语句
  71. $tmp_arr = $this->db->query("SHOW CREATE TABLE `$tbname_o`");
  72. $tmp_sql = $tmp_arr[0]['Create Table'].";\r\n";
  73. $tmp_sql = str_replace(conf('DB_PREFIX'),'%DB_PREFIX%',$tmp_sql);
  74. $dumpsql_vol .= $tmp_sql; //表结构语句处理结束
  75. $modelname = parse_name($modelname,1);
  76. $model=D($modelname);
  77. //$tableData=$model->findAll(); //查询当前表的所有数据
  78. $count = $model->count();
  79. if($count>500)
  80. {
  81. $count = ceil($count/500);
  82. if($count>0)
  83. {
  84. for($i=1;$i<=$count;$i++)
  85. {
  86. $limit_str = (($i-1)*500).",500";
  87. $rows = $model->limit($limit_str)->findAll();
  88. if(count($rows)>0)
  89. {
  90. foreach($rows as $row)
  91. {
  92. $dumpsql_row = "INSERT INTO `{$tbname}` VALUES ("; //用于每行数据插入的SQL脚本语句
  93. foreach($row as $col_value)
  94. {
  95. $dumpsql_row .="'".mysql_real_escape_string($col_value)."',";
  96. }
  97. $dumpsql_row=substr($dumpsql_row,0,-1); //删除最后一个逗号
  98. $dumpsql_row .= ");\r\n";
  99. $dumpsql_vol.= $dumpsql_row;
  100. }
  101. }
  102. //开始判断分卷长度
  103. if(strlen($dumpsql_vol)>$this->max_size)
  104. {
  105. //文件大小超过
  106. //$dumpfile[] = $dumpsql_vol; //存入SQL文件集合
  107. //开始写入sql脚本
  108. $filepath = get_real_path()."public/db_backup/"; //导出的目录
  109. $filename = $dumptime."_".$vol.".sql"; //导出的sql名
  110. $rs = file_put_contents($filepath.$filename,$dumpsql_vol);
  111. if($rs==0)
  112. {
  113. //导出失败
  114. for($ii=1;$ii<=$vol;$ii++)
  115. {
  116. @unlink($filepath.$dumptime."_".$ii.".sql");
  117. }
  118. return false;
  119. }
  120. $vol++; //增加卷数
  121. $dumpsql_vol = $this->make_head($vol); //重新制作卷头
  122. }
  123. elseif($key==count($tables)-1&&$i==$count-1)
  124. {
  125. //读取至最后一张表的最后一行
  126. //$dumpfile[] = $dumpsql_vol; //存入SQL文件集合
  127. //开始写入sql脚本
  128. $filepath = get_real_path()."public/db_backup/"; //导出的目录
  129. $filename = $dumptime."_".$vol.".sql"; //导出的sql名
  130. $rs = file_put_contents($filepath.$filename,$dumpsql_vol);
  131. if($rs==0)
  132. {
  133. //导出失败
  134. for($ii=1;$ii<=$vol;$ii++)
  135. {
  136. @unlink($filepath.$dumptime."_".$ii.".sql");
  137. }
  138. return false;
  139. }
  140. }
  141. }
  142. }
  143. else
  144. {
  145. if($key==count($tables)-1)
  146. {
  147. //读取至最后一张表的最后一行
  148. // $dumpfile[] = $dumpsql_vol; //存入SQL文件集合
  149. //开始写入sql脚本
  150. $filepath = get_real_path()."public/db_backup/"; //导出的目录
  151. $filename = $dumptime."_".$vol.".sql"; //导出的sql名
  152. $rs = file_put_contents($filepath.$filename,$dumpsql_vol);
  153. if($rs==0)
  154. {
  155. //导出失败
  156. for($ii=1;$ii<=$vol;$ii++)
  157. {
  158. @unlink($filepath.$dumptime."_".$ii.".sql");
  159. }
  160. return false;
  161. }
  162. }
  163. //开始写入sql脚本
  164. }
  165. }
  166. else
  167. {
  168. //小于一千条数据时
  169. if($count>0)
  170. {
  171. for($i=0;$i<$count;$i++)
  172. {
  173. $rows = $model->limit($i.",1")->findAll();
  174. if(count($rows)>0)
  175. {
  176. foreach($rows as $row)
  177. {
  178. $dumpsql_row = "INSERT INTO `{$tbname}` VALUES ("; //用于每行数据插入的SQL脚本语句
  179. foreach($row as $col_value)
  180. {
  181. $dumpsql_row .="'".mysql_real_escape_string($col_value)."',";
  182. }
  183. $dumpsql_row=substr($dumpsql_row,0,-1); //删除最后一个逗号
  184. $dumpsql_row .= ");\r\n";
  185. $dumpsql_vol.= $dumpsql_row;
  186. }
  187. }
  188. //开始判断分卷长度
  189. if(strlen($dumpsql_vol)>$this->max_size)
  190. {
  191. //文件大小超过
  192. //$dumpfile[] = $dumpsql_vol; //存入SQL文件集合
  193. //开始写入sql脚本
  194. $filepath = get_real_path()."public/db_backup/"; //导出的目录
  195. $filename = $dumptime."_".$vol.".sql"; //导出的sql名
  196. $rs = file_put_contents($filepath.$filename,$dumpsql_vol);
  197. if($rs==0)
  198. {
  199. //导出失败
  200. for($ii=1;$ii<=$vol;$ii++)
  201. {
  202. @unlink($filepath.$dumptime."_".$ii.".sql");
  203. }
  204. return false;
  205. }
  206. $vol++; //增加卷数
  207. $dumpsql_vol = $this->make_head($vol); //重新制作卷头
  208. }
  209. elseif($key==count($tables)-1&&$i==$count-1)
  210. {
  211. //读取至最后一张表的最后一行
  212. //$dumpfile[] = $dumpsql_vol; //存入SQL文件集合
  213. //开始写入sql脚本
  214. $filepath = get_real_path()."public/db_backup/"; //导出的目录
  215. $filename = $dumptime."_".$vol.".sql"; //导出的sql名
  216. $rs = file_put_contents($filepath.$filename,$dumpsql_vol);
  217. if($rs==0)
  218. {
  219. //导出失败
  220. for($ii=1;$ii<=$vol;$ii++)
  221. {
  222. @unlink($filepath.$dumptime."_".$ii.".sql");
  223. }
  224. return false;
  225. }
  226. }
  227. }
  228. }
  229. else
  230. {
  231. if($key==count($tables)-1)
  232. {
  233. //读取至最后一张表的最后一行
  234. // $dumpfile[] = $dumpsql_vol; //存入SQL文件集合
  235. //开始写入sql脚本
  236. $filepath = get_real_path()."public/db_backup/"; //导出的目录
  237. $filename = $dumptime."_".$vol.".sql"; //导出的sql名
  238. $rs = file_put_contents($filepath.$filename,$dumpsql_vol);
  239. if($rs==0)
  240. {
  241. //导出失败
  242. for($ii=1;$ii<=$vol;$ii++)
  243. {
  244. @unlink($filepath.$dumptime."_".$ii.".sql");
  245. }
  246. return false;
  247. }
  248. }
  249. //开始写入sql脚本
  250. }
  251. }//end 数据条判断
  252. }
  253. return true;
  254. }
  255. /**
  256. * 恢复列表的备份
  257. *
  258. * @param array $filelist
  259. * @return string
  260. */
  261. public function restore($filelist)
  262. {
  263. set_time_limit(0);
  264. $filepath = get_real_path()."public/db_backup/"; //导出的目录
  265. foreach($filelist as $fileItem)
  266. {
  267. $sql = file_get_contents($filepath.$fileItem['filename']);
  268. $sql = $this->remove_comment($sql);
  269. $sql = trim($sql);
  270. $sql = str_replace("\r", '', $sql);
  271. $segmentSql = explode(";\n", $sql);
  272. foreach($segmentSql as $itemSql)
  273. {
  274. if($itemSql!='')
  275. {
  276. $itemSql = str_replace("%DB_PREFIX%",conf('DB_PREFIX'),$itemSql);
  277. $this->db->query($itemSql);
  278. if($this->db->getError()!="")
  279. {
  280. return $this->db->getError();
  281. }
  282. }
  283. }
  284. }
  285. return "";
  286. }
  287. /**
  288. * 过滤SQL查询串中的注释。该方法只过滤SQL文件中独占一行或一块的那些注释。
  289. *
  290. * @access public
  291. * @param string $sql SQL查询串
  292. * @return string 返回已过滤掉注释的SQL查询串。
  293. */
  294. private function remove_comment($sql)
  295. {
  296. /* 删除SQL行注释,行注释不匹配换行符 */
  297. $sql = preg_replace('/^\s*(?:--|#).*/m', '', $sql);
  298. /* 删除SQL块注释,匹配换行符,且为非贪婪匹配 */
  299. //$sql = preg_replace('/^\s*\/\*(?:.|\n)*\*\//m', '', $sql);
  300. $sql = preg_replace('/^\s*\/\*.*?\*\//ms', '', $sql);
  301. return $sql;
  302. }
  303. }
  304. ?>