
你还可以(并且应该,如果可能)使用CHECK TABLE和REPAIR TABLE语句来检查和修复MyISAM表。参见13.5.2.3节,“CHECK TABLE语法”和13.5.2.6节,“REPAIR TABLE语法”。
一张损坏的表的症状通常是查询意外中断并且能看到下述错误:
“tbl_name.frm”被锁定不能更改。
不能找到文件“tbl_name.MYI”(Errcode:nnn)。
文件意外结束。
记录文件被毁坏。
从表处理器得到错误nnn。
要想得到错误相关的详细信息,你可以运行perror nnn,其中nnn为错误编号。下面的示例显示了如何使用perror来找到最常用错误编号(用表的方式指出问题)的含义:
shell>perror 126 127 132 134 135 136 141 144 145126 = Index file is crashed / Wrong file format127 = Record-file is crashed132 = Old database file134 = Record was already deleted (or record file crashed)135 = No more room in record file136 = No more room in index file141 = Duplicate unique key or constraint on write or update144 = Table is crashed and last repair failed145 = Table was marked as crashed and should be repaired
请注意错误135(记录文件中没有更多的空间)和错误136(索引文件中没有更多的空间)不是可以通过简单修复可以修复的错误。在这种情况下,必须使用ALTER TABLE来增加MAX_ROWS和AVG_ROW_LENGTH表选项值:
ALTER TABLE tbl_name MAX_ROWS=xxx AVG_ROW_LENGTH=yyy如果你不知道当前的表的选项值,使用SHOW CREATE TABLE或DESCRIBE来查询。
对于其它的错误,你必须修复表。myisamchk通常可以检测和修复大多数问题。
修复过程包括四个阶段,此处将进行描述。开始修复前,应进入数据库目录并检查表文件的许可。在Unix中,确保它们对于运行mysqld的用户可读(你也应可读,因为你需要访问检查的文件)。如果你需要修改文件,你还必须拥有写访问权限。
用myisamchk修复表的选项的描述参见5.9.5节,“myisamchk:MyISAM表维护实用工具”的前几节。
下面几节列出了上述命令失败或你想要使用myisamchk提供的扩展特性等情况的例子。
如果你要通过命令行来修复表,必须首先停止mysqld服务器。请注意当你在远程服务器上运行mysqladmin shutdown时,mysqladmin返回后,mysqld服务器将仍然运行一会儿,直到停止所有查询并将所有键清空到硬盘上。
阶段1:检查你的表
如果你有很多时间,运行myisamchk *.MYI或myisamchk -e *.MYI。使用-s(沉默)选项禁止不必要的信息。
如果mysqld服务器处于宕机状态,应使用--update-state选项来告诉myisamchk将表标记为'检查过的'。
你必须只修复那些myisamchk报告有错误的表。对这样的表,继续到阶段2。
如果在检查时,你得到奇怪的错误(例如out of memory错误),或如果myisamchk崩溃,到阶段3。
阶段2:简单安全的修复
注释:如果想更快地进行修复,当运行myisamchk时,你应将sort_buffer_size和Key_buffer_size变量的值设置为可用内存的大约25%。
首先,试试myisamchk -r -q tbl_name(-r -q意味着“快速恢复模式”)。这将试图不接触数据文件来修复索引文件。如果数据文件包含它应有的一切内容和指向数据文件内正确地点的删除连接,这应该管用并且表可被修复。开始修复下一张表。否则,执行下列过程:
在继续前对数据文件进行备份。
使用myisamchk -r tbl_name(-r意味着“恢复模式”)。这将从数据文件中删除不正确的记录和已被删除的记录并重建索引文件。
如果前面的步骤失败,使用myisamchk --safe-recover tbl_name。安全恢复模式使用一个老的恢复方法,处理常规恢复模式不行的少数情况(但是更慢)。
如果在修复时,你得到奇怪的错误(例如out of memory错误),或如果myisamchk崩溃,到阶段3。
阶段3:困难的修复
只有在索引文件的第一个16K块被破坏,或包含不正确的信息,或如果索引文件丢失,你才应该到这个阶段。在这种情况下,需要创建一个新的索引文件。按如下步骤 *** 做:
把数据文件移到安全的地方。
使用表描述文件创建新的(空)数据文件和索引文件:
shell>mysql db_name
mysql>SET AUTOCOMMIT=1
mysql>TRUNCATE TABLE tbl_name
mysql>quit
如果你的MySQL版本没有TRUNCATE TABLE,则使用DELETE FROM tbl_name。
将老的数据文件拷贝到新创建的数据文件之中。(不要只是将老文件移回新文件之中;你要保留一个副本以防某些东西出错。)
回到阶段2。现在myisamchk -r -q应该工作了。(这不应该是一个无限循环)。
你还可以使用REPAIR TABLE tbl_name USE_FRM,将自动执行整个程序。
阶段4:非常困难的修复
只有.frm描述文件也破坏了,你才应该到达这个阶段。这应该从未发生过,因为在表被创建以后,描述文件就不再改变了。
从一个备份恢复描述文件然后回到阶段3。你也可以恢复索引文件然后回到阶段2。对后者,你应该用myisamchk -r启动。
如果你没有进行备份但是确切地知道表是怎样创建的,在另一个数据库中创建表的一个拷贝。删除新的数据文件,然后从其他数据库将描述文件和索引文件移到破坏的数据库中。这样提供了新的描述和索引文件,但是让.MYD数据文件独自留下来了。回到阶段2并且尝试重建索引文件。
InnoDB是将表中的数据存储到磁盘中,所以关闭服务器数据不会丢失。而真正发生数据处理是在内存中完成的,这样内存与磁盘的数据交互,实现了对数据的读写,而读写磁盘过程相比内存读写很慢,InnoDB采取的方式为:
将数据划分为页,以页为作为交互的数据单元,基本大小为16KB。
InnoDB为了不同的⽬的⽽设计了 许多种不同类型的⻚,⽐如存放表空间头部信息的⻚,存放Insert Buffer信息的⻚,存放INODE信息的⻚,存放undo⽇志信息的⻚等等等等。
SELECT * FROM record_compact WHERE C1=3
最笨的办法:从Infimum记录(最⼩记录)开始,沿着链表⼀直往 后找,这种暴力查找当然是不可取的,为此InnoDB设计一种目录索引。制作过程如下:
步骤一:将所有的记录(最大最小记录, 不包括已标记删除的记录)分组
步骤二:将每组中的最后一条记录(也就是组内最大的记录那条)的头信息的n_owned属性表示为改组拥有的记录条数
步骤三:将每组的最后一条记录的地址偏移量(槽)单独拿出来放在靠近页尾部的地方即page_directory页目录。所以这个⻚⾯⽬录就是由槽组成的。
我们平时以记录为单元向表中插入数据,这些记录在磁盘上的存储方式称为行格式或者记录格式。目前设计了4中行格式:Compact、Redundant、 dynamic、Compressed
行格式的语法:
CREATE TABLE 表名 (列信息) ROW_FOMAT=行格式名称
ALTER TABLE 表名 ROW_FORMAT=行格式名称
------------------------------------------------------------------------------------
例如:->USE dabao;
->CREATE TABLE record_format(c1 VARCHAR(10),c2 VARCHAR(10),c3 CHAR(10),c4 VARCHAR(10) NOT NULL) CHARSET=ascii ROW_FORMAT=COMPACT
INSERT INTO record_format(c1,c2,c3,c4)VALUES('AAA','BBBB','CCCC','DDDD'),('EEE','DDDD','DADA'NULL)
然后我们就开始解开每个行格式下的存储方式的神秘面纱。
compact分为记录的额外信息和记录的真实数据。
(1)变长字段长度列表
MySQL支持一些变长的数据类型,变长字段占用的存储空间分为两部分:真正的数据内容和占用的字节数。
把真正的数据内容占据的字节长度放在记录的开头,从而形成一个变字长的字段长度列表,各字段占用的字节数按照列的顺序 逆序 存放。根据每条记录中的列数据中的字符串大小,来判断具体使用1字节还是2个字节存储真实数据,InnoDB有自己的一套规则。M:选用的字符集类型中一个字符所占用的大小;W:变长类型的最大存储字符数;L:实际存储的字节大小。
if W*M<255 则采用1个字符存储真正字符串占用的字节数
else if W*M>255 && L<127 则采用1个字符存储真正字符串占用的字节数else 则采用2个字符存储真正字符串占用的字节数
变长字段长度列表只存储值为非NULL,
(2)NULL值 列表
不让把所有的null值都存储到真实数据中,所以compact列格式把null的列集中管理,存储到null值列表中,处理过程:
1.统计表中允许存储null的列表,如果表中没有可以null的列,则null值列表也不存在。否则每个允许null值的列占用一个位,并且逆序排列,二进制值为1时,该列的值为null。否则不为空。
2.MySQL中规定所有的null列必须存储在整个字节的位中,位数不足则最高位补零。
(3)记录头信息
5个固定字节数。记录当前记录条数,当前堆位置,下一条记录位置等信息。
(1) User Record
(2)记录头信息的秘密
1.delete_mask 这个属性表示当前记录是否被删除 占用一个位 值为1则已经删除。需要注意的是,这里的删除记录,并不是立即从磁盘中清除,是因为如果每次记录删除立即磁盘清除的话,就需要将其他记录在磁盘上重新排序需要消耗性能,所以只是打个标记,将所有的删除记录组成一个垃圾链表,标记的垃圾链表的空间则变为可重用空间,新来的记录就会覆盖标记删除的记录。
!!!删除记录位为1时与该记录假如垃圾链表其实是两个阶段。跟事务的删除 *** 作有关。
2.min_rec_mask B+树的每层非叶子节点的最小记录都会添加该标记。索引的时候会用到。
3.n_owned
4.heap_no 表示当前记录在页中的位置,有趣的是InnoDB会在每页上默认添加最大最小伪纪录作为补充称一条完整记录。
图中可以看出 最⼩记录和最⼤记录的heap_no值分 别是0和1,也就是说它们的位置最靠前。
5.record_type 表示当前记录类型,0:普通记录;1:非叶子节点记录,索引 2:最小记录;3 最大记录
6.next_record 表示从当前记录的真实数据到下⼀条记录的真实数据的 地址偏移量.下⼀条记录指得并不是按照我们插⼊顺序的下⼀条记录, ⽽是按照 主键值 由⼩到⼤的顺序的下⼀条记录.
删除一个记录时
MySQL中除了存储c1,c2,c3,c4用户自定义列数据外,MySQL会自动为每条记录添加三个隐藏列:ROW_id(主键,唯一标识一条记录,6个字节)、 transaction_id( 事务ID 6个字节 )ROLL_id(回滚指针,7个字节)
对于第2条记录中c3和c4列的值都为NULL,它们被存储在了前边的NULL值列表处,在记录的真实数据处就不再冗余存储,从⽽节省存储空间。
最终的compact列格式:
如果想要c3列也变为可变字段长度,则将定长字符集改为可变字符集。
ALTER TABLE record_format MODIFY COLUMN c3 CHAR(10) CHARACTER SET = utf8
对于Compact和Reduntant⾏格式来说,如果 某⼀列中的数据⾮常多的话,在本记录的真实数据处只会存储该列的前768个字节的数据和20个字节存储指向这些⻚的地址,然后把剩下的数据存放到其他⻚中,这个过程也叫做⾏溢出,存储超出768字节的那些⻚⾯也被称为溢出⻚。
MySQL中规定⼀个⻚中⾄少存放两⾏记录,溢出条件:
(1)每个⻚除了存放我们的记录以外,也需要存储⼀些额外的信 息,乱七⼋糟的额外信息加起来需要136个字节的空间。
(2)每个记录需要的额外信息是27字节。
假设⼀个列中存储的数据字节数为n,那么发⽣⾏溢出现象时需要满
⾜这个式⼦:136 + 2×(27 + n) >16384(页大小16K) 求解这个式⼦得出的解是:n >8098。
MySQL版本是5.7,它的默认⾏格式就是Dynamic,这俩⾏格式和Compact⾏格式挺像,只不过在处理⾏溢出数据时有点⼉分歧,它们不会在记录的真实数据处存储字段真实数据的前768个字节,⽽是把所有的字节都存储到其他⻚⾯中,只在记录的真实数据处存储其他⻚⾯的地址。
1. ⻚是MySQL中磁盘和内存交互的基本单位,也是MySQL是管理存储空间的基本单位。
2. 指定和修改⾏格式的语法如下:
CREATE TABLE 表名 (列的信息) ROW_FORMAT=⾏格式名称
ALTER TABLE 表名 ROW_FORMAT=⾏格式名称
3. InnoDB⽬前定义了4种⾏格式
* COMPACT⾏格式
*REDUNDANT
*DYNAMIC
* COMPRESSED
1. InnoDB为了不同的⽬的⽽设计了不同类型的⻚,我们把⽤于存放记录的⻚叫做数据⻚。
2. ⼀个数据⻚可以被⼤致划分为7个部分,分别是
File Header,表示⻚的⼀些通⽤信息,占固定的38字节。
Page Header,表示数据⻚专有的⼀些信息,占固定的56个字节。
Infimum + Supremum,两个虚拟的伪记录,分别表示⻚中的最⼩和最⼤记录,占固定的26个字节。
User Records:真实存储我们插⼊的记录的部分,⼤⼩不固定。
Free Space:⻚中尚未使⽤的部分,⼤⼩不确定。
Page Directory:⻚中的某些记录相对位置,也就是各个槽在⻚⾯中的地址偏移量,⼤⼩不固定,插⼊的记录越多,这个部分占⽤的空间越多。
File Trailer:⽤于检验⻚是否完整的部分,占⽤固定的8个字节。
3. 每个记录的头信息中都有⼀个next_record属性,从⽽使⻚中的所有记录串联成⼀个单链表
4. InnoDB会为把⻚中的记录划分为若⼲个组,每个组的最后⼀个记录的地址偏移量作为⼀个槽,存放在Page Directory中,所以在⼀个⻚中根据主键查找记录是⾮常快的,分为两步:
通过⼆分法确定该记录所在的槽。
通过记录的next_record属性遍历该槽所在的组中的各个记录。
5. 每个数据⻚的File Header部分都有上⼀个和下⼀个⻚的编号,所以所有的数据⻚会组成⼀个双链表。
6. 为保证从内存中同步到磁盘的⻚的完整性,在⻚的⾸部和尾部都会存储⻚中数据的校验和和⻚⾯最后修改时对应的LSN值,如果⾸部和尾部的校验和和LSN值校验不成功的话,就说明同步过程出现了问题。
?php下加一个mysql_connect("localhost","mysql用户","mysql密码")
mysql_select_db("数据库名")
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)