Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2566997
  • 博文数量: 709
  • 博客积分: 12251
  • 博客等级: 上将
  • 技术积分: 7905
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-17 00:00
个人简介

实现有价值的IT服务

文章存档

2012年(7)

2011年(147)

2009年(3)

2008年(5)

2007年(74)

2006年(431)

2005年(42)

分类: Mysql/postgreSQL

2006-06-28 17:32:38

适用版本: 所有版本 \A/I7Zp^B|  
所属类别: 数据库相关 6x '^i  
关键字: MyISAM表 尺寸 限制 文件系统 fdEe)D!  
近日,一位Discuz!老用户的论坛在发表回复时出现“The table is full”的提示,字面意义上是数据表已满的意思。因为很少有开发者遭遇单一表超过4G的情况,因此朋友间的讨论只能提供一些外围的信息。为解决此问题,我翻阅了很多资料,本文将以我此次问题的解决过程,介绍问题发生的原因及对策。 &,9/&h0  
根据经验,The table is full提示往往出现在以下两种情况: [!|1S0F  
1. 表中设置了MAX_ROWS值,简单的说,若MAX_ROWS设置为100,而程序试图写入第101条记录,会出现此错误。 PU8`!.`@  
2. 表满。这种情况是本文讨论的重点。 +Gu2D7H):  
F?^8N K  
我们认为MySQL在存取表的时候,存在一种定位分配规律。这个规律在默认的情况下,可以寻址4G以内的数据。超过这个大小,数据库将不能对数据定位,因而也无法进行读写。经过实验,这个限制是完全可以被突破的。 WWLZS:_  
本例中,用户的系统环境为双Athlon处理器、SCSI硬盘72G、2G内存,用户的帖子表数据尺寸为4294963640,接近4G(4G的实际字节数为4294967296)。 ] s4{LDT  
JG6' -w  
首先SSH登录后,查看用户的系统信息: ;k=dL0dc  
z,V1KWZ  
# uname -a x!Map3}?  
Linux zichen.com 2.4.20-8smp #1 SMP Thu Mar 13 16:43:01 EST 2003 i686 athlon i386 GNU/Linux GV| Qv_G  
1F44|+5i  
证明是Linux系统,根据内核版本2.4.20-8smp,加上国内使用的常见系统,估计应该是redhat 9发行包。 |x(Weeb  
[ynUk,99Y  
# cat /etc/*release* aqb.\((%  
Red Hat Linux release 9 (Shrike) "*1F} rT-  
~+IvT^7/N  
这也证明了我们对系统版本的猜想。 f7}my4V-  
ca;_P+P6@9  
然后看一下用的是什么文件系统。因为该用户并非高手,估计在装系统的时候就是一路回车下来,redhat 9默认的应该是EXT3,不过我们还是看一下: tf- {m71  
nN 3nd   
# parted cUZNFGgc!  
GNU Parted 1.6.3 > U>c>I%  
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 3&og5]X  
This program is free software, covered by the GNU General Public License. R 7.~f  
C{-b|Q1  
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of eq}>ADUn  
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ! Qho|6  
t,]\%HX  
Using /dev/sda fVP)o 2:  
Information: The operating system thinks the geometry on /dev/sda is 8942/255/63. Therefore, cylinder 1024 ends at 8032.499M. vX/U} #=  
(parted) print 6cX%ESx9  
Disk geometry for /dev/sda: 0.000-70149.507 megabytes \GU~%*7KS:  
Disk label type: msdos ~WQv!O; R  
Minor Start End Type Filesystem Flags r(Bpww(B;  
1 0.031 101.975 primary ext3 boot 1P_U\k7a  
2 101.975 10103.378 primary linux-swap ]p.Mv7o2  
Ev"HR^^Z  
证明确实是这样子。随后我们翻阅了EXT3文件系统的相关技术参数,EXT3是在EXT2基础上演变而来。EXT2所支持最大单一文件长度是2G,这个是很蹩脚的一个限制。EXT3做的很大一个改善就是将这个限制放大到了2TB,由此稍松一口气,起码不是操作系统上的限制。 Q n %5G  
*n!C:4w  
经过朋友的开导,了解到单一文件大小有如下几个因素: 8^"6~ 0V  
1. 文件系统的限制(如刚存所说EXT3的2TB限制) GH*4zk{  
2. 某一程序进程所能存取的第一文件最大尺寸(例如apache在Linux EXT3下能存取的最大尺寸为2G,诸如日志) 8B {!n  
"o J}?@  
初步判断瓶颈就在上述其中第二项。随后找到myisamchk来显示一下表信息,证明了瓶颈就在MySQL本身的存取上。 Zi 
VkQGp)P  
# myisamchk -dv cdb_posts gQR"-Gm%p  
'Jl^I-u}  
结果就不贴了,其中有一项Max datafile length的值恰好就是4G。由此产生了瓶颈。 $z68vo3.E6  
后来翻阅了N多资料,进行了N多尝试,也走了不少弯路,最终觉得还是官方文档比较可靠。比较老的文档里写道这是由于tmp_table_size的值造成的,也有提到用BIG-TABLES这个参数。事实证明这些都是歧途。大晚上的确实很累,这里只给出最终的解决方案吧,中间的就不罗嗦了。 8mFD  
E][TVLNYu  
进到mysql客户端。 k a4te<-n  
# mysql -uroot -p fhX$uaS  
Enter password: ****** f2bHN$85  
Welcome to the MySQL monitor. Commands end with ; or \g. drlX!#JO:  
Your MySQL connection id is 59411 to server version: 4.0.18-standard 2II~T6v  
y?uJRIuB  
Type 'help;' or '\h' for help. Type '\c' to clear the buffer. *;X;>u/V0F  
iT=)?*:itP  
mysql> use ****** 66[(@6M:  
Database changed swmWBl  
mysql> ALTER TABLE cdb_posts MAX_ROWS=1000000000 AVG_ROW_LENGTH=15000; h-4Pnz]hG?  
RpO>"  
因为这个表非常大,执行时间在双Athlon的专业服务器上竟然花了30分钟! ]8J:H,Yh  
之后再通过myisamchk查看该表的信息: bM7=,in 
# myisamchk -dv cdb_posts ie;2#p#1  
MyISAM file: cdb_posts Af .C]V"j  
Record format: Packed kHd> L^2  
Character set: latin1 (8) P}c~Gwy  
File-version: 1 `V!!o]]  
Creation time: 2004-08-30 22:19:48 qw5JdD-  
Recover time: 2004-08-30 22:42:47 47b3yx9  
Status: open,changed j>!QDG@_4  
Auto increment key: 1 Last value: 1063143 z TW0|mJ  
Data records: 619904 Deleted blocks: 5 xA~`xb-1I  
Datafile parts: 619909 Deleted data: 323872 u bU\XQ;  
Datafile pointer (bytes): 6 Keyfile pointer (bytes): 4 $/lI$q Z  
Datafile length: 4295287332 Keyfile length: 40421376 s V^Z5  
Max datafile length: 281474976710654 Max keyfile length: 4398046510079 }vY qx  
Recordlength: 149 Iu'Jzd1  
iic 6CQc-  
table description: oud4@"jz  
Key Start Len Index Type Rec/key Root Blocksize 'gUUqh=  
1 1 4 unique unsigned long 1 4535296 1024 e^&@x]z#a  
2 5 2 multip. unsigned short 13776 12540928 1024 3f$Bz~X~  
3 111 4 multip. unsigned long 1 18854912 1024 3rkL  
4 28 3 multip. uint24 18 24546304 1024 ui;]pH  
5 7 3 multip. uint24 7 32827392 1024 _hu#}Q4  
111 4 unsigned long 1 7 kk P(  
6 7 3 multip. uint24 7 40418304 1024 _ Hlxt  
28 3 uint24 dR*E%xr)?  
R6wXni*  
令人振奋的事情发生了,该表的 Max datafile length: 281474976710654 Max keyfile length: 4398046510079,即最大数据尺寸(MYD文件)达到了2TB,最大索引尺寸(MYI)仍然为4G。 uQg6-GJ  
由此默认的4G限制被突破了。关于其中的原理,其实很简单:假设你有一个日记本,上面有10页纸可以写东西,编排目录只需要1个字节(因为0~9就够了)。如果你把这本子又塞进两张纸,变成12页,1个字节的目录空间就无法寻址到后面的两页中,进而产生了错误。上面那个ALTER语句中的数值都是我为保证成功,取的比较大的值(因为ALTER一次实在是太慢了,没时间在那乱试验),相当于告诉数据库,这个本子有1000000000页,每页平均有15000个字节。这样数据库便知道这是很大的一个本子,因此不遗余力的拿出了100页(假设说)做目录编排,这样这个新的目录就可以寻址到日记本的所有内容了。错误消失。 {q6G=qy6Q  
QVsm=*N  
惟一的缺点就是,目录占用的空间多了一些,但已经微乎其微了,做了这种改变其实4G的文件尺寸大小只增大了1M多,非常令人振奋。 1!W`~%x'  
%%#P]./Qr  
阅读(3060) | 评论(1) | 转发(0) |
0

上一篇:MySQL語言參考

下一篇:mysql常用经典操作

给主人留下些什么吧!~~