Chinaunix首页 | 论坛 | 博客
  • 博客访问: 100993439
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: Mysql/postgreSQL

2008-05-11 22:21:06

15.2.17.1. InnoDB数据词典操作错误诊断和排除

表的一个特殊问题是MySQL服务器以.frm文件来保存数据词典信息,它被放在数据库目录,然而InnoDB也存储信息到表空间文件里它自己的数据词典里。如果你把.frm文件移来移去;或者,如果服务器在数据词典操作的中间崩溃,.frm文件可能结束与InnoDB内部数据词典的同步。

一个不同步的数据词典的症状是CREATE TABLE语句失败。如果发生这种情况,你应该查看服务器的错误日志。如果日志说表已经存在于InnoDB内部数据词典当中,你在InnoDB表空间文件内有一个孤表,它没有对应的.frm文件。错误信息看起来象如下的:

InnoDB: Error: table test/parent already exists in InnoDB internal
InnoDB: data dictionary. Have you deleted the .frm file
InnoDB: and not used DROP TABLE? Have you used DROP DATABASE
InnoDB: for InnoDB tables in MySQL version <= 3.23.43?
InnoDB: See the Restrictions section of the InnoDB manual.
InnoDB: You can drop the orphaned table inside InnoDB by
InnoDB: creating an InnoDB table with the same name in another
InnoDB: database and moving the .frm file to the current database.
InnoDB: Then MySQL thinks the table exists, and DROP TABLE will
InnoDB: succeed.

你可以按照错误日志里给的指示移除一个孤表。如果还是不能成功地使用DROP TABLE,问题可能是因为在mysql客户端里的名字完成。要解决这个问题,用--disable-auto-rehash选项来启动mysql客户端并再次尝试DROP TABLE 。(有名字完成打开着,mysql试着构建个表名字的列表,当一个正如描述的问题存在之时,这个列表就不起作用)。

不同步数据词典的另一个“同义词”是MySQL打印一个不能打开.InnoDB文件的错误:

ERROR 1016: Can't open file: 'child2.InnoDB'. (errno: 1)

在错误日志你可以发现一个类似于此的信息:

InnoDB: Cannot find table test/child2 from the internal data dictionary
InnoDB: of InnoDB though the .frm file for the table exists. Maybe you
InnoDB: have deleted and recreated InnoDB data files but have forgotten
InnoDB: to delete the corresponding .frm files of InnoDB tables?

这意味这有一个孤单的.frm文件,在InnoDB内没有相对应的表。你可以通过手动删除来移除这个孤单的.frm文件。

如果MySQL在一个 ALTER TABLE操作的中间崩溃,你可以用InnoDB表空间内临时孤表来结束。你可以用innodb_table_monitor看一个列出的表,名为#sql-...。如果你把表的名字包在`(backticks)里,你可以在名字包含“#”字符的表上执行SQL语句。因此,你可以用前述的的方法象移除其它孤表一样移除这样一个孤表。注意,要在Unix外壳里复制或重命名一个文件,如果文件名包含"#"字符,你需要把文件名放在双引号里。

15.3. MERGE存储引擎

MERGE存储引擎,也被认识为MRG_MyISAM引擎,是一个相同的可以被当作一个来用的MyISAM表的集合。“相同”意味着所有表同样的列和索引信息。你不能合并列被以不同顺序列于其中的表,没有恰好同样列的表,或有不同顺序索引的表。而且,任何或者所有的表可以用myisampack来压缩。请参阅8.2节,“myisampack — 生成压缩的只读MyISAM表”。表选项的差异,比如AVG_ROW_LENGTH, MAX_ROWS或PACK_KEYS都不重要。

当你创建一个MERGE表之时,MySQL在磁盘上创建两个文件。文件名以表的名字开始,并且有一个扩展名来指明文件类型。一个.frm文件存储表定义,一个.MRG文件包含被当作一个来用的表的名字。这些表作为MERGE表自身,不必要在同一个数据库中。

你可以对表的集合用SELECT, DELETE, UPDATE和INSERT。你必须对你映射到一个MERGE表的这些表有SELECT, UPDATE和DELETE 的权限。

如果你DROP MERGE表,你仅在移除MERGE规格。底层表没有受影响。

