【问题标题】:Backing Up Views with Mysql Dump使用 Mysql Dump 备份视图
【发布时间】:2009-11-01 20:15:43
【问题描述】:

我只想用 mysqldump 备份视图。

这可能吗?

如果有,怎么做?

【问题讨论】:

  • 哇,谁知道在标准的mysqldump 命令中捕获看起来像表格的简单任务需要这么长的解释。我想知道有多少人花了很多时间进行调试,因为他们的转储中没有包含某个开发人员决定创建的一个视图,该视图没有在myunknowinglyincompletedatabasedump.sql 文件中捕获。我的解决方案。在 IntelliJ 中,右键单击视图 Generate DDL to Clipboard。粘贴。虽然不完全自动化。

标签: mysql mysqldump


【解决方案1】:

注意:来自Ken 的这个答案从建议的编辑移到了自己的答案。

这是使用上述变体的完整命令行示例

 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 友好。如果您有很多视图,此命令行可能会变得太长,在这种情况下,您需要在选择中添加某种额外的过滤器(例如,查找以给定字符开头的所有视图)。

【讨论】:

  • 有没有办法使用 docker 来执行这个查询?使用此命令的示例? docker exec -i $(docker-compose ps -q mysqldb) mysql ...
  • @dez,您可以使用 docker exec -it <container> bash 进入 Bash 提示符,其中 <container> 是容器 ID 或名称,如 docker ps 所示。在 Bash 提示符下,您可以运行答案中的命令。如果主机需要访问生成的 views.sql 文件,请确保它存储在您已绑定安装在容器中的某个位置。
【解决方案2】:

只需使用 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'

【讨论】:

  • 谢谢,这很有帮助。我的观点分布在多个数据库模式中,这得到了所有观点。
  • 也许容易剪切和粘贴,但不容易想出答案。我建议从上面的答案中删除“很容易”和“只是”。此外,考虑到所有答案及其长度,以完成概念上简单的任务,即向大多数新手倾倒看起来像一张桌子的东西,这表明这种“简单”是行不通的。 “令人沮丧”将是一个更好的表征。
  • 这个简化了对基本要素的备份 - 只是 CREATE VIEW 查询,没有所有 MySQL 特定的 /*!...*/ cmets 和其他设置。 (mysqldump--compact 选项似乎不适用于 VIEW。)正是我需要的!
【解决方案3】:

我修改了Andomar's excellent answer 以允许只指定一次数据库(和其他设置):

#!/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

【讨论】:

    【解决方案4】:

    通过备份,我假设您的意思只是没有数据的定义。

    现在 mysqldump 似乎不区分 VIEWs 和 TABLEs,所以也许最好的办法是在 mysqldump 的命令行上明确指定 VIEWs 或者在 mysqldump 之前动态找出这个列表,然后传递它像以前一样下降。

    您可以使用此查询获取特定数据库中的所有视图:

    SHOW FULL TABLES WHERE table_type='view';

    【讨论】:

      【解决方案5】:

      就回答这个问题而言,olliiiveranswer 是最好的直接回答这个问题。对于我的回答,我将尝试将其构建为一个全面的完整备份和恢复解决方案。

      在这个问题的其他答案和一些其他资源的帮助下,我想出了这个脚本,可以根据需要使用来自生产服务器的实时副本轻松替换我的开发服务器上的数据库。它一次在一个数据库上工作,而不是在所有数据库上工作。虽然我确实有一个单独的脚本,但在这里分享并不安全,因为它基本上会删除并重新创建除了少数几个数据库之外的所有内容,并且您的环境可能会有所不同。

      脚本假定两台机器上的 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
      

      到目前为止,它似乎可以工作,尽管您可能需要根据自己的目的对其进行调整。确保无论您的凭据文件在哪里,都设置了安全访问权限,以便未经授权的用户无法读取它!

      由于正确导出视图似乎很困难,我调整了 olliiiveranswer 以使其首先删除所有表或视图,这些表或视图与我们要导入的数据库中的有效视图的确切名称相同如果它们存在,则导入所有表,这可能会错误地将这些视图创建为表,然后删除这些表并正确定义这些视图。

      基本上是这样的:

      • 验证您在命令行中指定的数据库是否存在
      • 使用 MYSQLDUMP 创建转储文件
      • SCP 转储文件从生产到指定的测试服务器
      • 通过 SSH 在指定的测试服务器上发出导入命令并返回输出
      • 完成后从两台服务器中删除转储文件
      • 为沿途的大多数步骤发出一些合理的输出

      【讨论】:

        【解决方案6】:

        我会像 OP 所要求的那样尽可能接近 mysqldump 的输出,因为它包含大量关于视图的信息,这些信息无法通过来自 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
        

        【讨论】:

          【解决方案7】:

          谢谢你 - 非常有用。

          一个小问题——也许是因为我有一组稍微复杂的视图,这些视图引用了其他视图等:

          我发现“定义者”用户需要存在并且对目标架构具有正确的权限,否则mysql不会生成引用其他视图的视图,因为它的东西定义不足。

          在生成中:

          /*!50013 DEFINER=&lt;user&gt;@&lt;host&gt; SQL 安全定义器 */

          --> 确保&lt;user&gt;@&lt;host&gt; 在您的目标实例上正常,或者将该字符串替换为可以的用户。

          谢谢 索尔斯坦

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-11-05
            • 1970-01-01
            • 2015-12-14
            • 2023-03-05
            • 2020-03-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多