15.5. BDB (BerkeleyDB)存储引擎

Sleepycat Software给MySQL提供Berkeley DB事务性存储引擎。这个存储引擎典型被简称为BDB。对BDB存储引擎的支持包括在MySQL 源码分发版 里,在MySQL-Max二进制 分发版 里被激活。

BDB表可能有一个更大的崩溃幸存机会,并且也具有对事务COMMIT和ROLLBACK操作的能力。MySQL源码 分发版 和被补丁过可以与MySQL一起工作的BDB 分发版 一起提供。你不能使用一个未补丁过的BDB版本与MySQL一起工作。。

我们在MySQL AB上与Sleepycat紧密合作工作以保持MySQL/BDB接口的质量在高水平。(即使Berkeley DB其本身是非常能经受考验和非常可靠的。MySQL接口仍然被认为是第三等质量的。我们将继续改善和优化它)。

当它达到对所有涉及BDB表的问题的支持之时,我们答应负责帮助我们的用户定位问题并创建可重复产生的测试案例。任何这样的测试案例被转交给Sleepycat,它反过来帮助我们找到并解决问题。因为这是一个二阶段的操作,任何关于BDB表的问题我们可能要花比对其它存储引擎稍微更长一点的时间来解决它。可是,我们期望这个过程没有显著的困难,因为Berkeley DB 代码本身被用在MySQL之外许多的应用中。

要获得关于Berkeley DB的一般信息,请访问Sleepycat网站,http://www.sleepycat.com/

15.5.1 BDB支持的操作系统

当前,我们知道BDB存储引擎支持下列操作系统:

·         Linux 2.x Intel

·         Sun Solaris (SPARC and x86)

·         FreeBSD 4.x/5.x (x86, sparc64)

·         IBM AIX 4.3.x

·         SCO OpenServer

·         SCO UnixWare 7.1.x

·         Windows NT/2000/XP

BDB不支持下列操作系统:

·         Linux 2.x Alpha

·         Linux 2.x AMD64

·         Linux 2.x IA-64

·         Linux 2.x s390

·         Mac OS X

注释:前一个列表还不完全,我们收到更多信息时我们会更新它。

如果你从支持BDB表的源码建立的MySQL,但是,当你启动mysqld之时,发生下列错误,这意味着对你的架构BDB不被支持:

bdb: architecture lacks fast mutexes: applications cannot be threaded
   
     
      
Can't init databases
   
     
      

在这种情况下,你必须重建MySQL不带BDB表支持或用--skip-bdb选项启动服务器。

15.5.2 . 安装BDB

如果你已经下载一个包括对Berkeley DB支持的的二进制版的MySQL, 只要简单地按照通常的二进制 分发版 安装指令。(MySQL-Max 分发版包括BDB支持)。

如果你从源码建立MySQL,你可以在其它任何常用选项之外用--with-berkeley-db选项运行configure来允许支持BDB。下载一个MySQL 5.1分发版,改变位置到它的最顶层目录,然后运行下面命令:

shell> ./configure --with-berkeley-db [other-options]
   
     
      

更多信息,请参阅2.7节,“在其它类似Unix系统上安装MySQL”, 5.1.2节,“mysqld-max扩展MySQL服务器”, 和2.8节,“使用源码分发版版安装MySQL”

15.5.3 BDB启动选项

下列对mysqld的选项可被用来改变BDB存储引擎的行为:

·         --bdb-home=path

BDB表的基础目录。这应该和你为--datadir使用的目录相同。

·         --bdb-lock-detect=method

BDB 锁定检测方式。选项值应该为DEFAULT, OLDEST, RANDOM或YOUNGEST。

·         --bdb-logdir=path

BDB日志文件目录。

·         --bdb-no-recover

不在恢复模式启动Berkeley DB。

·         --bdb-no-sync

不同步刷新BDB日志。这个选项不被赞成,取而代之地使用--skip-sync-bdb-logs(请参阅对--sync-bdb-logs的描述)。

·         --bdb-shared-data

以多处理模式启动Berkeley DB。(初始化Berkeley DB之时,不要使用DB_PRIVATE)。

·         --bdb-tmpdir=path

BDB临时文件目录。

·         --skip-bdb

禁止BDB存储引擎。

·         --sync-bdb-logs

同步刷新BDB日志。这个选项默认被允许,请使用--skip-sync-bdb-logs来禁止它。

请参阅5.3.1节,“mysqld命令行选项”

如果你使用--skip-bdb选项,MySQL不初始化Berkeley DB库,而且这样节省大量的内存。尽管如此,如果你使用这个选项,你不能使用BDB表。如果你试着创建一个BDB表,MySQL取而代之地创建一个MyISAM。