当你创建一个MERGE表之时,你必须指定一个UNION=(list-of-tables)子句,它说明你要把哪些表当作一个来用。如果你想要对MERGE表的插入发生在UNION列表中的第一个或最后一个表上,你可以选择地指定一个INSERT_METHOD选项。使用FIRST或LAST值使得插入被相应地做在第一或最后一个表上。如果你没有指定INSERT_METHOD选项,或你用一个NO值指定该选项。往MERGE表插入记录的试图导致错误。

下面例子说明如何创建一个MERGE表:

mysql> CREATE TABLE t1 (
    ->    a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ->    message CHAR(20));
mysql> CREATE TABLE t2 (
    ->    a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ->    message CHAR(20));
mysql> INSERT INTO t1 (message) VALUES ('Testing'),('table'),('t1');
mysql> INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2');
mysql> CREATE TABLE total (
    ->    a INT NOT NULL AUTO_INCREMENT,
    ->    message CHAR(20), INDEX(a))
    ->    TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;

注意,一个列在MERGEN表中被索引,但没有被宣告为一个PRIMARY KEY,因为它是在更重要的MyISAM表中。这是必要的,因为MERGE表在更重要的表中的设置上强制非唯一性。

创建MERGE表之后,你可以发出把一组表当作一体来操作的查询:

mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table   |
| 3 | t1      |
| 1 | Testing |
| 2 | table   |
| 3 | t2      |
+---+---------+

注意,你也可以直接从MySQL之外直接操作.MRG文件:

shell> cd /mysql-data-directory/current-database
shell> ls -1 t1 t2 > total.MRG
shell> mysqladmin flush-tables

要重映射一个MERGE表到一个不同的MyISAM表集,你可以执行下列之一:

·         DROP MERGE表并且重建它。

·         使用ALTER TABLE tbl_name UNION=(...)来改变底层表的列表。

·         改变.MRG文件,并对MERGE表或者所有底层表发出一个FLUSH TABLE语句来强制存储引擎去读新的定义文件。

MERGE表可以帮你解决以下问题:

·         容易地管理一套日志表。比如,你可以把不同月的数据放进分离的表中,用myisampack压缩其中的一些,并随后创建一个MERGE表来把它们当作一个来使用。

·         获得更快的速度。你可以以一些标准来分割大的只读表,然后放进不同磁盘上的单个表中。基于此的一个MERGE表可比使用大表要快得多。

·         执行更有效的搜索。如果你确切知道要搜索什么,对一些查询你可以只在被分割的表的其中之一来搜索,并且对其它使用MERGE。你甚至有许多不同的MERGE表,它们使用有重叠的表套。

·         执行更有效的修补。修补被映射到一个MERGE表中的单个表比修补单个大型表要更轻松。

·         即刻映射许多表成一个。MERGE表不需要维护它自己的索引,因为它使用大哥表的所用。因此,MERGE表集合是非常块地创建或重映射。(注意,当你创建一个MERGE表之时,即使没有索引被创建,你必须仍然指定索引定义)。

·         如果根据需要或按照批次,你有一组要合起来作为一个大表的表,你应该根据需要对它们创建一个MERGE表来替代大表。这样要快得多而且节约大量的磁盘空间。

·         超过操作系统的文件尺寸限制。每个MyISAM表都受制于这个限制,但是一个MyISAM表的集合则不然。

·         你可以通过定义一个映射到单个表的MERGE表来为一个MyISAM表创建一个别名或“同物异名”。这样做应该没有真实的可察觉的性能影响 (对每个读只有一些间接调用和memcpy()调用)。

MERGE表的缺点:

·         你可以对MERGE表使用仅相同的MyISAM表。

·         你不能在MERGE表中使用很多MyISAM功能。比如,你不能在MERGE表上创建FULLTEXT索引。(当然,你可以在底层MERGE 表上创建FULLTEXT索引,但是你不能用全文搜索来搜索MERGE表)。

·         如果MERGE表是非临时的,所有底层MyISAM表也必须是永久的。如果MERGE表是临时的,MyISAM表可以是任何临时&非临时的混合。

·         MERGE表使用更多的文件描述符。如果是个客户端正使用一个映射到10个表的MERGE表,服务器使用(10*10)+10个文件描述符。(10个数据文件描述符给10个客户端每人一个,并且在客户端之间共享10个索引文件描述符)。

