Posts Tagged: MySQL


3
九 08

LAMP架构中的关键瓶颈在哪里

以下为引用:

我的想法源起于这样一个事情,有一次一个网站的技术总监问我,为什么他们的网站那么慢,要怎么办。当时,我的MSN里Zend总部的工程师正好在线,我就 问他PHP响应比较慢了,怎么办?他当时直接告诉我,数据库问题!肯定是数据库没有优化设计好。所以,我没有给那个技术总监确切的答案了,因为他们的数据 库设计我们是不能涉及的。所以就给了大概的数据库优化的建议。这样的事情屡次发生,我就开始怀疑,为什么Zend总部的工程师每次都跟我 说是数据库的问题呢,难道我们不能从PHP层面来解决这个问题吗?答案是不能!因为PHP目前的运行速度已经是很快了,通过Zend的性能分析也能看到一 个用户的点击,PHP的运行时间只有10%不到,那PHP在干吗?它在等。等数据库的查询结果。这个方面在目前的PHP产品中有了很大 的提高,那就是Caching和网页静态化两个方案。Caching可能大家会比较陌生,但是网也静态化现在连PHP产品的用户都非常清楚了。速度快、容 易被搜索到等等,好处不言而喻。开玩笑地说,现在网站的主页实现网页静态化只需要硬盘足够大。至于Caching就比较复杂些,也是大多数PHPer感到 头疼的地方。甚至于有些人会用C来实现。因为Caching中的数据有效期验证、查找、提取、更新等等都是比较难处理。当然,也有人会用数据库来处理 Caching问题。


28
五 08

MySQL Slave实现同步关键步骤之一

CHANGE MASTER TO
MASTER_HOST=’192.168.1.124′,
MASTER_USER=’replicuser’,
MASTER_PASSWORD=’***********’,
MASTER_PORT=3307,
MASTER_LOG_FILE=’mysql-bin.000094′;

start slave;

show slave status\G

 


13
五 08

使用MySQL的计划任务

原先,LAMP的程序员为了完成一些周期性的数据库操作任务,总是不得不借助于操作系统的帮助,比如Windows的计划任务,或者Linux的contab。MySQL5.1终于新增了Event Scheduler功能,可以直接在后台实现一下定时性的作业。但不知道什么原因,在英文版的参考手册中,位于触发器和视图之间的第20章Event Scheduler,在中文版中被删减掉了,手册的其他部分也没有丝毫提到它,好像它根本就不存在一样,所以它的知名度不是很高。有兴趣的读者可以参考http://dev.mysql.com/doc/refman/5.1/en/events.html获得比较完整的帮助。

1.1 开启
     MySQL的Event Scheduler是根据预先安排的计划进行数据库操作的数据库对象,可以看作是一种“时间触发器”。Event实际上是被一个特殊的event scheduler线程执行的,假如它正在运行的话,可以通过SHOW PROCESSLIST命令看到它。全局变量event_scheduler用来设定是否服务器端运行执行计划任务,该变量有如下三种值:
      OFF:计划任务处于停止状态,event scheduler线程没有运行。是event_scheduler的默认值;
      ON:计划任务处于运行状态,event scheduler线程启动,并执行所有的计划任务;
      DISABLED:该值将致使计划任务不可运行
     你可以使用下列的任意一句开启计划任务:
           SET GLOBAL event_scheduler = ON;
           SET @@global.event_scheduler = ON;
           SET GLOBAL event_scheduler = 1;
           SET @@global.event_scheduler = 1;

