2014/09/11 09:39:01 分类: 技术随笔 1人评论 次浏览
SAE 只允许用户通过phpMyAdmin管理远程数据库, 在做本地SAE环境开发的时候是是分不方便的.
因此写了点代码能够方便的将远程数据库同步到本地来.
一、SAE 无程数据库备份
可以通过SAE 提供的Cron, Storage, DeferredJob 来实现数据库备份. 其中有用到我的PhpLog 日志插件. 代码如下:
/cron/dbBackup.php
require('..' . DIRECTORY_SEPARATOR . 'ext' . DIRECTORY_SEPARATOR . 'PhpLog' . DIRECTORY_SEPARATOR . 'PhpLog.php');
$filename = SAE_MYSQL_DB . '-' . date('Ymd-his') . '-' . substr(time(), -4, 4) . '.sql';
$dj = new SaeDeferredJob();
$taskID = $dj->addTask("export", "mysql", "wordpress", "dbBackup/$filename", SAE_MYSQL_DB, "", "");
if ($taskID === false) {
PhpLog::log('数据库备份失败 errno:' . $dj->errno() . ' errmsg:' . $dj->errmsg(),'error','dbBackup');
} else {
PhpLog::log('数据库备份成功 id:' . $taskID, 'info', 'dbBackup');
}
然后需要在将此代码加入Cron 每月1号定时备份. 在config.yaml 加入以下代码:
config.yaml
name: dbBackup version: 2 cron: - description: db backup url: /cron/dbBackup.php schedule: "0 0 1 * *"
此时 dbBackup.php 是没有加入访问控制的. 所有人都可以通过web访问. 于是我们可以在dbBackup.php加入不允许通过web访问.
if(!isset($_SERVER['argv'])) {// || strncasecmp(php_sapi_name(),'cli',3))
PhpLog::log('外部非法运行, 来自IP: ' . $_SERVER["REMOTE_ADDR"] . ' 运行环境: ' . $env, 'warning', 'dbBackup');
echo "";
die();
}
到此处, 数据库备份代码已完成.
一、还原到本地数据库.
原理很简单, 就是通过Storage API 获取到最新的备份文件, 然后更新到本地数据库.
首先需要一个页面输出最新备份SQL文件.
/cron/dbRestore.php
$storage = new SaeStorage();
$list = $storage->getListByPath('wordpress', 'dbBackup');
if (count($list['files']) === 0) {
echo '无文件';
die;
}
header("Content-type: text/html; charset=utf-8");
echo $storage->read('wordpress', $list['files'][0]['fullName']);
其次需要一个本地的php脚本导入SQL文件到数据库.
/cron/dbRestore.local.php
define("DB_HOST", 'localhost');
define("DB_USER", 'root');
define("DB_PASSWORD", 'root');
define("DB_NAME", 'app_madcoder');
define("DOWNLOAD_LINK", '//www.madcoder.cn/cron/dbRestore.php'); // 查看最新备份文件的页面.
define("RESTORE_SQL", 'restore.sql'); // 导入成功后所要执行的SQL. 文件不存在刚不执行.
echo iconv('UTF-8','GBK','最新备份文件下载中...').PHP_EOL;
$sql = file_get_contents(DOWNLOAD_LINK);
echo iconv('UTF-8','GBK','文件下载成功, 正在写入文件').PHP_EOL;
$filename = md5(time()) . '.sql';
if ($fp = fopen($filename, "w")) {
@fwrite($fp, $sql);
if (@fwrite($fp, $sql)) {
echo iconv('UTF-8','GBK','写入文件成功, 准备导入MYSQL').PHP_EOL;
fclose($fp);
} else {
echo iconv('UTF-8','GBK','写文件失败.').PHP_EOL;
fclose($fp);
die;
}
}
echo iconv('UTF-8','GBK','正在还原数据库,请稍等....').PHP_EOL;
$rst = exec('mysql -h ' . DB_HOST . ' -u ' . DB_USER . ' -p' . DB_PASSWORD .' --default-character-set=utf8 ' . DB_NAME. ' < ' . $filename);
unlink($filename); // SQL 导入后删除临时文件.
if (file_exists(RESTORE_SQL)) {
echo iconv('UTF-8','GBK','正在执行还原SQL.').PHP_EOL;
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$sql = str_replace(PHP_EOL, '', file_get_contents(RESTORE_SQL));
$rst = $mysqli->multi_query($sql);
$errors = $mysqli->error;
if ($errors) {
echo iconv('UTF-8','GBK','还原SQL执行失败, 错误: ' . $errors).PHP_EOL;
} else {
echo iconv('UTF-8','GBK','还原SQL执行成功.').PHP_EOL;
}
$mysqli->close();
}
echo iconv('UTF-8','GBK','程序结束.').PHP_EOL;
同时, 支持在导入完成后执行指定SQL文件. 因为我在远程库里site url 是 www.madcoder.cn, dump到本地是, 我需要它变成 1.madcoder.sae.com 之类的. 加入 restore.sql:
update wp_posts set guid = replace(guid, 'www.madcoder.cn', '1.madcoder.sae.com')
where guid like '%www.madcoder.cn%';
update wp_options set option_value = replace(option_value, 'www.madcoder.cn', '1.madcoder.sae.com')
where option_value like '%www.madcoder.cn%';
这样一键dump下来远程数据库之后本地就可以直接进行开发调试了.
当然, 这里的dbRestore.php是必须加入访问控制的, 不然所以人都能轻松dump下你的整个数据库那就麻烦了.
我们可以限定IP访问, 加上访问key, 等等方式来控制访问. 当然, 安全性很低, 大家自己取舍. 代码就不贴了, 不然人人能dump我的库了.
然后运行dbRestore.local.php 将本地数据库还原到最近远程备份.
运行结果如下图:
本博客所有文章如无特别注明均为原创。作者:Gcaufy
复制或转载请以超链接形式注明转自码疯窝,原文地址 SAE 平台代码实现数据库定时备份以及同步到本地