· 键读会更慢。当你读一个键的时候,MERGE存储引擎需要在所有 底层表上发出一个读以检查哪一个接近匹配给定的键。如果你随后做了一个read-next,MERGE存储引擎需要搜索读缓冲来找出下一个键。只有当一个键缓冲被耗尽,存储引擎才需要读下一个键块。这使得MERGE键在eq_ref搜索中非常慢,但在ref搜索中不是太慢。请参阅7.2.1节,“EXPLAIN 语法(获取SELECT相关信息)” 以获得更多关于eq_ref和ref的信息。

15.3.1MERGE表方面的问题

下列是已知关于MERGE表的问题:

·         如果你使用ALTER TABLE 来把MERGE表变为其它表类型,到底层表的映射就被丢失了。取而代之的,来自底层MyISAM表的行被复制到已更换的表中,该表随后被指定新类型。

·         REPLACE不起作用。

·         没有WHERE子句,或者在任何被映射到一个打开的MERGE表上的任何一个表上的REPAIR TABLE,TRUNCATE TABLE, OPTIMIZE TABLE或ANALYZE TABLE,你不能使用DROP TABLE, ALTER TABLE, DELETE FROM。如果你这么做了,MERGE表将仍旧指向原始表,这样产生意外结果。解决这个不足最简单的办法是在执行任何一个这些操作之前发出一个FLUSH TABLES语句来确保没有MERGE表仍旧保持打开。

·         一个MERGE表不能在整个表上维持UNIQUE约束。当你执行一个INSERT, 数据进入第一个或者最后一个MyISAM表(取决于INSERT_METHOD选项的值)。MySQL确保唯一键值在那个MyISAM表里保持唯一,但不是跨集合里所有的表。

·         当你创建一个MERGE表之时,没有检查去确保底层表的存在以及有相同的机构。当MERGE表被使用之时,MySQL检查每个被映射的表的记录长度是否相等,但这并不十分可靠。如果你从不相似的MyISAM表创建一个MERGE表,你非常有可能撞见奇怪的问题。

·         在MERGE表中的索引的顺序和它的底层表中的索引应该一样。如果你使用ALTER TABLE给一个被用在MERGE表中的表添加一个UNIQUE索引,然后使用ALTER TABLE在MERGE表上添加一个非唯一索引,如果在底层表上已经有一个非唯一索引,对表的索引排序是不同的。(这是因为ALTER TABLE把UNIQUE索引放在非唯一索引之前以利于重复键的快速检测 )。因此对使用这样索引的表的查询可能返回不期望的结果。

·         在Windows中,在一个被MERGE表使用的表上DROP TABLE不起作用,因为MERGE引擎的表映射对MySQL的更上层隐藏。因为Windows不允许已打开文件的删除,你首先必须刷新所有MERGE表(使用FLUSH TABLES)或在移除该表之前移除MERGE表。

对于MERGE存储引擎,在上有一个专门的论坛。

15.4. MEMORY (HEAP)存储引擎

MEMORY存储引擎用存在内存中的内容来创建表。这些在以前被认识为HEAP表。MEMORY是一个首选的术语,虽然为向下兼容,HEAP依旧被支持。

每个MEMORY表和一个磁盘文件关联起来。文件名由表的名字开始,并且由一个.frm的扩展名来指明它存储的表定义。

要明确指出你想要一个MEMORY表,可使用ENGINE选项来指定:

CREATE TABLE t (i INT) ENGINE = MEMORY;

如它们名字所指明的,MEMORY表被存储在内存中,且默认使用哈希索引。这使得它们非常快,并且对创建临时表非常有用。可是,当服务器关闭之时,所有存储在MEMORY表里的数据被丢失。因为表的定义被存在磁盘上的.frm文件中,所以表自身继续存在,在服务器重启动时它们是空的。

这个例子显示你如何可以创建,使用并删除一个MEMORY表:

mysql> CREATE TABLE test ENGINE=MEMORY
    ->     SELECT ip,SUM(downloads) AS down
    ->     FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;

MEMORY表有下列特征:

·         给MEMORY表的空间被以小块来分配。表对插入使用100%动态哈希来。不需要溢出区或额外键空间。自由列表无额外的空间需求。已删除的行被放在一个以链接的列表里,并且在你往表里插入新数据之时被重新使用。MEMORY表也没有通常与在哈希表中删除加插入相关的问题。

·         MEMORY表可以有多达每个表32个索引,每个索引16列,以及500字节的最大键长度。