通常,如果你象使用BDB表,你应该不用--bdb-no-recover选项启动mysqld。可是,如果BDB日志被破坏则当你试着启动mysqld时,上述办法启动服务器可能导致问题。请参阅2.9.2.3节,“MySQL服务器的启动和故障诊断排除”

使用bdb_max_lock 变量,你可以指定在BDB表上被激活的锁定的最大数目。默认值是10,000。当你执行长事务或当mysqld不得不检查许多行来执行一个查询之时,如果发生如下错误,你应该增加这个数目:

bdb: Lock table is out of available locks
   
     
      
Got error 12 from ...
   
     
      

如果你正使用大型多语句事务,你可能也想改变binlog_cache_size和max_binlog_cache_size变量。请参阅5.11.3节,“二进制日志”

也请参阅5.3.3节,“服务器系统变量”

15.5.4 BDB表的特征

每个BDB表用两个文件被存在磁盘上。文件的名字用表的名字做开头,并且有一个扩展名来指明文件类型。一个.frm文件存储表定义,一个.db文件包含表数据和索引。

要明确指出你想要一个BDB表,用ENGINE或TYPE表选项来指明:

CREATE TABLE t (i INT) ENGINE = BDB;
   
     
      
CREATE TABLE t (i INT) TYPE = BDB;
   
     
      

BerkeleyDB是用ENGINE或者TYPE选项的BDB存储引擎的“同义词”。

BDB存储引擎提供事务性表,你使用这些表的方法取决于autocommit模式:

·         如果你正运行着,同时随着autocommit的被允许(这是默认的),对BDB表的改变被立即提交并且不能被 回滚。

·         如果你正运行着,同时随着autocommit的被禁止,改变不变成永久的直到你执行一个COMMIT语句。作为提交的替代,你可以执行ROLLBACK来忘记改变。

你可以用BEGIN WORK语句开始一个事务来挂起autocommit,或者用SET AUTOCOMMIT=0来明确禁止autocommit。

请参阅13.4.1节,“START TRANSACTION, COMMIT和ROLLBACK语法”

BDB存储引擎有下列特征:

·         BDB表可以有多达每表31个索引,每个索引16列,并且1024字节的最大 键尺寸。

·         MySQL在每个BDB表中需要一个PRIMARY KEY以便每一行可以被唯一地识别。如果你不明确创建一个,MySQL为你创建并维持一个隐藏的PRIMARY KEY。隐藏的 键有一个5字节的长度,并且为每个插入的企图而被增加。这个键不出现在SHOW CREATE TABLE或DESCRIBE的输出之中。

·         PRIMARY KEY比任何其它索引都要快,因为PRIMARY KEY被与行的数据一起存储。其它索引被存储为键数据+PRIMARY KEY,所以保持PRIMARY KEY尽可能地短以节约磁盘空间并获得更好速度是重要的。

这个行为类似于InnoDB的,在其中较短的primary keys不仅在主索引也在第二索引节约空间 。

·         如果在BDB表中,你访问的所有列是同一索引的一部分或主键的一部分,MySQL可以执行查询而不访问确实的行。在一个MyISAM表中,只有 列是同一索引的一部分之时,才可以这么做。

·         连续扫描比对MyISAM表的扫描更慢,因为在BDB表中的数据被存储在B树而不是在分离的数据文件中。

·        键值象MyISAM表中的 键值一样不是前缀或后缀压缩的。换句话说,在BDB表中键信息只比在MyISAM表中稍微多占据一点空间。

·         在BDB表中经常有洞允许你在索引树的中间插入新行。这个使得BDB表比MyISAM表稍微大一些

·         SELECT COUNT(*) FROM tbl_name对BDB表很慢,因为在该表中没有行计数被维持。

·         优化器需要知道表中的大概行数。MySQL通过计数插入以及在每个BDB表中的单独片断内维持它来解决了问题。如果你不发出大量的DELETE或ROLLBACK语句,这个数对MySQL优化器来说是足够精确了。可是,MySQL仅在关闭的时候才存储这个数,所以,如果服务器被意外地终止,这个数可能是不正确的。即使数不是100%正确,它不是 明确的。你可以使用ANALYZE TABLE或者 OPTIMIZE TABLE语句来更新行计数。请参阅13.5.2.1节,“ANALYZE TABLE语法”13.5.2.5节,“OPTIMIZE TABLE语法”

·         BDB表上的内部锁定在页面级别上做。

