数据库备份

This commit is contained in:
JaguarJack 2020-07-19 16:47:58 +08:00
parent 027ba1acdb
commit 78bb8bccd7
4 changed files with 191 additions and 154 deletions

View File

@ -5,6 +5,7 @@ use catcher\base\CatchRequest as Request;
use catcher\base\CatchController;
use catcher\CatchResponse;
use catcher\exceptions\FailedException;
use catcher\library\BackUpDatabase;
use think\facade\Console;
use think\facade\Db;
use think\Paginator;
@ -87,10 +88,10 @@ class DataDictionary extends CatchController
* @throws FailedException
* @return \think\response\Json
*/
public function backup(): \think\response\Json
public function backup(BackUpDatabase $backUpDatabase): \think\response\Json
{
try {
Console::call('backup:data', [trim(implode(',', \request()->post('data')), ','), '-z']);
$backUpDatabase->done(trim(implode(',', \request()->post('data')), ','));
}catch (\Exception $e) {
throw new FailedException($e->getMessage());
}

View File

@ -4,6 +4,9 @@ declare (strict_types = 1);
namespace catcher\command\Tools;
use catcher\CatchAdmin;
use catcher\facade\FileSystem;
use catcher\library\BackUpDatabase;
use catcher\library\Zip;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
@ -20,7 +23,6 @@ class BackupCommand extends Command
// 指令配置
$this->setName('backup:data')
->addArgument('tables', Argument::REQUIRED, 'backup tables')
->addOption('zip', '-z',Option::VALUE_NONE, 'is need zip')
->setDescription('backup data you need');
}
@ -28,158 +30,8 @@ class BackupCommand extends Command
{
$tables = $this->input->getArgument('tables');
$isZip = $this->input->getOption('zip');
$this->generator(explode(',', $tables), CatchAdmin::backupDirectory());
if ($isZip) {
$this->zip();
}
(new BackUpDatabase)->done($tables);
$output->info('succeed!');
}
/**
*
* @time 2019年09月30日
* @param $tables
* @param $format
* @param $path
* @return void
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
public function generator($tables, $path): void
{
foreach ($tables as $table) {
$this->table = $table;
$this->createDataFile();
}
}
/**
* 创建数据文件
*
* @time 2019年09月27日
* @param $format
* @return void
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
public function createDataFile(): void
{
$file = CatchAdmin::backupDirectory() . $this->table . '.sql';
$handle = fopen($file, 'wb+');
fwrite($handle, $begin = "BEGIN;\r\n", \strlen($begin));
$this->createClass($this->table, $handle);
fwrite($handle, $end = 'COMMIT;', \strlen($end));
fclose($handle);
}
/**
* 创建了临时模型
*
* @time 2019年09月27日
* @param $table
* @param $format
* @param $handle
* @return void
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
protected function createClass($table, $handle)
{
$this->setUnbuffered();
// 防止 IO 多次写入
$buffer = [];
// 记录中记录
$total = Db::table($table)->count();
$limit = 1000;
// 生成器减少内存
while ($total > 0) {
$items = Db::table($table)->limit($limit)->select();
$this->writeIn($handle, $items);
$total -= $limit;
}
}
/**
* sql 文件格式
*
* @time 2019年09月27日
* @param $handle
* @param $data
* @return void
*/
protected function writeIn($handle, $datas)
{
$values = '';
$sql = '';
foreach ($datas as $data) {
foreach ($data as $value) {
$values .= sprintf("'%s'", $value) . ',';
}
$sql .= sprintf('INSERT INTO `%s` VALUE (%s);' . "\r\n", $this->table, rtrim($values, ','));
$values = '';
}
fwrite($handle, $sql, strlen($sql));
}
/**
* 设置未缓存模式
*
* @time 2019年09月29日
* @return void
*/
protected function setUnbuffered()
{
$connections = \config('database.connections');
$connections['mysql']['params'] = [
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false
];
\config([
'connections' => $connections,
],'database.connections');
}
protected function zip()
{
if (extension_loaded('zip')) {
$files = glob(CatchAdmin::backupDirectory() . '*.sql');
$zip = new \ZipArchive();
$backupPath = runtime_path('database/');
CatchAdmin::makeDirectory($backupPath);
$zip->open($backupPath . 'backup.zip', \ZipArchive::CREATE);
$zip->addEmptyDir('backup');
foreach ($files as $file) {
$zip->addFile($file, 'backup/'. basename($file));
}
$zip->close();
foreach ($files as $file) {
unlink($file);
}
rmdir(CatchAdmin::backupDirectory());
}
}
}

View File

@ -0,0 +1,174 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------
namespace catcher\library;
use catcher\CatchAdmin;
use catcher\facade\FileSystem;
use think\facade\Db;
class BackUpDatabase
{
/**
*
* @time 2020年07月19日
* @param $tables
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @return void
*/
public function done($tables)
{
$this->generator(explode(',', $tables));
$this->zip();
}
/**
*
* @time 2019年09月30日
* @param $tables
* @return void
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
protected function generator($tables): void
{
foreach ($tables as $table) {
$this->table = $table;
$this->createDataFile();
}
}
/**
* 创建数据文件
*
* @time 2019年09月27日
* @return void
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
public function createDataFile(): void
{
$file = CatchAdmin::backupDirectory() . $this->table . '.sql';
$handle = fopen($file, 'wb+');
fwrite($handle, $begin = "BEGIN;\r\n", \strlen($begin));
$this->createClass($this->table, $handle);
fwrite($handle, $end = 'COMMIT;', \strlen($end));
fclose($handle);
}
/**
* 创建了临时模型
*
* @time 2019年09月27日
* @param $table
* @param $handle
* @return void
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DataNotFoundException
*/
protected function createClass($table, $handle)
{
$this->setUnbuffered();
// 防止 IO 多次写入
$buffer = [];
// 记录中记录
$total = Db::table($table)->count();
$limit = 1000;
// 生成器减少内存
while ($total > 0) {
$items = Db::table($table)->limit($limit)->select();
$this->writeIn($handle, $items);
$total -= $limit;
}
}
/**
* sql 文件格式
*
* @time 2019年09月27日
* @param $handle
* @param $datas
* @return void
*/
protected function writeIn($handle, $datas)
{
$values = '';
$sql = '';
foreach ($datas as $data) {
foreach ($data as $value) {
$values .= sprintf("'%s'", $value) . ',';
}
$sql .= sprintf('INSERT INTO `%s` VALUE (%s);' . "\r\n", $this->table, rtrim($values, ','));
$values = '';
}
fwrite($handle, $sql, strlen($sql));
}
/**
* 设置未缓存模式
*
* @time 2019年09月29日
* @return void
*/
protected function setUnbuffered()
{
$connections = \config('database.connections');
$connections['mysql']['params'] = [
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false
];
\config([
'connections' => $connections,
],'database.connections');
}
/**
* 文件压缩
*
* @time 2020年07月19日
* @throws \Exception
* @return void
*/
protected function zip()
{
$files = FileSystem::allFiles(CatchAdmin::backupDirectory());
$storePath = runtime_path('database/');
if (!FileSystem::isDirectory($storePath)) {
FileSystem::makeDirectory($storePath);
}
(new Zip)->make($storePath . 'backup.zip')->addFiles($files)->close();
FileSystem::deleteDirectory(CatchAdmin::backupDirectory());
}
}

View File

@ -0,0 +1,10 @@
<?php
// +----------------------------------------------------------------------
// | CatchAdmin [Just Like ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
// +----------------------------------------------------------------------
// | Author: JaguarJack [ njphper@gmail.com ]
// +----------------------------------------------------------------------