·         MEMORY存储引擎执行HASH和BTREE索引。你可以通过添加一个如下所示的USING子句为给定的索引指定一个或另一个:

·                CREATE TABLE lookup
·                    (id INT, INDEX USING HASH (id))
·                    ENGINE = MEMORY;
·                CREATE TABLE lookup
·                    (id INT, INDEX USING BTREE (id))
·                    ENGINE = MEMORY;

B树的一般特征和哈希索引在7.4.5节,“MySQL如何使用索引”里描述。

·         你可以在一个MEMORY表中有非唯一键。(对哈希索引的实现,这是一个不常用的功能)。

·         你页可以对MEMORY表使用INSERT DELAYED。请参阅13.2.4.2节,“INSERT DELAYED语法”

·         如果你在一个有高度键重复的(许多索引条目包含同一个值)MEMORY表上有一个哈希索引,对影响键值的表的更新及所有删除都是明显地慢的。这个变慢的程度比例于重复的程度(或者反比于索引cardinality)。你可以使用一个B树索引来避免这个问题。

·         MEMORY表使用一个固定的记录长度格式。

·         MEMORY不支持BLOB或TEXT列。

·         MEMORY支持AUTO_INCREMENT列和对可包含NULL值的列的索引。

·         MEMORY表在所有客户端之间共享(就像其它任何非TEMPORARY表)。

·         MEMORY表内容被存在内存中,内存是MEMORY表和服务器在查询处理之时的空闲中创建的内部表共享。可是,两个类型的表不同在于MEMORY表不会遇到存储转换,而内部表是:

-        如果一个内部表变得太大,服务器自动把它转换为一个磁盘表。尺寸限制由tmp_table_size系统变量的值来确定。

-        MEMORY表决不会转换成磁盘表。要确保你不会偶尔做点傻事,你可以设置max_heap_table_size系统变量给MEMORY表加以最大尺寸。对于单个的表,你也可以在CREATE TABLE语句中指定一个MAX_ROWS表选项。

·         服务器需要足够内存来维持所有在同一时间使用的MEMORY表。

·         当你不再需要MEMORY表的内容之时,要释放被MEMORY表使用的内存,你应该执行DELETE FROM或TRUNCATE TABLE,或者整个地删除表(使用DROP TABLE)。

·         当MySQL服务器启动时,如果你想开拓MEMORY表,你可以使用--init-file选项。例如,你可以把INSERT INTO ... SELECT 或LOAD DATA INFILE这样的语句放入这个文件中以便从持久稳固的的数据源装载表。请参阅5.3.1节,“mysqld 命令行选项” and 13.2.5节,“LOAD DATA INFILE 语法”

·         如果你正使用复制,当主服务器被关闭且重启动之时,主服务器的MEMORY表变空。可是从服务器意识不到这些表已经变空,所以如果你从它们选择数据,它就返回过时的内容。自从服务器启动后,当一个MEMORY表在主服务器上第一次被使用之时,一个DELETE FROM语句被自动写进主服务器的二进制日志,因此再次让从服务器与主服务器同步。注意,即使使用这个策略,在主服务器的重启和它第一次使用该表之间的间隔中,从服务器仍旧在表中有过时数据。可是,如果你使用--init-file选项于主服务器启动之时在其上推行MEMORY表。它确保这个时间间隔为零。

·         在MEMORY表中,一行需要的内存使用下列表达式来计算:

·                SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)
·                + SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)
·                + ALIGN(length_of_row+1, sizeof(char*))

ALIGN()代表round-up因子,它使得行的长度为char指针大小的确切倍数。sizeof(char*)在32位机器上是4,在64位机器上是8。

对于MEMORY存储引擎,在上有一个专门的论坛。

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网站,。

15.5.1BDB支持的操作系统

当前,我们知道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.3BDB启动选项

下列对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.4BDB表的特征

每个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模式被允许之时。(修复不是微不足道的)。

15.6. EXAMPLE存储引擎

EXAMPLE存储引擎是一个不做任何事情的存根引擎。它的目的是作为MySQL源代码中的一个例子,用来演示如何开始编写一个新存储引擎。 同样,它的主要兴趣是对开发者。

要对EXAMPLE引擎检查源码,请查看MySQL源码分发版的sql/examples目录。

要允许这个存储引擎,使用在建立MySQL之时使用--with-example-storage-engine选项来configure