1.2 创建
     Event Scheduler作为一种数据库对象,其增删改的DDL语句与其他对象非常相似,无非CREATE、ALTER、DROP等,创建的基本语法是:
          CREATE EVENT        (1)
          [IF NOT EXISTS]        (2)
          event_name         (3)
          ON SCHEDULE schedule      (4)
          [ON COMPLETION [NOT] PRESERVE]   (5)
          [ENABLE | DISABLE]       (6)
          [COMMENT 'comment']       (7)
          DO sql_statement        (8)
     逐条介绍:
     (1) 创建Event嘛,这俩关键字当然不能少了
     (2) 如果不存在同名的数据库对象才创建
     (3) 计划任务的名字。作为数据库对象,都有一个本库内唯一的名字做标识
     (4) 计划任务的计划,重点就在这儿。有两个关键字来设定任务的执行计划:AT和EVERY:
          AT指定的是一个一次性计划,后面跟着一个时间戳,后续的sql语句将在指定的时间被执行一次;
          EVERY指定的是一个周期性计划,在该子句中可以指定从某时间点到某时间点期间,每隔某周期就执行一次该任务。
     (5) 任务整个执行完毕后,该计划任务对象是否还在数据库中保留。默认不保留
     (6) 有效或失效。默认有效
     (7) 真正要执行的语句

1.3 实例
      首先是一个一次性计划任务的例子,该任务在指定的2008-02-06 23:59:00这个时间点,向messages表中插入一条记录:
          CREATE EVENT e_totals
          ON SCHEDULE AT ’2006-02-10 23:59:00′
          DO
          INSERT INTO messages VALUES (null, ‘admin’, ‘过年了!’, ‘祝大家鼠年发大财!!!’, ’127.0.0.1′,NOW());
      下面是一个周期性计划任务的例子,该任务在2008-02-06 23:59:00开始的一年内,每隔1小时就删除掉messages表的早先的10条记录:
          CREATE EVENT e_hourly
          ON SCHEDULE
          EVERY 1 HOUR STARTS ’2007-02-10 23:59:00′ ENDS ’2008-02-10 23:59:00′
          DO
          DELETE FROM messages limit 10;

     计划任务属于数据库服务器端的对象,创建好后,只要开启了event_scheduler,就可以自动触发执行了,不用在前台进行任何干预。当然一定要记住,只有MySQL5.1以上版本才支持该对象。
 


21
三 08

MySQL密码恢复

MySQL忘记root密码后,怎么办?

在/etc/my.cnf的[mysqld]段里添加如下一行:

skip-grant-tables

然后restart MySQL服务,这时即可不用密码登录MySQL了,以root登录MySQL,并重新设置root的密码。

注意:使用skip-grant-tables启动MySQL时,任何数据连接都不再被认证,所以,此时,MySQL是极不安全的,建议使用skip-grant-tables时,同时使用skip-networking参数,禁用通过网络连接数据库。


20
二 08

header() & drbd

