This text is a work in progress—highly subject to change—and may not accurately describe any released version of the Apache™ Subversion® software. Bookmarking or otherwise referring others to this page is probably not such a smart idea. Please visit http://www.svnbook.com/ for stable versions of this book.

维护 Berkeley DB 仓库

从理论上讲, 基于 BDB 的仓库的维护步骤和基于 FSFS 的仓库是一样的, 但是从历史上看, 基于 BDB 的仓库需要一点额外的关怀才能保持运转. 本节 将介绍管理 Berkeley DB 的独特之处.

Berkeley DB 恢复

“错误容忍与恢复”一节 提到过, 如果未被恰当地关闭, 基于 Berkeley DB 的仓库可能会处于无法 访问的状态. 如果发生了这种情况, 管理员需要把数据库回滚到一个一致的 状态. 这是基于 BDB 的仓库所特有的问题—如果仓库的后端存储是 FSFS, 则根本不会出现这种问题. 从 1.4 (Berkeley DB 版本是 4.4) 开始, Subversion 对异常情况的适应能力越来越强, 但还是有可能出现仓库 被卡住的情况, 这时候管理员必须知道如何安全地处理这种状况.

为了保护仓库里的数据, Berkeley DB 使用了锁机制. 锁机制保证了数据库 的各个部分不会被多个访问者同时修改, 并且每个进程从数据库中读取时都能 看到处于正确状态的数据. 当一个进程需要修改数据库里的某个数据时, 它首先 查看目标数据上是否存在锁, 如果目标数据未被锁定, 进程将会锁定数据, 然后 修改数据, 最后放锁. 其他进程将一直等待, 直到持锁的进程放锁后, 它们才能 继续访问目标数据. (这和仓库内的版本化文件上的锁一点关系也没有, 我们已 在 的多种涵义 专门向读者解释过.)

在使用 Subversion 仓库的过程中, 致命的错误或中断会使得进程没 有机会去移除数据库上的锁, 由此造成的结果是后端数据库系统被 卡住 了. 这种情况一旦发生, 任何试图访问仓库的进程 都会被无限期地挂起 (因为每个进程都在等待解锁, 但原本要去解锁的进程 已经不存在了).

如果你的仓库的后端数据库被卡住了, 不要惊慌. Berkeley DB 文件 系统利用数据库事务, 检查点和预写日志来保证只有最具灾难性的事件 才会造成数据库环境被永久地损坏[85]. 一个谨慎的仓库管理员会 经常对仓库进行备份, 但现在还不用去存储柜那儿取备份, 而是先按照下面 的步骤来尝试恢复仓库:

  1. 先确保没有进程正在访问 (或试图访问) 仓库, 对于连接到网络上 的仓库, 这还意味着要关闭 Apache HTTP 服务器或 svnserve 守护进程.

  2. 切换到拥有仓库的用户账号. 这一步很重要, 如果账号不正确, 在 恢复仓库时可能会改变仓库内文件的权限, 使得即使仓库恢复后也无法 被其他人访问.

  3. 执行命令 svnadmin recover:

    $ svnadmin recover /var/svn/repos
    Repository lock acquired.
    Please wait; recovering the repository may take some time...
    
    Recovery completed.
    The latest repos revision is 19.
    $
    

    命令可能会花好几分钟才会结束.

  4. 重启服务器进程.

上面的步骤能够解决导致仓库卡住的大部分问题. 要确保在执行命令时 的身份是拥有仓库的用户, 而不是简单地切换到 root 用户. 在恢复过程中可能会从头开始创建各种数据库文件 (例如共享内存区). 如果以 root 身份执行命令, 将导致新建的文件只属于 root, 这就意味着即使仓库重新上线, 普通用户也没 办法访问.

清除不再有用的 Berkeley DB 日志文件

在 Berkeley DB 4.2 发布之前, 对于基于 BDB 的 Subversion 仓库 而言, 消耗磁盘最多的罪魁祸首就是 Berkeley DB 的日志文件, 这些日志 文件是 Berkeley DB 在修改真正地数据库文件之前所写的预写日志. 预写 日志记录了数据库从一个状态到另一个状态过程中所产生的所有活动, 而 数据库文件在任意一个时刻都代表了一个特定的状态, 日志文件包含了 状态 之间 的所有修改, 因此日志会增长地非常 迅速, 消耗的磁盘存储空间也很可观.