当你创建一个EXAMPLE之时,服务器创建在数据库目录创建一个表定义文件。文件由表名字开始,并由一个.frm的扩展名。没有其它文件被创建。没有数据被存储进表或者从中取回。

mysql> CREATE TABLE test (i INT) ENGINE = EXAMPLE;
Query OK, 0 rows affected (0.78 sec)
 
mysql> INSERT INTO test VALUES(1),(2),(3);
ERROR 1031 (HY000): Table storage engine for 'test' doesn't have this option
 
mysql> SELECT * FROM test;
Empty set (0.31 sec)

EXAMPLE存储引擎不支持编索引。

15.7. FEDERATED存储引擎

FEDERATED存储引擎访问在远程数据库的表中的数据,而不是本地的表。

FEDERATED存储引擎仅在-MAX版的MySQL上可用。

要为FEDERATED引擎检查源码,请查看MySQL源码分发版的sql目录。

对于FEDERATED存储引擎,在上有一个专门的论坛。

15.7.1. 安装FEDERATED存储引擎

要允许这个存储引擎,当你构建MySQL时请使用--with-federated-storage-engine来configure

15.7.2FEDERATED存储引擎的描述

当你创建一个FEDERATED表的时候,服务器在数据库目录创建一个表定义文件。文件由表的名字开始,并有一个.frm扩展名。无其它表被创建,因为实际的数据在一个远程数据库上。这不同于为本地表工作的存储引擎的方式。

对于本地的数据录表,数据文件是本地的。例如,如果你创建一个名为user的MyISAM表,MyISAM处理器创建一个名为users.MYD的数据文件。对本地表读,插入,删除和更新在本地数据文件里的数据的处理器和记录被以对处理器的特定格式存储。为了读记录,处理器必须把数据分解进列。为了写记录,列值必须被转换到被处理器使用的行格式并且被写进本地的数据文件。

使用MySQL FEDERATED存储引擎,没有对表的本地数据文件(比如,没有.MYD文件)。取而代之地,一个远程数据库存储那些正常地应该在表中的数据。这使得MySQL客户端API来读,删除,更新和插入数据的使用成为必要。数据取回被通过SELECT * FROM tbl_name SQL语句来初始化。要读这个结果,通过使用mysql_fetch_row() C API函数,行被一次取一个,然后从SELECT结果包中的列转换成FEDERATED处理器期望的格式。

基本流程如下:

1.    SQL调用被本地发布

2.    MySQL处理器API (数据以处理器格式)

3.    MySQL客户端API (数据被转换成SQL调用)

4.    远程数据库-> MySQL客户端API

5.    转换结果包(如果有的话)到处理器格式

6.    处理器 API -> 结果行或受行影响的对本地的计数

15.7.3. 如何使用FEDERATED

使用FEDERATED表的步骤是非常简单的。通常,你运行两个服务器,要么在同一个主机上,要么在不同主机上。(一个FEDERATED表使用其它被同一服务器管理的表也是可能的。虽然只有极少的点要这么做)。

首先,你必须在你想要用FEDERATED表访问的远程服务器上有一个表。假设,远程的表在FEDERATED数据库中并且被如下定义:

CREATE TABLE test_table (
    id     int(20) NOT NULL auto_increment,
    name   varchar(32) NOT NULL default '',
    other  int(20) NOT NULL default '0',
    PRIMARY KEY  (id),
    KEY name (name),
    KEY other_key (other)
)
ENGINE=MyISAM
DEFAULT CHARSET=latin1;

ENGINE表选项可能命名任何存储引擎,该表需要不是一个MyISAM表。

接着,在本地服务器上为访问远程表创建一个FEDERATED表:

CREATE TABLE federated_table (
    id     int(20) NOT NULL auto_increment,
    name   varchar(32) NOT NULL default '',
    other  int(20) NOT NULL default '0',
    PRIMARY KEY  (id),
    KEY name (name),
    KEY other_key (other)
)
ENGINE=FEDERATED
DEFAULT CHARSET=latin1
CONNECTION='mysql://root@remote_host:9306/federated/test_table';

注意: CONNECTION 替代 用在先前版本的MySQL里的COMMENT)。

除了ENGINE表选项应该是FEDERATED,并且CONNECTION表选项是给FEDERATED指明如何连接到远程服务器上的连接字符串之外,这个表的结构必须完全与远程表的结构相同。

FEDERATED引擎仅创建在已联盟数据库中的test_table.frm文件。