PHP中使用header生成301转向:
header(‘HTTP/1.1 301 Moved Permanently’); // 301头
header(“Location: /logs/”.$post_id.”.html#tb”);  

http://www.drbd.org
DRBD用于MySQL数据库的HA
http://www.builder.com.cn/2007/0726/437357.shtml
lisqklpioreiu.png


20
二 08

header() & drbd

PHP中使用header生成301转向:
header(‘HTTP/1.1 301 Moved Permanently’); // 301头
header(“Location: /logs/”.$post_id.”.html#tb”);  

http://www.drbd.org
DRBD用于MySQL数据库的HA
http://www.builder.com.cn/2007/0726/437357.shtml
lisqklpioreiu.png


6
十二 07

MySql数据库的字段类型

MySQL数据库的表是一个二维表,由一个或多个数据列构成。
每个数据列都有它的特定类型,该类型决定了MySQL如何看待该列数据,我们可以把整型数值存放到字符类型的列中,MySQL则会把它看成字符串来处理。
MySQL中的列类型有三种:数值类、字符串类和日期/时间类。
从大类来看列类型和数值类型一样,都是只有三种。但每种列类型都还可细分。
下面对各种列类型进行详细介绍。

数值类的数据列类型
数值型的列类型包括整型和浮点型两大类。

TINYINT:1字节 非常小的正整数,带符号:-128~127,不带符号:0~255
SMALLINT:2字节 小整数,带符号:-32768~32767,不带符号:0~65535
MEDIUMINT:3字节 中等大小的整数,带符号:-8388608~8388607,不带符号:0~16777215
INT:4字节 标准整数,带符号:-2147483648~2147483647,不带符号:0~4294967295
BIGINT:8字节 大整数,带符号:-9223372036854775808~9233372036854775807,不带符号:0~18446744073709551615
FLOAT:4字节 单精度浮点数,最小非零值:+-1.175494351E-38,最大非零值:+-3.402823466E+38
DOUBLE:8字节 双精度浮点数,最小非零值:+-2.2250738585072014E-308,最大非零值:+-1.7976931348623157E+308
DECIMAL:M+2字节 以字符串形式表示的浮点数,它的取值范围可变,由M和D的值决定。

整型数据列类型

MySQL有五种整型数据列类型,即TINYINT,SMALLINT,MEDIUMINT,INT和BIGINT。它们之间的区别是取值范围不同,存储空间也各不相同。
在整型数据列后加上UNSIGNED属性可以禁止负数,取值从0开始。

声明整型数据列时,我们可以为它指定个显示宽度M(1~255),如INT(5),指定显示宽度为5个字符,如果没有给它指定显示宽度,MySQL会为它指定一个默认值。显示宽度只用于显示,并不能限制取值范围和占用空间,如:INT(3)会占用4个字节的存储空间,并且允许的最大值也不会是999,而是 INT整型所允许的最大值。

浮点型数据列类型

MySQL有三种浮点型数据列类型,分别是:FLOAT,DOUBLE和DECIMAL。
浮点类数据类型有一个最大可表示值和一个最小非零可表示值,最小非零可表示值决定了该类型的精确度。

MySQL 4.0.2版之后,FLOAT和DOUBLE都可以指定UNSIGNED属性。当指定该属性时,取值范围不平移到正数区间,而只是简单地把浮点类型的负数部份去掉。

浮点类型也有M(1~255)和D(1~30,且不能大于M-2)。分别表示显示宽度和小数位数。M和D在FLOAT和DOUBLE中是可选的,默认,当 MySQL版本大于3.23.6时,FLOAT和DOUBLE类型将被保存为硬件所支持的最大精度。DECIMAL的M和D值在MySQL3.23.6后可选,默认D值为0,M值为10。

如何选择数值类数据列类型?

为了节省存储空间和提高数据库处理效率,我们应根据应用数据的取值范围来选择一个最适合的数据列类型。如果把一个超出数据列取值范围的数存入该列,则 MySQL就会截短该值,如:我们把99999存入SMALLINT(3)数据列里,因为SMALLINT(3)的取值范围是-32768~32767,所以就会被截短成32767存储。显示宽度3不会影响数值的存储。只影响显示。

对于浮点数据列,存入的数值会被该列定义的小数位进行四舍五入。如把一个1.234存入FLOAT(6.1)数据列中,结果是1.2。

DECIMAL与FLOAT和DOUBLE的区别是:DECIMAL类型的值是以字符串的形式被储存起来的,它的小数位数是固定的。它的优点是,不会象 FLOAT和DOUBLE类型数据列那样进行四舍五入而产生误差,所以很适合用于财务计算;而它的缺点是:由于它的存储格式不同,CPU不能对它进行直接运算,从而影响运算效率。DECIMAL(M,D)总共要占用M+2个字节。

数值类数据列的属性

ZEROFILL属性适用于所有数值类数据列类型,作用是,如果数值的宽度小于定义的显示宽度,则在数值前填充0。
UNSIGNED属性不允许数据列出现负数。
AUTO_INCREMENT属性可生成独一无二的数字序列。只对整数类的数据列有效。
NULL和NOT NULL属性设置数据列是否可为空。
DEFAULT属性可为数据列指定默认值。

//////////////////////////////////////////////////////

字符串类数据列类型

字符串可以用来表示任何一种值,所以它是最基本的类型之一。
我们可以用字符串类型来存储图象或声音之类的二进制数据,也可存储用gzip压缩的数据。
下表介绍了各种字符串类型:

CHAR[(M)] M字节 M字节
VARCHAR[(M)] M字节 L+1字节
TINYBLOD,TINYTEXT 2^8-1字节 L+1字节
BLOB,TEXT 2^16-1字节 L+2
MEDIUMBLOB,MEDIUMTEXT 2^24-1字节 L+3
LONGBLOB,LONGTEXT 2^32-1字节 L+4
ENUM(‘value1′,’value2′,…) 65535个成员 1或2字节
SET(‘value1′,’value2′,…) 64个成员 1,2,3,4或8字节

L+1、L+2是表示数据列是可变长度的,它占用的空间会根据数据行的增减面则改变。数据行的总长度取决于存放在这些数据列里的数据值的长度。L+1或L +2里多出来的字节是用来保存数据值的长度的。在对长度可变的数据进行处理时,MySQL要把数据内容和数据长度都保存起来。

如果把超出字符串最大长度的数据放到字符类数据列中,MySQL会自动进行截短处理。

ENUM和SET类型的数据列定义里有一个列表,列表里的元素就是该数据列的合法取值。如果试图把一个没有在列表里的值放到数据列里,它会被转换为空字符串(“”)。

字符串类型的值被保存为一组连续的字节序列,并会根据它们容纳的是二进制字符串还是非二进制字符而被区别对待为字节或者字符:

二进制字符串被视为一个连续的字节序列,与字符集无关。MySQL把BLOB数据列和带BINARY属性的CHAR和VARCHAR数据列里的数据当作二进制值。

非二进制字符串被视为一个连续排列的字符序列。与字符集有关。MySQL把TEXT列与不带BINARY属性的CHAR和VARCHAR数据列里的数据当作二进制值对待。

在MySQL4.1以后的版本中,不同的数据列可以使用不同的字符集。在MySQL4.1版本以前,MySQL用服务器的字符集作为默认字符集。

非二进制字符串,即我们通常所说的字符串,是按字符在字符集中先后次序进行比较和排序的。而二进制字符串因为与字符集无关,所以不以字符顺序排序,而是以字节的二进制值作为比较和排序的依据。下面介绍两种字符串的比较方式:

二进制字符串的比较方式是一个字节一个字节进行的,比较的依据是两个字节的二进制值。也就是说它是区分大小写的,因为同一个字母的大小写的数值编码是不一样的。

非二进制字符串的比较方式是一个字符一个字符进行的,比较的依据是两个字符在字符集中的先后顺序。在大多数字符集中,同一个字母的大小写往往有着相同的先后顺序,所以它不区分大小写。

二进制字符串与字符集无关,所以无论按字符计算还是按字节计算,二进制字符串的长度都是一样的。所以VARCHAR(20)并不表示它最多能容纳20个字符,而是表示它最多只能容纳可以用20个字节表示出来的字符。对于单字节字符集,每个字符只占用一个字节,所以这两者的长度是一样的,但对于多字节字符集,它能容纳的字符个数肯定少于20个。

CHAR和VARCHAR

CHAR和VARCHAR是最常用的两种字符串类型,它们之间的区别是:

CHAR是固定长度的,每个值占用相同的字节,不够的位数MySQL会在它的右边用空格字符补足。

VARCHAR是一种可变长度的类型,每个值占用其刚好的字节数再加上一个用来记录其长度的字节即L+1字节。

CHAR(0)和VARCHAR(0)都是合法的。VARCHAR(0)是从MySQL4.0.2版开始的。它们的作用是作为占位符或用来表示各种on/off开关值。

如何选择CHAR和VARCHAR,这里给出两个原则:

如果数据都有相同的长度,选用VARCHAR会多占用空间,因为有一位用来存储其长度。如果数据长短不一,选用VARCHAR能节省存储空间。而CHAR不论字符长短都需占用相同的空间,即使是空值也不例外。

如果长度出入不大,而且是使用MyISAM或ISAM类型的表,则用CHAR会比VARCHAR好,因为MyISAM和ISAM类型的表对处理固定长度的行的效率高。

在一个数据表里,只要有一个数据列的长度是可变的,则所有数据列的长度将是可变的。MySQL会进行自动地转换。一个例外,CHAR长度小于4的不会进行自动转换,因为MySQL会认为这样做没必要,节省不了多少空间。反而MySQL会把大量长度小的VARCHAR转换成CHAR,以减少空间占用量。

BLOB和TEXT

BLOB是二进制字符串,TEXT是非二进制字符串。两者都可存放大容量的信息。

有关BLOB和TEXT索引的建立:

BDB表类型和MySQL3.23.2以上版本的MyISAM表类型允许在BLOB和TEXT数据列上建立索引。

ISAM、HEAP和InnoDB表不支持大对象列的索引。

使用BLOB和TEXT应注意的问题:

由于这两个列类型所存储的数据量大,所以删除和修改操作容易在数据表里产生大量的碎片,需定期运行OPTIMIZE TABLE以减少碎片和提高性能。

如果使用的值非常巨大,就需对服务器进行相应的优化调整,增加max_allowed_packet参数的值。对那些可会用到变些巨大数据的客户程序,也需加大它们的数据包大小。

ENUM和SET

ENUM和SET都是比较特殊的字符串数据列类型,它们的取值范围是一个预先定义好的列表。ENUM或SET数据列的取值只能从这个列表中进行选择。ENUM和SET的主要区别是:

ENUM只能取单值,它的数据列表是一个枚举集合。它的合法取值列表最多允许有65535个成员。例如:ENUM(“N”,”Y”)表示,该数据列的取值要么是”Y”,要么就是”N”。

SET可取多值。它的合法取值列表最多允许有64个成员。空字符串也是一个合法的SET值。

ENUM和SET的值是以字符串形式出现的,但在内部,MySQL以数值的形式存储它们。

ENUM的合法取值列表中的字符串被按声明定义的顺序被编号,从1开始。

SET的编号不是按顺序进行编号的,SET中每一个合法取值都对应着SET值里的一个位。第一个合法取值对应0位,第二个合法取值对应1位,以此类推,如果数值形式的SET值等于0,则说明它是一个空字符串,如果某个合法的取值出现在SET数据列里,与之对应的位就会被置位;如果某个合法的取值没有出现在 SET数据列里,与之对应的位就会被清零。正因为SET值与位有这样的对应关系,所以SET数据列的多个合法取值才能同时出现并构成SET值。

字符串类型数据列的字符集属性

在MySQL 4.1以前的版本,字符串数据列的字符集由服务器的字符决定,MySQL 4.1版以后的版本可对每个字符串数据列指定不同的字符串。如果按默认方式设置,可按数据列、数据表、数据库、服务器的顺序关联字符串的字符集,直到找一个明确定义的字符集。

/////////////////////////////////////////////////////////

日期,时间型数据列类型

DATE 1000-01-01~9999-12-31 3字节(MySQL3.23版以前是4字节 ) 0000-00-00
TIME -838:59:59~838:59:59 3字节 00:00:00
DATETIME 1000-01-01 00:00:00~9999-12-31 23:59:59 8字节 0000-00-00 00:00:00
TIMESTAMP 19700101000000~2037年的某个时刻 4字节 00000000000000
YEAR YEAR(4):1901~2155 YEAR(2):1970~2069 1字节 0000

MySQL总是把日期和日期里的年份放在最前面,按年月日的顺序显示。

DATE、TIME、DATATIME数据列类型

DATE、TIME和DATATIME类型分别存放日期值、时间值、日期和时间值的组合。它们的格式分别是“CCYY-MM-DD”、“hh:mm:ss”、“CCYY-MM-DD hh:mm:ss”。

DATATIME里的时间值和TIME值是有区别的,DATATIME里的时间值代表的是几点几分,TIME值代表的是所花费的时间。当向TIME数据列插值时,需用时间的完整写法,如12分30秒要写成“00:12:30”。

TIMESTAMP数据列类型

TIMESTAMP数据列的格式是CCYYMMDDhhmmss,取值范围从19700101000000开始,即1970年1月1号,最大到2037年。它的特点是能把数据行的创建或修改时间记录下来:

如果把一个NULL值插入TIMESTAMP列,这个数据列就将自动取值为当前的日期和时间。

在创建和修改数据行时,如果没有明确对TIMESTAMP数据列进行赋值,则它就会自动取值为当前的日期和时间。如果行中有多个TIMESTAMP列,只有第一个会自动取值。

如果对TIMESTAMP设置一个确定的日期和时间值,则会使TIMESTAMP的自动取值功能失效。

TIMESTAMP默认的列宽是14,可指定列宽,以改变显示效果。但不论你指定的列宽如何,MySQL都是以4字节来存储TIMESTAMP值,也总是以14位精度来计算。

如果需要把创建时间和最近一次修改时间同时记录下来,可以用两个时间戳来记录,一个记录创建时间,一个记录修改时间。不过需记住两件事,一是要把记录修改时间的TIMESTAMP数据列放在最前面,这样才会自动取值;二是创建一条新记录时,要用now()函数来初始化创建时间TIMESTAMP数据列,这样,该TIMESTAMP数据列就不会再变化。

YEAR

YEAR是一种单字节的数据列类型,YEAR(4)的取值范围是1901~2155,YEAR(2)的取值范围是1970~2069,但只显示最后两位数。MySQL能自动把两位数字年份转换成四位数字的年份,如97和14分被转换成1997和2014。转换规则是这样的:

年份值00~69将被转换成2000~2069;

年份值70~99将被转换成1970~1999。

00被转换成0000,而不是2000。因为数值00也就是0,而0值是YEAR的一个合法取值。


26
十一 07

将InnoDB的表格式转换为MyISAM格式

ALTER TABLE `tablename` ENGINE = MYISAM


25
十一 07

MySQL Proxy

据说MySQL Proxy可以用来实现MySQL负载均衡和读写分开。

http://dev.mysql.com/downloads/mysql-proxy/

http://forge.mysql.com/wiki/MySQL_Proxy


22
十一 07

编译mysql-5.0.45,支持大表,线程库支持

BASH环境:

export LDFLAGS=’-s’
./configure -q –prefix=/usr/local/mysql-5.0.45 –enable-assembler –with-charset=utf8 –with-collation=utf8_general_ci  –with-pthread  –with-embedded-server –with-mysqlmanager –with-big-tables
make -s -j4


29
七 05

使用myisamchk进行崩溃恢复

 13.4 使用myisamchk进行崩溃恢复 
 2004-02-12 MySQL 译者:晏子 http://www.mysql.com/doc.html
  
由MySQL用来存储数据的文件格式以已经被广泛地测试过,但是总是有外部情况可以导致数据库表被破坏:

mysqld进程在一个写入当中被杀死。
计算机的意外关闭(例如,如果计算机掉电)。
一个硬件错误

这章描述如何检查和处理在MySQL数据库中的数据损坏。如果你的表损坏很多,你应该尝试找出其原因!见G.1 调试一个MySQL服务器。

在执行崩溃恢复时,理解在一个数据库中的每一个表tbl_name对应的在数据库目录中的3个文件是很重要的:

文件 用途

“tbl_name.frm” 表定义(表格)文件
“tbl_name.MYD” 数据文件
“tbl_name.MYI” 索引文件

这3个文件的每一个文件类型可能遭受不同形式的损坏,但是问题最常发生在数据文件和索引文件。

myisamchk通过一行一行地创建一个“.MYD”(数据 )文件的副本来工作,它通过由删除老的“.MYD 文件并且重命名新文件到原来的文件名结束修复阶段。如果你使用–quick,myisamchk不创建一个临时“.MYD”文件,只是假定“.MYD”文件是正确的并且仅创建一个新的索引文件,不接触“.MYD”文件,这是安全的,因为myisamchk自动检测“.MYD”文件是否损坏并且在这种情况下,放弃修复。你也可以给myisamchk两个–quick选项。在这种情况下,myisamchk不会在一些错误上(象重复键)放弃,相反试图通过修改“.MYD”文件解决它们。通常,只有在你在太少的空闲磁盘空间上实施一个正常修复,使用两个–quick选项才有用。在这种情况下,你应该至少在运行myisamchk前做一个备份。

13.4.1 怎样检查表的错误

为了检查一张表,使用下列命令:

myisamchk tbl_name

这能找出所有错误的99.99%。它不能找出的是仅仅涉及数据文件的损坏(这很不常见)。如果你想要检查一张表,你通常应该没有选项地运行myisamchk或用-s或–silent选项的任何一个。

myisamchk -e tbl_name

它做一个完全彻底的数据检查(-e意思是“扩展检查”)。它对每一行做每个键的读检查以证实他们确实指向正确的行。这在一个有很多键的大表上可能花很长时间。myisamchk通常将在它发现第一个错误以后停止。如果你想要获得更多的信息,你能增加–verbose(-v)选项。这使得myisamchk继续一直到最多20个错误。在一般使用中,一个简单的myisamchk(没有除表名以外的参数)就足够了。

myisamchk -e -i tbl_name

象前面的命令一样,但是-i选项告诉myisamchk还打印出一些统计信息。

13.4.2 怎样修复表

一张损坏的表的症状通常是查询意外中断并且你能看到例如这些错误:

“tbl_name.frm”被锁定不能改变。
不能找到文件“tbl_name.MYI”(Errcode :### )。
从表处理器的得到错误###(此时,错误135是一个例外)。
意外的文件结束。
记录文件被毁坏。
在这些情况下,你必须修复表。myisamchk通常能检测并且修复出错的大部分东西。

修复过程包含最多4个阶段,在下面描述。在你开始前,你应该cd到数据库目录和检查表文件的权限,确保他们可被运行mysqld的Unix用户读取(和你,因为你需要存取你正在检查的文件)。如果它拒绝你修改文件,他们也必须是可被你写入的。

阶段1:检查你的表

运行myisamchk *.MYI或(myisamchk -e *.MYI,如果你有更多的时间)。使用-s(沉默)选项禁止不必要的信息。

你必须只修复那些myisamchk报告有一个错误的表。对这样的表,继续到阶段2。

如果在检查时,你得到奇怪的错误(例如out of memory错误),或如果myisamchk崩溃,到阶段3。

阶段 2 :简单安全的修复

首先,试试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> DELETE FROM tbl_name;
mysql> quit

将老的数据文件拷贝到新创建的数据文件之中。(不要只是将老文件移回新文件之中;你要保留一个副本以防某些东西出错。)

回到阶段2。现在myisamchk -r -q应该工作了。(这不应该是一个无限循环)。

阶段4:非常困难的修复

只有描述文件也破坏了,你才应该到达这个阶段。这应该从未发生过,因为在表被创建以后,描述文件就不再改变了。

从一个备份恢复描述文件并且回到阶段3。你也可以恢复索引文件并且回到阶段2。对后者,你应该用myisamchk -r启动。

如果你没有一个备份但是确切地知道表是怎样被创建的,在另一个数据库中创建表的一个拷贝。删除新的数据文件,然后从其他数据库将描述和索引文件移到破坏的数据库中。这给了你新的描述和索引文件,但是让数据文件独自留下来了。回到阶段2并且尝试重建索引文件。

13.4.3 表优化

为了组合成碎片的记录并且消除由于删除或更新记录而浪费的空间, 以恢复模式运行myisamchk:

shell> myisamchk -r tbl_name

你可以用SQL的OPTIMIZE TABLE语句使用的相同方式来优化一张表,OPTIMIZE TABLE比较容易,但是myisamchk更快。也没有在一个实用程序和服务器之间不必要的交互可能性,因为当你使用OPTIMIZE TABLE时,服务器做所有的工作。

myisamchk也有你可用来改进一个表的性能的很多其他选项:

-S, –sort-index
-R index_num, –sort-records=index_num
-a, –analyze

对于选项完整的描述见13.1.1 myisamchk调用语法。