我只想用 mysqldump 备份视图。
这可能吗?
如果是这样,怎么做?
注意:肯的这个答案从建议的编辑移到了自己的答案。
这是使用上述变体的完整命令行示例
mysql -u username INFORMATION_SCHEMA
--skip-column-names --batch
-e "select table_name from tables where table_type = 'VIEW'
and table_schema = 'database'"
| xargs mysqldump -u username database
> views.sql
这通过对 INFORMATION_SCHEMA 数据库的查询提取所有视图名称,然后将它们通过管道传输到 xargs 以制定 mysqldump 命令。需要 --skip-column-names 和 --batch 以使输出 xargs 友好。如果您有很多视图,此命令行可能会变得太长,在这种情况下,您需要在选择中添加某种额外的过滤器(例如,查找以给定字符开头的所有视图)。
只需使用 information_schema 即可备份多个数据库的视图:
mysql --skip-column-names --batch -e 'select CONCAT("DROP TABLE IF EXISTS ", TABLE_SCHEMA, ".", TABLE_NAME, "; CREATE OR REPLACE VIEW ", TABLE_SCHEMA, ".", TABLE_NAME, " AS ", VIEW_DEFINITION, "; ") table_name from information_schema.views'
我修改了 Andomar 的优秀答案,只允许指定一次数据库(和其他设置):
#!/bin/bash -e
mysql --skip-column-names --batch -e \
"select table_name from information_schema.views \
where table_schema = database()" $* |
xargs --max-args 1 mysqldump $*
我将其另存为mysql-dump-views.sh
并通过以下方式调用它:
$ mysql-dump-views.sh -u user -ppassword databasename >dumpfile.sql
通过备份,我假设您的意思只是没有数据的定义。
似乎现在 mysqldump 不区分 VIEWs 和 TABLEs,所以也许最好的办法是在 mysqldump 的命令行上显式指定 VIEW,或者在 mysqldump 之前动态找出这个列表,然后像以前一样传递它.
您可以使用以下查询获取特定数据库中的所有视图:
SHOW FULL TABLES WHERE table_type='view';
就回答这个问题而言,olliiiver的回答是直接做这个的最好的。对于我的回答,我将尝试将其构建为一个全面的完整备份和恢复解决方案。
在这个问题的其他答案和一些其他资源的帮助下,我想出了这个脚本,可以根据需要使用来自生产服务器的实时副本轻松替换我的开发服务器上的数据库。它一次在一个数据库上工作,而不是在所有数据库上工作。虽然我确实有一个单独的脚本,但在这里共享并不安全,因为它基本上会删除并重新创建除了少数几个数据库之外的所有内容,并且您的环境可能会有所不同。
该脚本假定两台机器上的 root 系统和 MySQL 用户(尽管可以更改),在服务器之间工作无密码 SSH,并依赖于每台机器上的 MySQL 密码文件 /root/mysqlroot.cnf,如下所示:
[client]
password=YourPasswordHere
文件:synctestdb.sh,可以选择符号链接到 /usr/sbin/synctestdb 以方便使用
Usage: synctestdb DBNAME DESTSERVER
从生产服务器运行它。
这里是:
#!/bin/bash
if [ "${1}" != "" ] && [ "${1}" != "--help" ] && [ "${2}" != "" ] ; then
DBNAME=${1}
DESTSERVER=${2}
BKDATE=$( date "+%Y-%m-%d" );
SRCHOSTNAME=$( /bin/hostname )
EXPORTPATH=/tmp
EXPORTFILE=/tmp/${SRCHOSTNAME}_sql_${BKDATE}_devsync.sql
CREDSFILE=/root/mysqlroot.cnf
SSHUSER=root
DBEXISTS=$( echo "SHOW DATABASES LIKE '${DBNAME}'" \
| mysql --defaults-extra-file=${CREDSFILE} -NB INFORMATION_SCHEMA )
if [ "${DBEXISTS}" == "${DBNAME}" ] ; then
echo Preparing --ignore-tables parameters for all relevant views
echo
#build --ignore-table parameters list from list of all views in
#relevant database - as mysqldump likes to recreate views as tables
#we pair this with an export of the view definitions later below
SKIPVIEWS=$(mysql --defaults-extra-file=${CREDSFILE} \
-NB \
-e "SELECT \
CONCAT( '--ignore-table=', TABLE_SCHEMA, '.', TABLE_NAME ) AS q \
FROM INFORMATION_SCHEMA.VIEWS \
WHERE TABLE_SCHEMA = '${DBNAME}';" )
if [ "$?" == "0" ] ; then
echo Exporting database ${DBNAME}
echo
mysqldump --defaults-extra-file=${CREDSFILE} ${SKIPVIEWS} \
--add-locks --extended-insert --flush-privileges --no-autocommit \
--routines --triggers --single-transaction --master-data=2 \
--flush-logs --events --quick --databases ${DBNAME} > ${EXPORTFILE} \
|| echo -e "\n\nERROR: ${SRCHOSTNAME} failed to mysqldump ${DBNAME}"
echo Exporting view definitions
echo
mysql --defaults-extra-file=${CREDSFILE} \
--skip-column-names --batch \
-e "SELECT \
CONCAT( \
'DROP TABLE IF EXISTS ', TABLE_SCHEMA, '.', TABLE_NAME, \
'; CREATE OR REPLACE VIEW ', TABLE_SCHEMA, '.', TABLE_NAME, ' AS ', \
VIEW_DEFINITION, '; ') AS TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS \
WHERE TABLE_SCHEMA = '${DBNAME}';" >> ${EXPORTFILE} \
|| echo -e "\n\nERROR: ${SRCHOSTNAME} failed to mysqldump view definitions"
echo Export complete, preparing to transfer export file and import
echo
STATUSMSG="SUCCESS: database ${DBNAME} synced from ${SRCHOSTNAME} to ${DESTSERVER}"
scp \
${EXPORTFILE} \
${SSHUSER}@${DESTSERVER}:${EXPORTPATH}/ \
|| STATUSMSG="ERROR: Failed to SCP file to remote server ${DESTSERVER}"
ssh ${SSHUSER}@${DESTSERVER} \
"mysql --defaults-extra-file=${CREDSFILE} < ${EXPORTFILE}" \
|| STATUSMSG="ERROR: Failed to update remote server ${DESTSERVER}"
ssh ${SSHUSER}@${DESTSERVER} \
"rm ${EXPORTFILE}" \
|| STATUSMSG="ERROR: Failed to remove import file from remote server ${DESTSERVER}"
rm ${EXPORTFILE}
echo ${STATUSMSG}
else
echo "ERROR: could not obtain list of views from INFORMATION_SCHEMA"
fi
else
echo "ERROR: specified database not found, or SQL credentials file not found"
fi
else
echo -e "Usage: synctestdb DBNAME DESTSERVER \nPlease only run this script from the live production server\n"
fi
到目前为止,它似乎可以工作,尽管您可能需要根据自己的目的对其进行调整。确保无论您的凭据文件在哪里,都设置了安全访问权限,以便未经授权的用户无法读取它!
由于正确导出视图似乎很困难,我调整了 olliiiver的答案,以便首先我们删除所有表或视图,如果它们存在的话,我们正在导入的数据库中具有有效视图的确切名称,然后导入所有表,这可能会错误地将这些视图创建为表,然后删除这些表并正确定义这些视图。
基本上这是它的工作原理:
我会尽可能地坚持mysqldump的输出,就像 OP 询问的那样,因为它包含大量关于视图的信息,这些信息无法通过来自 INFORMATION_SCHEMA 的简单查询来重建。
这就是我从源数据库创建部署视图脚本的方式:
SOURCEDB="my_source_db"
mysql $SOURCEDB --skip-column-names -B -e \
"show full tables where table_type = 'view'" \
| awk '{print $1}' \
| xargs -I {} mysqldump $SOURCEDB {} > views.sql
谢谢你 - 非常有用。
不过有一个小问题——也许是因为我有一组稍微复杂的观点,这些观点引用了其他观点等:
我发现“定义者”用户需要存在并且对目标模式具有正确的权限,否则mysql不会生成引用其他视图的视图,因为它的定义不足。
在生成的:
/*!50013 DEFINER= @SQL<user>
安全<host>
定义器 */
--> 确保<user>
@<host>
在您的目标实例上是可以的,或者用这样做的用户替换这个字符串。
谢谢索尔斯坦