远程主机信息指明本地服务器要连接到的远程服务器,数据库和表信息指明哪一个远程表要被作为数据文件来用。在这个例子中。远程服务器被指定来作为远程主机在9306端口上运行,所以你要启动服务器,让它监听9306端口。

在CONNECTION选项中的连接字符串的一般形式如下:

scheme://user_name[:password]@host_name[:port_num]/db_name/tbl_name

只有mysql在这一点被支持为scheme,密码和端口号时可选的。

这里有一些连接字符串的例子:

CONNECTION='mysql://username:password@hostname:port/database/tablename'
CONNECTION='mysql://username@hostname/database/tablename'
CONNECTION='mysql://username:password@hostname/database/tablename'

为指定连接字符串使用CONNECTION是非可选,并且在将来可能会改变。当你使用FEDERATED表的时候,要记得这个,因为这意味着当将来发生那种改变之时,可能被要求。

因为任何被用的密码作为纯文本被存在连接字符串中,它可以被任何使对FEDERATED表使用SHOW CREATE TABLE或SHOW TABLE STATUS的用户,或者在INFORMATION_SCHEMA数据库中查询TABLES表的用户看见。

对于FEDERATED存储引擎,在上有一个专门的论坛。

15.7.4FEDERATED存储引擎的局限性

FEDERATED支持及不支持的如下:

·         在第一个版本中,远程服务器必须是一个MySQL服务器。FEDERATED对其它数据库引擎的支持可能会在将来被添加。

·         FEDERATED表指向的远程表在你通过FEDERATED表访问它之前必须存在。

·         一个FEDERATED表指向另一个FEDERATED表是可能的,但是你必须小心不要创建一个循环。

·         没有对事务的支持。

·         如果远程表已经改变,对FEDERATED引擎而言是没有办法知道的。这个的原因是因为这个表必须象数据文件一样工作,除了数据库其它任何都不会被写入。如果有任何对远程数据库的改变,本地表中数据的完整性可能会被破坏。

·         FEDERATED存储引擎支持SELECT, INSERT, UPDATE, DELETE和索引。它不支持ALTER TABLE, DROP TABLE或任何其它的数据定义语言语句。当前的实现不使用预先准备好的语句。

·         执行使用SELECT, INSERT, UPDATE和DELETE,但不用HANDLER。

·         FEDERATED表不能对查询缓存不起作用。

这些限制中的一些在FEDERATED处理机的将来版本可能被消除。

15.8. ARCHIVE存储引擎

ARCHIVE存储引擎被用来以非常小的覆盖区存储大量无索引数据。 

要允许这个存储引擎,在建立MySQL之时使用--with-archive-storage-engine选项来configure。如果这个存储引擎可带这个语句使用,你可以看见:

mysql> SHOW VARIABLES LIKE 'have_archive';

当年创建一个ARCHIVE表,服务器在数据库目录创建一个表定义文件。文件由表的名字开始,并由一个.frm的扩展名。存储引擎创建其它文件,所有都有由表名字开头的名字。数据和元数据文件有扩展名.ARZ和.ARM。一个.ARN文件可能在优化操作中出现。

ARCHIVE引擎仅支持INSERT和SELEC(无删除,替换或更新)。它支持ORDER BY操作,BLOB 域,以及基本地所有数据类型,除了几何数据类型(请参阅19.4.1节,“MySQL 空间数据类型”)。ARCHIVE引擎使用行级锁定。

存储: 当记录被插入时,它们被压缩。ARCHIVE引擎使用无损数据压缩。OPTIMIZE TABLE的使用可以分析表,并把它打包为更小的格式( 使用OPTIMIZE TABLE的原因,往下看)。引擎页支持CHECK TABLE。有数种被使用的插入类型:

·         直接插入INSERT之时把一行推仅压缩缓冲,并且缓冲在它需要的时候刷新。到缓冲的插入被锁定保护。一个SELECT强制一个刷新发生,除非进来的唯一插入是INSERT DELAYED(那些刷新如同需要一样)。请参阅13.2.4.2节,“INSERT DELAYED 语法”

·         块插入旨在它完成后可见,除非其它插入在同一时间发生,在这种情况下,块插入可以被部分看见。一个SELECT不会导致一个块插入的刷新,除非SELECT在被装载时发生一个正常插入。

