MySQL 5.1参考手册 :: 15. 存储引擎和表类型(6)
时间:2008-05-11 来源:sdccf
15.2.12. 多版本的实施
因为InnoDB是多版本化的数据库, 它必须保持关于表空间中旧版本行的信息。这个信息被存在名为rollback segment(在Oracle中模拟数据结构之后)的数据结构中。
内部地,InnoDB往存在数据库中的每一行中添加两个域。一个6字节的域说明插入或更新该行的最后一个事务的事务识别符。同时,一个删除也被内部处理为一个更新,其中行中一个特殊的位被设置来标注该行为已删除。每一行也包含一个称为滚动指针的7字节域。滚动指针指向一个被写到回滚片断的撤销日志记录。如果该行被更新,撤销日志记录包含在该行被更新之前重建该行的内容必需的的信息。
InnoDB使用在回滚片断中的信息来执行在事务回滚中需要的撤销操作。它也使用这个信息来为一个持续读构建更早版本的行。
在回滚片断中的撤销日志被分为插入和更新撤销日志。插入撤销日志仅在事务回滚中需要,且只要事务一提交就可以被丢弃。更新撤销日志也被用在持续读中,而且它们仅在当前没有被InnoDB分配给一个快照的事务之后被丢弃,这个快照在持续读中可能会需要更新撤销日志的信息来建立一个数据库行的早期版本。
你必须记得规律地提交你的事务,包括那些只发布持续读的事务。否则, InnoDB不能从更新撤销日志丢弃数据,并且回滚片断可能变得太大,填满你的表空间。
在一个回滚片断里,一个撤销日志记录的物理尺寸典型地小于相应的已插入行或已更新行。你可以用这个信息来计算回滚片断需要的空间。
在InnoDB多版本化方案中,当你用SQL语句删除一行之时,该行没有被从数据库立即物理删除掉。只有当InnoDB可以丢弃为删除而被写的更新撤销日志记录时,InnoDB也物理地从数据库删除相应行和它的索引记录。这个删除操作被成为精华,它运行得很快,通常与做删除的SQL语句花的时间在一个数量级。
在某一情景下,在那里,用户以几乎相同的比率,小批次地在表中插入和删除行,净化线程开始滞后是可能的,并且表变得越来越大,使得每样事都是磁盘绑定的而且非常慢。即使表仅载有10MB有用的数据,它可能变得用所有的死行占据10GB空间。在这种情况下,节流新操作,并分配更多的资源来净化线程可能是比较好的。启动选项和可设置全球变量innodb_max_purge_lag就是为这个目的而存在的。请参阅15.2.4节,“InnoDB 启动选项” 以获得更多信息。
15.2.13. 表和索引结构
15.2.13.1. 索引的物理结构
15.2.13.2. 缓冲插入
15.2.13.3. 适应的哈希索引
15.2.13.4. 物理记录结构
MySQL为表把它的数据词典信息以.frm文件的形式存在数据库目录里,这对所有MySQL存储引擎都是真的。但是每个InnoDB表在表空间内的InnoDB内部数据词典里有它自己的条目。当MySQL移除表或数据库,它不得不删除.frm文件和InnoDB数据词典内的相应条目。这就是为什么你不能在数据库之间简单地移动.frm文件来移动InnoDB表。
每个InnoDB表有专门索引,被称为clustered index,对行的数据被存于其中。如果你对你的表定义一个PRIMARY KEY,主键的索引是集束索引。
如果你没有为表定义PRIMARY KEY,MySQL拾取第一个仅有NOT NULL列的UNIQUE索引作为主键,并且InnoDB把它当作集束索引来用。如果表中没有这样一个索引,InnoDB内部产生一个集束索引,其中用InnoDB在这样一个表内指定给行的行ID来排序行。行ID是一个6字节的域,它在新行被插入的时候单一地增加。因此被行ID排序的行是物理地按照插入顺序排的。
通过集束索引访问一个行是较快的,因为行数据是在索引搜索引导的同一页面。如果表是巨大的,当对比于传统解决方案,集束索引构架经常节约磁盘I/O。(在许多数据库,数据传统地被存在与索引记录不同的页)。
在InnoDB中,非集束索引里的记录(也称为第二索引)包含对行的主键值。InnoDB用这个主键值来从集束索引中搜索行。注意,如果主键是长的,第二索引使用更多空间。
InnoDB比较CHAR和VARCHAR字符串不同长度,以便在较短字符串中剩下的长度被处理视为用空格补上的。
15.2.13.1. 索引的物理结构
所有InnoDB的索引是B数,其中索引记录被存储在树的树叶页。一个索引页的默认大小是16KB。当新记录被插入,InnoDB试着为将来索引记录的插入和更新留下十六分之一的空白页。
如果索引记录以连续的顺序被插入(升序或者降序),结果索引页大约是15/16满。如果记录被以随机的顺序被插入,页面是从1/2到 15/16满。如果索引页的填充因子降到低于1/2,InnoDB试着搜索索引树来释放页。
15.2.13.2. 缓冲插入
在数据库应用中,主键是一个唯一的识别符,并且新行被以主键的升序来插入,这是个常见的情况。因此,到集束索引的插入不需要从一个磁盘随机读。
另一方面,第二索引通常是非唯一的,到第二索引的插入以相对随机次序发生。这可能会导致大量的随机磁盘I/O操作,而没有一个被用在InnoDB中的专用机制。
如果一个索引记录应该被插入到一个非唯一第二索引,InnoDB检查第二索引页是否在缓冲池中。如果是,InnoDB直接插入到索引页。如果索引页没有在缓冲池中被发现,InnoDB插入记录到一个专门的插入缓冲结构。插入缓冲被保持得如此小以至于它完全适合在缓冲池,并且可以非常快地做插入。
插入缓冲周期地被合并到数据库中第二索引树里。把数个插入合并到索引树的同一页,节省磁盘I/O操作,经常地这是有可能的。据测量,插入缓冲可以提高到表的插入速度达15倍。
在插入事务被提交之后,插入缓冲合并可能连续发生。实际上,服务器关闭和重启之后,这会连续发生。(请参阅15.2.8.1节,“强制恢复”)。
当许多第二索引必须被更新之时,并且许多行已被插入之时,插入缓冲合并可能需要数个小时。在这个时间内,磁盘I/O将会增加,这样会导致磁盘绑定查询明显缓慢。另一个明显的后台I/O操作是净化线程(请参阅15.2.12节,“实现多版本化”)。
15.2.13.3. 适应的哈希索引
如果一个表几乎完全配合主内存,在其上执行查询最快的方法就是使用哈希索引。InnoDB有一个自动机制,它监视对为一个表定义的索引的索引搜索。如果InnoDB注意到查询会从建立一个哈希索引中获益,它会自动地这么做。
注意,哈希索引总是基于表上已存在的B树索引来建立。根据InnoDB对B树索引观察的搜索方式,InnoDB会在为该B树定义的任何长度的键的一个前缀上建立哈希索引。 哈希索引可以是部分的:它不要求整个B树索引被缓存在缓冲池。InnoDB根据需要对被经常访问的索引的那些页面建立哈希索引。
在某种意义上,InnoDB通过针对丰富主内存的适应的哈希索引机制来剪裁自己,更加靠近主内存数据库的架构。
15.2.13.4. 物理记录结构
InnoDB表中的记录有如下特征:
· InnoDB中每个索引记录包含一个6字节的头。这个头被用来将连续的记录连接在一起,并且也用在row-level锁定中。
· 集束索引中的记录包含对所有自定义列的域。此外,有一个6字节的域给事务ID以及一个7字节的域给滚动指针。
· 如果没有为一个表定义初级键,每个集束索引记录也包含一个6字节的行ID域。
· 每个第二索引记录也包含为集束索引键定义的所有域。
· 一个记录也包含一个指向该记录每一个域的指针,如果在一个记录中域的总长度小于128字节,该指针时一个字节;否则就是2字节。这些指针的阵列被称为记录目录。这些指针指向的区域被称为记录的数据部分。
· 内部地,InnoDB以固定长度格式存储固定长度字符列,比如CHAR(10)。InnoDB从VARCHAR列截短跟踪空间。注意,MySQL可以内部地把CHAR列转换为VARCHAR列。请参阅13.1.5.1节,“安静的列规格改变”。
· 一个SQL的NULL值在记录目录里保留1或2字节。此外,SQL的NULL值如果被保存在可变长度列,则在记录数据部分保留零字节。在一个固定长度列,它在记录的数据部分保留该列的固定长度。为NULL值保留固定空间背后的动机是之后该列从NULL值到非NULL值的更新可以就地完成,且不会导致索引页的碎片。
15.2.14.文件空间管理和磁盘I/O
15.2.14.1. 磁盘I/O
15.2.14.2. 为表空间使用原始设备
15.2.14.3.文件空间管理
15.2.14.4. 整理表碎片
15.2.14.1. 磁盘 I/O
InnoDB使用模拟异步磁盘I/O:InnoDB创建许多线程来处理I/O操作,比如read-ahead.
在InnoDB中有两个read-ahead试探:
· 在连续read-ahead中,如果InnoDB注意到在表空间中对一个片断的访问方式是连续的,它就预先布置一批数据库页的读 给I/O系统。
· 在随机read-ahead中,如果InnoDB注意到表空间中的一些区域看起来进入完全读进缓冲池中的处理中,它就布置剩余的读到I/O系统。
InnoDB使用一个被称为doublewrite的新颖的文件刷新技术。它给操作体统崩溃或掉电后的恢复添加了安全,并且通过减少对fsync()操作的需要,它在多数Unix变种上改善了性能。.
Doublewrite意为在向一个数据文件写页之前,InnoDB首先把它们写到一个毗邻的表空间区域,称为doublewrite缓冲。仅在写然后刷新到doublewrite已经完成之前,InnoDB写页面到它们在表空间中恰当的位置。如果操作系统在写页面的中间崩溃,在恢复过程中,InnoDB可以在随后从doublewrite缓冲中找到页面的一个良好复制。
15.2.14.2. 为表空间使用原始设备
你也可以使用原始磁盘分区作为表空间数据文件。通过使用原始磁盘,你可以在Windows和一些Unix系统上执行non-buffered I/O 而无须文件系统开支,这样可以改善性能
当你创建一个新数据文件之时,你必须在innodb_data_file_path里紧接着数据文件尺寸之后放置关键字newraw。分区必须至少和你指定的尺寸一样大,注意,在InnoDB中,1MB是1024x1024字节, 但是在磁盘规格中,1MB通常意为1,000,000字节。
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw
下次你启动服务器之时,InnoDB注意到关键字newraw并初始化新分区。但是仍然并不创建或改变任何InnoDB表。另外,当你重启服务器之时,InnoDB重新初始化分区,你的改变会丢失。(从3.23.44启动,作为一个安全措施, 当用newraw指定任何分区之时,InnoDB阻止用户修改数据)。
InnoDB初始化新分区之后,停止服务器,在对行的数据文件规格中改变newraw:
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:5Graw;/dev/hdd2:2Graw
然后重启动服务器,并且InnoDB允许做改变。
在Windows上,你可以象这样分配磁盘分区为一个数据文件:
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=//./D::10Gnewraw
对于访问物理驱动器,//./ 相当于Windows语法的\\.\ 。
当你使用原始磁盘分区之时,确信它们有允许被用来运行MySQL服务器的帐号读和写访问的许可。
15.2.14.3.文件空间管理
你在配置文件中定义的数据文件形成InnoDB的表空间。文件被简单地连起来以形成表空间。没有条纹在使用。当前你不能定义你的表被分配到表空间中的位置。但是,在一个新创建的表中间中,InnoDB 从第一个数据文件开始分配空间。
表空间包含数据库页,默认大小是16KB。这些页被分组成64个连续页的范围。表空间内的文件在InnoDB中被称为片断。术语“rollback segment”有一些混淆,因为它确切地包含许多表空间片断。
在InnoDB中,每个索引分配两个片断。一个是给B树的非树叶节点的,另一个是给树叶节点的。在这里,理想的是为包含数据的树叶节点达到更好的有序性。
当一个片断在表空间内长大,InnoDB单独地分配最先的32页给它。此后InnoDB开始分配整个范围给该片断。InnoDB可以一次给一个大片断添加多达4个范围以确保数据良好的连续性。
在表空间中的一些页包含其它页的位图,因此在一个InnoDB表空间中的一些范围不能被整个地分配给片断,只能作为单个页被分配。
当你发出SHOW TABLE STATUS询问表空间里可用的自由空间之时,InnoDB报告在表空间中完全自由的范围。InnoDB总是为扫除和其它内部目的保留一些范围,这些保留的范围不包括在自由空间里。
当你从一个表中删除数据之时,InnoDB联系相应的B树索引。是否释放单独页或是范围到表空间取决删除的方式,因此被释放的空间变成对其它用户可用,但是记住,已删除的行仅在该行不再被事务回滚或持续读所需要之后的一个(自动)净化操作中被物理删除。
15.2.14.4. 整理表碎片
如果有随机插入到表的索引或从表的索引随机删除,索引可能变成碎片的。碎片意思是索引页在磁盘上的物理排序并不接近页上记录的索引排序,或者在分配给索引的64页块上有许多没有被使用的页。
碎片的一个“同义词”是一个表占据的空间超过它应该占据的空间的大小。确切是多少,这是很难去确定的。所有InnoDB数据和索引被存在B树中,并且它们的填充因子可能从50%到100%。碎片的另一个“同义词”是一个表扫描例如:
SELECT COUNT(*) FROM t WHERE a_non_indexed_column <> 12345;
花了超过它应该花的时间。(在上面的查询中我们“欺骗”SQL优化器来扫描集束索引,而不是一个第二索引)。多数磁盘可以读10MB/s到50MB/s,这可以被用来评估一个表扫描可以多快地运行。
如果你周期地执行“null” ALTER TABLE操作,它就可以加速索引扫描:
ALTER TABLE tbl_name ENGINE=INNODB
这导致MySQL重建表。另一个执行碎片整理操作的办法是使用mysqldump来转储一个表到一个文本文件,移除表,并重新从转储文件重装载它。
如果到一个索引的插入总是升序的,并且记录仅从末尾被删除,InnoDB文件空间管理保证在索引中的碎片不会发生。
15.2.15. InnoDB错误处理
15.2.15.1. InnoDB错误代码
15.2.15.2. 操作系统错误代码
在InnoDB中错误处理不像SQL标准中指定的一样。按照标准,在SQL语句过程中的任何错误应该导致该语句的回滚。InnoDB有时仅回滚部分语句,或者整个事务。下列条目叙述InnoDB如何执行错误处理:
· 如果你耗尽表空间中的文件空间,你使得MySQL表完全错误,并且InnoDB返回SQL语句。
· 一个事务死锁导致InnoDB回滚整个事务,在锁定等待超时的情况,InnoDB仅回滚最近的SQL语句。
当一个事务回滚因为死锁或锁定等待超时而发生,它在事务中撤销语句的作用。但是如果事务是用START TRANSACTION或BEGIN语句开始的,它就不撤销该语句。进一步,SQL语句变成事务的一部分直到COMMIT, ROLLBACK或者导致暗地提交的SQL语句发生。
· 如果你没有在语句中指定IGNORE选项,重复键错误回滚SQL语句。
· 行太长错误回滚SQL语句。
· 其它错误主要被代码的MySQL层(在InnoDB存储引擎级别以上)探测,它们回滚相应的SQL语句。在单个SQL语句中的回滚中锁定不被释放。
在暗地回滚过程中,就像在一个明确的ROLLBACK SQL命令的执行过程中一样,SHOW PROCESSLIST在State列为有关的连接显示Rolling back。
15.2.15.1. InnoDB错误代码
下面的这个不完全列表是你可能遇见的常见的InnoDB专有错误,带着为什么发生的原因以及如何该解决问题的相关信息
· 1005 (ER_CANT_CREATE_TABLE)
不能创建表。如果错误信息字符串指向errno 150,因为外键约束被不正确地形成,所以表创建失败。
· 1016 (ER_CANT_OPEN_FILE)
虽然对某表的.frm文件存在,但不能从InnoDB数据文件找到该InnoDB表。请参阅15.2.17.1节,“InnoDB数据词典操作故障诊断和排除”。
· 1114 (ER_RECORD_FILE_FULL)
InnoDB耗尽表空间中的可用空间,你应该重新配置表空间来添加一个新数据文件。
· 1205 (ER_LOCK_WAIT_TIMEOUT)
锁定等待超时过期。事务被回滚。
· 1213 (ER_LOCK_DEADLOCK)
事务死锁。你应该重运行事务。
· 1216 (ER_NO_REFERENCED_ROW)
你正试着添加一行,但没有父行,并且一个外键约束失败。你应该先添加父行。
· 1217 (ER_ROW_IS_REFERENCED)
你正试图删除一个有子行的父行,并且一个外键约束失败。你应该先删除子行。
15.2.15.2. 操作系统错误代码
要打印一个操作系统错误号的意思,请使用MySQL分发版里的perror程序。
下面表提供一些常用Linux系统错误代码。更完整的列表请参阅Linux source code。
· 1 (EPERM)
操作不被允许
· 2 (ENOENT)
无此文件或目录
· 3 (ESRCH)
无此进程
· 4 (EINTR)
中断的系统调用
· 5 (EIO)
I/O 错误
· 6 (ENXIO)
无此设备或地址
· 7 (E2BIG)
Arg列表太长
· 8 (ENOEXEC)
Exec合适错误
· 9 (EBADF)
坏文件号
· 10 (ECHILD)
无子进程
· 11 (EAGAIN)
再试一次
· 12 (ENOMEM)
内存耗尽
· 13 (EACCES)
许可被否定
· 14 (EFAULT)
坏地址
· 15 (ENOTBLK)
阻止需求的设备
· 16 (EBUSY)
设备或资源忙
· 17 (EEXIST)
文件存在
· 18 (EXDEV)
交叉设备连接
· 19 (ENODEV)
无此设备
· 20 (ENOTDIR)
不是一个目录
· 21 (EISDIR)
是一个目录?
· 22 (EINVAL)
非法参量
· 23 (ENFILE)
文件表溢出
· 24 (EMFILE)
打开的文件过多
· 25 (ENOTTY)
设备不适合的ioctl
· 26 (ETXTBSY)
文本文件忙
· 27 (EFBIG)
文件太大
· 28 (ENOSPC)
设备上没空间了
· 29 (ESPIPE)
非法查找
· 30 (EROFS)
只读文件系统
· 31 (EMLINK)
太多连接
下列表提供一列常用Windows系统错误代码。完整列表请访问Microsoft website。
· 1 (ERROR_INVALID_FUNCTION)
不正确函数。
· 2 (ERROR_FILE_NOT_FOUND)
系统不能找到指定的文件。
· 3 (ERROR_PATH_NOT_FOUND)
系统不能找到指定的路径。
· 4 (ERROR_TOO_MANY_OPEN_FILES)
系统不能打开文件。
· 5 (ERROR_ACCESS_DENIED)
访问被拒绝。
· 6 (ERROR_INVALID_HANDLE)
句柄非法。
· 7 (ERROR_ARENA_TRASHED)
存储控制块被破坏。
· 8 (ERROR_NOT_ENOUGH_MEMORY)
无足够存储来处理这个命令。
· 9 (ERROR_INVALID_BLOCK)
存储控制块地址非法。
· 10 (ERROR_BAD_ENVIRONMENT)
环境不正确。
· 11 (ERROR_BAD_FORMAT)
试图用不正确的格式装载一个程序。
· 12 (ERROR_INVALID_ACCESS)
访问代码不合法。
· 13 (ERROR_INVALID_DATA)
数据不合法。
· 14 (ERROR_OUTOFMEMORY)
无足够的存储来完成这个操作。
· 15 (ERROR_INVALID_DRIVE)
系统不能找到指定的驱动器。
· 16 (ERROR_CURRENT_DIRECTORY)
目录不能被删除。
· 17 (ERROR_NOT_SAME_DEVICE)
系统不能移动此文件到一个不同的磁盘驱动器。
· 18 (ERROR_NO_MORE_FILES)
没有更多文件。
· 19 (ERROR_WRITE_PROTECT)
媒质写保护。
· 20 (ERROR_BAD_UNIT)
系统不能找到指定的设备。
· 21 (ERROR_NOT_READY)
设备未准备好。
· 22 (ERROR_BAD_COMMAND)
设备不能识别此命令。
· 23 (ERROR_CRC)
数据错误(循环冗余码校验).
· 24 (ERROR_BAD_LENGTH)
程序发出一个命令,但是命令长度不正确。
· 25 (ERROR_SEEK)
驱动器不能在磁盘上定位指定区域或磁道。
· 26 (ERROR_NOT_DOS_DISK)
指定的磁盘或软盘不能被访问。
· 27 (ERROR_SECTOR_NOT_FOUND)
驱动器不能找到请求的扇区。
· 28 (ERROR_OUT_OF_PAPER)
打印机缺纸。
· 29 (ERROR_WRITE_FAULT)
系统不能写指定设备。
· 30 (ERROR_READ_FAULT)
系统不能从指定设备读。
· 31 (ERROR_GEN_FAILURE)
附加到系统的设备不起作用。
· 32 (ERROR_SHARING_VIOLATION)
进程不能访问文件,因为它正被另一个进程使用。
· 33 (ERROR_LOCK_VIOLATION)
进程不能访问文件,因为另一个进程已经锁定文件的一部分。
· 34 (ERROR_WRONG_DISK)
驱动器的的磁盘不正确,请插入 %2 (卷系列号: %3) 到驱动器 %1.
· 36 (ERROR_SHARING_BUFFER_EXCEEDED)
太多文件被打开以共享。
· 38 (ERROR_HANDLE_EOF)
到达文件的末尾。
· 39 (ERROR_HANDLE_DISK_FULL)
磁盘已满。
· 87 (ERROR_INVALID_PARAMETER)
参数不正确。(如果你在Windows中得到这个错误,并且已经在my.cnf或my.ini文件中设置innodb_file_per_table,则添加innodb_flush_method=unbuffered到你的my.cnf或my.ini文件)。
· 112 (ERROR_DISK_FULL)
磁盘已满。
· 123 (ERROR_INVALID_NAME)
文件名,目录名或者卷标语法不正确。
· 1450 (ERROR_NO_SYSTEM_RESOURCES)
存在系统资源不够完成请求的服务。
15.2.16. 对InnoDB表的限制
· 一个表不能包含超过1000列。
· 内部最大键长度是3500字节,但MySQL自己限制这个到1024字节。
· 除了VARCHAR, BLOB和TEXT列,最大行长度稍微小于数据库页的一半。即,最大行长度大约8000字节。LONGBLOB和LONGTEXT列必须小于4GB, 总的行长度,页包括BLOB和TEXT列,必须小于4GB。InnoDB在行中存储VARCHAR,BLOB或TEXT列的前768字节,余下的存储的分散的页面中。
· 虽然InnoDB内部地支持行尺寸大于65535,你不能定义一个包含VARCHAR列的,合并尺寸大于65535的行。
· mysql> CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),
· -> c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
· -> f VARCHAR(10000), g VARCHAR(10000));
· ERROR 1118 (42000): Row size too large. The maximum row size for the
· used table type, not counting BLOBs, is 65535. You have to change some
· columns to TEXT or BLOBs
· 在一些更老的操作系统上,数据文件必须小于2GB。
· InnoDB日志文件的合并尺寸必须小于4GB。
· 最小的表空间尺寸是10MB。最大的表空间尺寸是4,000,000,000个数据库页(64TB)。这也是一个表的最大尺寸。
· InnoDB表不支持FULLTEXT索引。
· ANALYZE TABLE 通过对每个索引树做八次随机深入并相应地更新索引集估值,这样来计数集。注意,因为这是仅有的估值,反复运行ANALYZE TABLE会产生不同数。这使得 ANALYZE TABLE 在 InnoDB 表上很快,不是百分百准确,因为它没有考虑所有的行。
MySQL 不仅在汇合优化中使用索引集估值。如果一些汇合没有以正确的方式优化,你可以试一下 ANALYZE TABLE 。很少有情况,ANALYZE TABLE 没有产生对你特定的表足够好的值,你可以使用 FORCE INDEX 在你查询中来强制使用特定索引,或者设置 max_seeks_for_key 来确保MySQL在表扫描之上运行索引查找。请参阅5.3.3节,“服务器系统变量”。请参阅A.6节,“优化器相关的问题”。
· 在Windows上,InnoDB总是内部地用小写字母存储数据库和表名字。要把数据库以二进制形式从Unix 移到Windows,或者从Windows移到Unix,你应该让所有数据库和表的名字都是小写。
· 警告: 不要在MySQL数据库内的把MySQL系统表从MyISAM转为InnoDB表!这是一个不被支持的操作。如果你这么做了,MySQL直到你从备份恢复旧系统表,或用mysql_install_db脚本重建系统表才重启动。
· InnoDB在表内不保留行的内部计数。(因为多版本化,这可能确实有些复杂)。要处理一个SELECT COUNT(*) FROM t语句,InnoDB必须扫描表的一个索引,如果这个索引不在缓冲池中,扫描需要花一些时间。要获得快速计数,你不得不使用一个自己创建的计数器表,并让你的应用按照它做的插入和删除来更新它。如果你的表格不经常改变,使用MySQL查询缓存时一个好的解决方案。如果大致的行数就足够了,则SHOW TABLE STATUS也可被使用。请参阅15.2.11节,“InnoDB性能调节提示”。
· 对于AUTO_INCREMENT列,你必须总是为表定义一个索引,并且索引必须包含AUTO_INCREMENT列。在MyISAM表中,AUTO_INCREMENT列可能时多列索引的一部分。
· 当你重启MySQL服务器之时,InnoDB可能为一个AUTO_INCREMENT列重使用一个旧值(即,一个被赋给一个老的已回滚的事务的值)。
· 当一个AUTO_INCREMENT列用完值,InnoDB限制一个BIGINT到-9223372036854775808以及BIGINT UNSIGNED到1。尽管如此,BIGINT值有由64位,所以注意到,如果你要一秒输入100万个行,在BIGINT到达它上限之前,可能还需要将近30万年。用所有其它整数类型列,产生一个重复键错误。这类似于MyISAM如何工作的,因为它主要是一般MySQL行为,并不特别关于任何存储引擎。
· DELETE FROM tbl_name不重新生成表,但取而代之地删除所有行,一个接一个地删除。
· TRUNCATE tbl_name为InnoDB而被映射到DELETE FROM tbl_name 并且不重置AUTO_INCREMENT计数器。
· SHOW TABLE STATUS不能给出关于InnoDB表准确的统计数据,除了被表保留的物理尺寸。行计数仅是在SQL优化中粗略的估计。
· 在MySQL 5.1中,如果innodb_table_locks=1(1是默认值) MySQL LOCK TABLES操作在每一个表上获取两个锁定。除了在MySQL层的表锁定,它也获得一个InnoDB表锁定。旧版的MySQL不获取InnoDB表锁定,旧行为可以通过设置innodb_table_locks=0 来选择。如果没有InnoDB表锁定被获得,即使表的一些记录被其它事务锁定,LOCK TABLES完成。
· 所有被一个事务持有的InnoDB锁定在该事务被提交或中止之时被释放。因此在AUTOCOMMIT=1模式,在InnoDB表上调用是没有太多意义的,因为被需求的InnoDB表锁定可能会被立即释放。
· 有时,在事务的过程中锁定更多的表可能是有用的。不幸地,MySQL中的LOCK TABLES执行一个暗地的COMMIT和UNLOCK TABLES。LOCK TABLES的一个InnoDB变量已经被计划, 该计划在事务的中间被执行。
· 为建立复制从服务器的LOAD TABLE FROM MASTER语句对InnoDB表不起作用。一个工作区在主服务器上更换表为MyISAM的,然后做负载,之后更换主服务器表回到InnoDB中。
· 在InnoDB中默认数据库页的大小是16KB。通过编译代码,你可以在8KB到64KB之间来设置这个值。你不得不更新在univ.i源文件中的UNIV_PAGE_SIZE和UNIV_PAGE_SIZE_SHIFT的值。
· 在MySQL 5.1中,触发器不被级联的外键行为激活。
15.2.17. InnoDB故障诊断和排除
15.2.17.1. InnoDB数据词典操作的错误诊断和排除
· 一个总的规则是,当一个操作失败或这你怀疑有一个缺陷。你应该查看MySQL服务器的错误日志,该日志典型地有一个有些象hostname.err这样的名字,或者在Windows上是mysql.err这样的。
· 故障诊断与排除之时,通常最好从命令提示符运行MySQL服务器,而不是从mysqld_safe包运行,或不作为一个Windows服务来运行。你可以看mysqld打印到控制台上的内容,因此更好掌握发生了什么。在Windows上,你必须用--console选项启动服务器将输出定向到控制台窗口
· 使用InnoDB Monitors获取关于某问题的信息。如果问题是性能相关的,或者你的服务器看起来被挂起,你应该使用innodb_monitor来打印InnoDB内部状态的信息,如果问题是关于锁定,则使用innodb_lock_monitor。如果问题是在表的创建或其它数据词典操作,使用innodb_table_monitor来打印InnoDB内部数据词典的内容。
· 如果你猜测一个表被破坏,则在该表上运行CHECK TABLE。