幸运的是, 从 Berkeley DB 4.2 开始, 数据库环境开始支持自动删除 不再有用的日志文件. 如果 svnadmin 的 Berkeley DB 版本大于或等于 4.2, 那么由它创建的仓库都会把自动删除日志作为默认 配置. 如果管理员不希望日志文件被自动删除, 只需要为 svnadmin create 加上选项 --bdb-log-keep. 如果 管理员忘记加上选项, 或者是后面又改变了心意, 只需要打开仓库子目录 db 里的 DB_CONFIG 文件, 注释掉含有 set_flags DB_LOG_AUTOREMOVE 的那一行, 然后对仓库执行 svnadmin recover, 使得修改后的配置 生效.

如果不支持日志文件的自动删除, 随着人们不断地使用仓库, 日志文件 会不断累积. 保留日志文件也可以算作数据库系统的一项特性—管理员 应该能够在只有日志文件的情况下恢复整个数据库, 所以日志文件对于数据库 的灾备恢复非常有用. 但是在典型情况下, 管理员希望归档不再被 Berkeley DB 使用的日志文件, 然后从磁盘上删除它们, 以便节省磁盘空间. 命令 svnadmin list-unused-dblogs 可以列出不再使用的 日志文件:

$ svnadmin list-unused-dblogs /var/svn/repos
/var/svn/repos/log.0000000031
/var/svn/repos/log.0000000032
/var/svn/repos/log.0000000033
…
$ rm `svnadmin list-unused-dblogs /var/svn/repos`
## disk space reclaimed!
[警告] 警告

如果基于 BDB 的仓库把日志文件用作备份或灾备恢复计划的一部分, 那么我们就 不能 允许自动删除日志文件. 根据 日志文件来恢复仓库要求 所有的 的日志都必须 留着. 如果在备份系统复制日志文件之前, 日志文件被自动删除了, 那么 不完整的日志文件集合对恢复仓库而言起不到半点作用.

Berkeley DB 实用工具

如果仓库的后端数据库是 Berkeley DB, 那么版本化文件系统的 所有结构和数据都存放在一系列数据库表中, 而这些数据库表位于仓库 的 db/ 子目录内. db/ 是一 个普通的 Berkeley DB 环境目录, 因此可以用 Berkeley DB 数据库工具 访问目录, 数据库工具通常由 Berkeley DB 发行版提供.

在日常工作中使用 Subversion 时, 这些数据库工具都不会被用到, Subversion 仓库所需的大部分维护工作都可以由 svnadmin 完成, 例如 Berkeley DB 实用工具 db_archive 的部分功能可以由 svnadmin list-unused-dblogssvnadmin list-dblogs 完成, 而 svnadmin recover 则反映了 Berkeley DB 实用工具 db_recover 的常见 用例.

然而, 还是存在几个 Berkeley DB 实用工具可能对你有用. db_dumpdb_load 分别用于 读写具有定制化格式的文件, 该文件描述了 Berkeley DB 数据库的键值对. 由于 Berkeley DB 数据库在不同的体系结构之间是不可移植的, 利用这种 格式的文件管理员就可以实现在不同的主机之间传输数据库, 而不是考虑体系 结构或操作系统的差异. 虽然我们也能用 svnadmin dumpsvnadmin load 完成类似的工作, 但 db_dumpdb_load 做得也 很好, 而且快得多. 有时候, 经验丰富的 Berkeley DB 用户还能利用这两个 命令在位地对仓库里的数据进行调整, 而这是 Subversion 工具做不到的. 另外, db_stat 还能输出关于 Berkeley DB 环境的 状态信息, 包括详细的, 关于锁和存储子系统的统计信息.

关于 Berkeley DB 工具链的更多信息, 见 Oracle 维护的 Berkeley DB 文档 https://docs.oracle.com/cd/E17275_01/html/api_reference/C/utilities.html.



[85] 例如用一个巨大的 电磁铁去接近硬盘.