·         LOCK TABLES在BDB表上就想在其它表上一样工作。如果你不使用LOCK TABLES,MySQL对该表发出一个内部多重写锁定 (一个不阻止其它作者的锁定)来确保即使另一个线程发出一个表锁定,该表也被恰当地锁定了。

·         要能够回滚一个事务,BDB存储引擎维护日志文件。多实现最高性能,你可以使用--bdb-logdir选项来把BDB日志放在不同的磁盘上,而不是放在数据库被放置的那个磁盘。

·         每次新BDB日志文件被启动之时,MySQL执行一个检查点,并且删掉当前事务不需要的任何BDB日志文件。你也可以在任何时候使用FLUSH LOGS来给Berkeley DB表设置检查点。

对灾难恢复,你应该使用表备份加MySQL的二进制日志,请参阅5.9.1节,“数据库备份”

警告:如果你删除仍在使用中的旧日志文件,BDB根本不能做恢复,并且如果有些事不对,你可能会丢失数据。

·         应用程序必须总是被准备来处理情况,即BDB表任何的改变可能导致一个自动回滚并且任何读可能会带着一个死锁错误而失败。

·         如果你在BDB表内遇到磁盘满,你得到一个错误(可能是错误28),并且事务应该回滚。这与MyISAM表相反,对于MyISAM 表,mysqld在继续之前等待足够的自由磁盘空间。

15.5.5 . 修改BDB所需的 事宜

·         同时打开许多BDB表可能是非常慢的。如果你要使用BDB表,你不应使用非常大的表缓存(例如,大于256)并且当你使用mysql客户端之时,你应该使用--no-auto-rehash选项。

·         SHOW TABLE STATUS 不为BDB表提供一些信息:

·                mysql> SHOW TABLE STATUS LIKE 'bdbtest'\G
    
      
       
·                *************************** 1. row ***************************
    
      
       
·                           Name: bdbtest
    
      
       
·                         Engine: BerkeleyDB
    
      
       
·                        Version: 10
    
      
       
·                     Row_format: Dynamic
    
      
       
·                           Rows: 154
    
      
       
·                 Avg_row_length: 0
    
      
       
·                    Data_length: 0
    
      
       
·                Max_data_length: 0
    
      
       
·                   Index_length: 0
    
      
       
·                      Data_free: 0
    
      
       
·                 Auto_increment: NULL
    
      
       
·                    Create_time: NULL
    
      
       
·                    Update_time: NULL
    
      
       
·                     Check_time: NULL
    
      
       
·                      Collation: latin1_swedish_ci
    
      
       
·                       Checksum: NULL
    
      
       
·                 Create_options:
    
      
       
·                        Comment:
    
      
       

·         优化性能。

·         改变为对表扫描操作使用无页面锁定。

15.5.6 对BDB表的限制

下列表说明使用BDB表之时你必须要遵从的限制:

·         每个BDB表在.db文件里存储文件被创建之时到该文件的路径。这个被做来允许在支持symlinks的多用户环境里检测锁定。因此,从一个数据库目录往另一个目录移动BDB表是不能的。

·         当制作BDB表的备份之时,你必须要么使用mysqldump要么做一个包含对每个BDB表的文件(.frm和.db文件)及BDB日志文件的备份。BDB存储引擎在它的日志文件存储未完成的事务以及要求它们在mysqld启动的时候被呈出来。BDB日志在数据目录里,具有log.XXXXXXXXXX(10位数字)形式名字的文件。

·         如果允许NULL值的列有唯一的索引,只有单个NULL值是被允许的。这不同于其它存储引擎。

15.5.7 . 使用BDB表时可能发生的错误

·         如果你升级之后启动mysqld时发生下列错误,它意味着新BDB版本不支持旧日志文件格式:

·                bdb:  Ignoring log file: .../log.XXXXXXXXXX:
    
      
       
·                unsupported log version #
    
      
       

在这种情况下,你必须删除从数据目录所有BDB日志(名字为log.XXXXXXXXXX这样格式的文件)并重新启动mysqld。我们也推荐你随后用mysqldump --opt来转储你的BDB表,移除表,并且从转储文件恢复它们。

·         如果autocommit模式被禁止,你移除在另一个事务中被参考的BDB表,你会从你的MySQL错误日志得到如下的错误信息:

·                001119 23:43:56  bdb:  Missing log fileid entry
    
      
       
·                001119 23:43:56  bdb:  txn_abort: Log undo failed for LSN:
    
      
       
·                                       1 3644744: Invalid
    
      
       

这不是一个致命错误,但是知道问题被解决,我们推荐你不要移除BDB表,除了autocommit模式被允许之时。(修复不是微不足道的)。

关注编程学问公众号