Databackup.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. namespace app\admin\controller;
  3. use app\admin\controller\base\Permissions;
  4. use databackup\src\Backup;
  5. use think\Env;
  6. use think\Request;
  7. use think\Session;
  8. /**
  9. * 备份大数据,还原时间太长,效率太差
  10. * Class Databackup
  11. * @package app\admin\controller
  12. */
  13. class Databackup extends Permissions
  14. {
  15. /** @var Backup */
  16. private static $sdk;
  17. const DEFAULT_PATH = RUNTIME_PATH . 'backup' . DS;
  18. protected function _initialize()
  19. {
  20. parent::_initialize();
  21. $path = Env::get('data_backup_path', '');
  22. $path = empty($path) ? self::DEFAULT_PATH : (endWith($path, DS) ? $path : $path . DS);
  23. self::$sdk = new Backup([
  24. 'path' => $path
  25. ]);
  26. }
  27. /**
  28. * table列表
  29. * @return mixed
  30. */
  31. public function index()
  32. {
  33. return $this->fetch('index', ['list' => self::$sdk->dataList()]);
  34. }
  35. /**
  36. * 备份文件列表
  37. * @return mixed
  38. */
  39. public function importlist()
  40. {
  41. return $this->fetch('importlist', ['list' => self::$sdk->fileList()]);
  42. }
  43. /**
  44. * 还原数据
  45. * @param int $time
  46. * @param null $part
  47. * @param null $start
  48. */
  49. public function import($time = 0, $part = null, $start = null)
  50. {
  51. if (is_numeric($time) && is_null($part) && is_null($start)) {
  52. $list = self::$sdk->getFile('timeverif', $time);
  53. if (is_array($list)) {
  54. session::set('backup_list', $list);
  55. $this->success('初始化完成!', '', array('part' => 1, 'start' => 0));
  56. } else {
  57. $this->error('备份文件可能已经损坏,请检查!');
  58. }
  59. } else if (is_numeric($part) && is_numeric($start)) {
  60. $list = session::get('backup_list');
  61. $start = self::$sdk->setFile($list)->import($start);
  62. if (false === $start) {
  63. $this->error('还原数据出错!');
  64. } elseif (0 === $start) {
  65. if (isset($list[++$part])) {
  66. $data = array('part' => $part, 'start' => 0);
  67. $this->success("正在还原...#{$part}", '', $data);
  68. } else {
  69. session::delete('backup_list');
  70. $this->success('还原完成!');
  71. }
  72. } else {
  73. $data = array('part' => $part, 'start' => $start[0]);
  74. if ($start[1]) {
  75. $rate = floor(100 * ($start[0] / $start[1]));
  76. $this->success("正在还原...#{$part} ({$rate}%)", '', $data);
  77. } else {
  78. $data['gz'] = 1;
  79. $this->success("正在还原...#{$part}", '', $data);
  80. }
  81. $this->success("正在还原...#{$part}", '');
  82. }
  83. } else {
  84. $this->error('参数错误!');
  85. }
  86. }
  87. /**
  88. * 删除备份文件
  89. */
  90. public function del($time = 0)
  91. {
  92. if (self::$sdk->delFile($time)) {
  93. $this->success("备份文件删除成功!", 'admin/databackup/importlist');
  94. } else {
  95. $this->error("备份文件删除失败,请检查权限!");
  96. }
  97. }
  98. /**
  99. * 备份表 - 命令行
  100. */
  101. public function backup()
  102. {
  103. $tables = $this->request->param('tables');
  104. if ($tables && $this->request->isCli()) {
  105. if ("all" === $tables) {
  106. $tables = [];
  107. foreach (self::$sdk->dataList() as $item) {
  108. $tables[] = $item['name'];
  109. }
  110. } else {
  111. $tables = explode(',', $tables);
  112. }
  113. //lock
  114. $fileinfo = self::$sdk->getFile();
  115. $lock = "{$fileinfo['filepath']}backup.lock";
  116. !is_file($lock) || $this->error('检测到有一个备份任务正在执行,请稍后再试!');
  117. is_writeable($fileinfo['filepath']) || $this->error('备份目录不存在或不可写,请检查后重试!');
  118. file_put_contents($lock, time());
  119. //
  120. $file = $fileinfo['file'];
  121. self::$sdk->Backup_Init() || $this->error('初始化失败,备份文件创建失败!');
  122. foreach ($tables as $tablename) {
  123. $start = self::$sdk->setFile($file)->backup($tablename, 0);
  124. if (false === $start) {
  125. $this->error($tablename . '备份出错!');
  126. } else {
  127. while (is_array($start)) {
  128. $start = self::$sdk->setFile($file)->backup($tablename, $start[0]);
  129. }
  130. }
  131. }
  132. unlink($lock);
  133. $this->success('备份完成!');
  134. }
  135. $this->error('参数错误!');
  136. }
  137. /**
  138. * 备份表
  139. */
  140. public function export()
  141. {
  142. if (Request::instance()->isPost()) {
  143. $input = input('post.');
  144. $fileinfo = self::$sdk->getFile();
  145. $lock = "{$fileinfo['filepath']}backup.lock";
  146. !is_file($lock) || $this->error('检测到有一个备份任务正在执行,请稍后再试!');
  147. is_writeable($fileinfo['filepath']) || $this->error('备份目录不存在或不可写,请检查后重试!');
  148. file_put_contents($lock, time());
  149. //缓存锁文件
  150. session::set('lock', $lock);
  151. //缓存备份文件信息
  152. session::set('backup_file', $fileinfo['file']);
  153. //缓存要备份的表
  154. session::set('backup_tables', $input['tables']);
  155. //创建备份文件
  156. if (false !== self::$sdk->Backup_Init()) {
  157. $first_table_name = $input['tables'][0]??'null';
  158. $this->success('初始化成功!', '', ['tab' => ['id' => 0, 'start' => 0, 'tablename' => $first_table_name]]);
  159. } else {
  160. $this->error('初始化失败,备份文件创建失败!');
  161. }
  162. } else if (Request::instance()->isGet()) {
  163. $tables = session::get('backup_tables');
  164. $file = session::get('backup_file');
  165. $id = input('id');
  166. $start = input('start');
  167. $tablename = $tables[$id];
  168. $start = self::$sdk->setFile($file)->backup($tablename, $start);
  169. if (false === $start) {
  170. $this->error($tablename . '备份出错!');
  171. } else {
  172. while (is_array($start)) {
  173. $start = self::$sdk->setFile($file)->backup($tablename, $start[0]);
  174. }
  175. if (0 === $start) {
  176. if (isset($tables[++$id])) {
  177. $tab = ['id' => $id, 'start' => 0, 'tablename' => $tables[$id]];//下一个递归信息
  178. $this->success($tablename . '备份完成!', '', array('tab' => $tab));
  179. } else {
  180. //备份完成,清空缓存
  181. unlink(session::get('lock'));
  182. Session::delete('backup_tables');
  183. Session::delete('backup_file');
  184. $this->success($tablename . '备份完成!');
  185. }
  186. } else {
  187. $this->error($tablename . '备份出错!');
  188. }
  189. }
  190. } else {
  191. $this->error('参数错误!');
  192. }
  193. }
  194. /**
  195. * 修复表
  196. * @param null $tables
  197. */
  198. public function repair($tables = null)
  199. {
  200. if (self::$sdk->repair($tables)) {
  201. $this->success("数据表修复完成!");
  202. } else {
  203. $this->error("数据表修复出错请重试");
  204. }
  205. }
  206. /**
  207. * 优化表
  208. * @param null $tables
  209. */
  210. public function optimize($tables = null)
  211. {
  212. if (self::$sdk->optimize($tables)) {
  213. $this->success("数据表优化完成!");
  214. } else {
  215. $this->error("数据表优化出错请重试!");
  216. }
  217. }
  218. }