取回: 在取回时,记录根据需要被解压缩,没有行缓存。一个SELECT操作执行完全表格扫描:当一个SELECT发生之时,它找出当前有多少行可用,并读行的数量。SELECT被当作持续读来执行。注意,许多SELECT语句在插入过程中会损坏压缩,除非块插入或者延迟的插入被使用。要修复任何已发生压缩问题,你可以总是做OPTIMIZE TABLE(也支持REPAIR TABLE)。被SHOW TABLE STATUS报告的行数总是正确的。请参阅13.5.2.6节,“REPAIR TABLE语法”13.5.2.5节,“OPTIMIZE TABLE语法”13.5.4.18节,“SHOW TABLE STATUS 语法”

对于ARCHIVE存储引擎,在 上有专门论坛。

15.9. CSV存储引擎

CSV存储引擎使用逗号分隔值格式的文本文件存储数据。

要允许使用这个存储引擎,当你建立MySQL之时,使用--with-csv-storage-engine选项来configure

当你创建一个CSV表之时,服务器在数据库目录创建一个表定义文件。文件由表的名字开始,并且由一个.frm的扩展名。存储引擎也创建一个数据文件。它的名字由表的名字开始,并且有一个.CSV的扩展名。数据文件是无格式文本文件。当你把数据存储进表时,存储引擎用CSV格式把它存进数据文件。

mysql> CREATE TABLE test(i INT, c CHAR(10)) ENGINE = CSV;
Query OK, 0 rows affected (0.12 sec)
 
mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0
 
mysql> SELECT * FROM test;
+------+------------+
| i    | c          |
+------+------------+
|    1 | record one |
|    2 | record two |
+------+------------+
2 rows in set (0.00 sec)

如果你检查在执行前述语句所创建的数据库目录里的test.CSV文件,它的内容应该看起来象如下所示:

"1","record one"
"2","record two"

CSV存储引擎不支持索引。

15.10. BLACKHOLE存储引擎

BLACKHOLE存储引擎就像“黑洞”一样,它接收数据但丢弃它而不是存储它。取回总是返回空集:

mysql> CREATE TABLE test(i INT, c CHAR(10)) ENGINE = BLACKHOLE;
Query OK, 0 rows affected (0.03 sec)
 
mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0
 
mysql> SELECT * FROM test;
Empty set (0.00 sec)

当你创建一个BLACKHOLE表的时候,服务器在数据库目录创建一个表定义文件。文件用表的名字开头,并且有一个.frm扩展名。没有其它文件关联到这个表格。

BLACKHOLE存储引擎支持所有种类的索引。

要允许这个存储引擎,在你建立MySQL之时使用--with-blackhole-storage-engine选项来configure。BLACKHOLE存储引擎在MySQ供应的服务器二进制版里可以找到;通过查看SHOW ENGINES或SHOW VARIABLES LIKE 'have%'的输出,你可以确定你的版本是否支持这个引擎。

到BLACKHOLE表的插入不存储任何数据,但如果二进制日志被允许,SQL语句被写入日志(并被复制到从服务器)。这可以有用帮助地作为重复器或过滤器机制。例如,假设你的应用需要从服务器侧的过滤规则,但传输所有二进制日志数据到从服务器首先导致过多交通的结果。在这种情况下,在主服务器主机上建立一个伪从服务器进程,它的存储引擎是BLACKHOLE,描述如下:

Replication using BLACKHOLE
        for filtering

主服务器写它的二进制日志。伪mysqld进程作为从服务器,应用期望的replicate-do和replicate-ignore规则的合并,并且写一个新的,被过滤的属于它自己的二进制日志 。(请参阅6.8节,“复制启动选项”)。这个已过滤日志被提供给从服务器。

既然伪进程不确实地存储任何数据,只有很小的由在复制主服务器主机上额外的mysqld进程招致的处理开支。这个类型的建立可以用额外复制从服务器来重复。

其它可能对BLACKHOLE存储引擎的使用包括:

·         转储文件语法的验证。

·         来自二进制日志记录的开销测量,通过比较允许二进制日志功能的BLACKHOLE的性能与禁止二进制日志功能的BLACKHOLE的性能。

·         因为BLACKHOLE本质上是一个“no-op” 存储引擎,它可能被用来查找与存储引擎自身不相关的性能瓶颈。


这是MySQL参考手册的翻译版本,关于MySQL参考手册,请访问dev.mysql.com。 原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的。


 

阅读(855) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~