再见西城 发表于 2015-1-16 20:13:15

绝无经由的MySQL数据库单一表冲破4G限定的完成办法

业界普遍的声音认为:“MySQL是一个可靠的数据库系统,MySQL学习教程无论是在嵌入式或大型群集系统的部署中,还是在基于Web的应用程序领域。成绩:在论坛宣布复兴时呈现“Thetableisfull”的提醒,字面意义上是数据表已满的意义。由于很少有开辟者遭受单一表凌驾4G的情形,因而伴侣间的会商只能供应一些核心的信息。为办理此成绩,我翻阅了良多材料,本文将以我此次成绩的办理历程,先容成绩产生的缘故原由及对策。
依据履历,Thetableisfull提醒常常呈现在以下两种情形:
1.表中设置了MAX_ROWS值,复杂的说,若MAX_ROWS设置为100,而程序试图写进第101笔记录,会呈现此毛病。
2.表满。这类情形是本文会商的重点

我们以为MySQL在存取表的时分,存在一种定位分派纪律。这个纪律在默许的情形下,能够寻址4G之内的数据。凌驾这个巨细,数据库将不克不及对数据定位,因此也没法举行读写。经由实行,这个限定是完整能够被冲破的。
本例中,用户的体系情况为双Athlon处置器、SCSI硬盘72G、2G内存,用户的帖子表数据尺寸为4294963640,靠近4G(4G的实践字节数为4294967296)。

起首SSH登录后,检察用户的体系信息:

#uname-a
linuxzichen.com2.4.20-8smp#1SMPThuMar1316:43:01EST2003i686athloni386GNU/Linux

证实是Linux体系,依据内核版本2.4.20-8smp,加上国际利用的罕见体系,估量应当是redhat9刊行包。

#cat/etc/*release*
RedHatLinuxrelease9(Shrike)

这也证实了我们对体系版本的料想。

然后看一下用的是甚么文件体系。由于该用户并不是妙手,估量在装体系的时分就是一起回车上去,redhat9默许的应当是EXT3,不外我们仍是看一下:

#parted
GNUParted1.6.3
Copyright(C)1998,1999,2000,2001,2002FreeSoftwareFoundation,Inc.
ThisPRogramisfreesoftware,coveredbytheGNUGeneralPublicLicense.

Thisprogramisdistributedinthehopethatitwillbeuseful,butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.SeetheGNUGeneralPublicLicenseformoredetails.

Using/dev/sda
Information:TheOperatingsystemthinksthegeometryon/dev/sdais8942/255/63.Therefore,cylinder1024endsat8032.499M.
(parted)print
Diskgeometryfor/dev/sda:0.000-70149.507megabytes
Disklabeltype:msdos
MinorStartEndTypeFilesystemFlags
10.031101.975primaryext3boot
2101.97510103.378primarylinux-swap

证实的确是如许子。随后我们翻阅了EXT3文件体系的相干手艺参数,EXT3是在EXT2基本演出变而来。EXT2所撑持最年夜单一文件长度是2G,这个是很糟糕的一个限定。EXT3做的很年夜一个改良就是将这个限定缩小到了2TB,由此稍松一口吻,最少不是操纵体系上的限定。

经由伴侣的劝导,懂得到单一文件巨细有以下几个要素:
1.文件体系的限定(如刚存所说EXT3的2TB限定)
2.某一程序历程所能存取的第一文件最年夜尺寸(比方apache在LinuxEXT3下能存取的最年夜尺寸为2G,诸如日记)

开端判别瓶颈就在上述个中第二项。随后找到myisamchk来显现一下表信息,证实了瓶颈就在MySQL自己的存取上。

#myisamchk-dvcdb_posts

了局就不贴了,个中有一项Maxdatafilelength的值刚好就是4G。由此发生了瓶颈。
厥后翻阅了N多材料,举行了N多实验,也走了很多弯路,终极以为仍是官方文档对照牢靠。对照老的文档里写道这是因为tmp_table_size的值酿成的,也有提到用BIG-TABLES这个参数。现实证实这些都是邪路。年夜早晨切实其实实很累,这里只给出终极的办理计划吧,两头的就不罗嗦了。

进到mysql客户端。
#mysql-uroot-p
EnterpassWord:******
WelcometotheMySQLmonitor.Commandsendwith;org.
YourMySQLconnectionidis59411toserverversion:4.0.18-standard

Typehelp;orhforhelp.Typectoclearthebuffer.

mysql>use******
Databasechanged
mysql>ALTERTABLEcdb_postsMAX_ROWS=1000000000AVG_ROW_LENGTH=15000;

由于这个表十分年夜,实行工夫在双Athlon的专业服务器上居然花了30分钟!
以后再经由过程myisamchk检察该表的信息:
#myisamchk-dvcdb_posts
MyISAMfile:cdb_posts
Recordformat:Packed
Characterset:latin1(8)
File-version:1
Creationtime:2004-08-3022:19:48
Recovertime:2004-08-3022:42:47
Status:open,changed
Autoincrementkey:1Lastvalue:1063143
Datarecords:619904Deletedblocks:5
Datafileparts:619909Deleteddata:323872
Datafilepointer(bytes):6Keyfilepointer(bytes):4
Datafilelength:4295287332Keyfilelength:40421376
Maxdatafilelength:281474976710654Maxkeyfilelength:4398046510079
Recordlength:149

tabledescription:
KeyStartLenIndexTypeRec/keyRootBlocksize
114uniqueunsignedlong145352961024
252multip.unsignedshort13776125409281024
31114multip.unsignedlong1188549121024
4283multip.uint2418245463041024
573multip.uint247328273921024
1114unsignedlong1
673multip.uint247404183041024
283uint24

使人奋发的事变产生了,该表的Maxdatafilelength:281474976710654Maxkeyfilelength:4398046510079,即最年夜数据尺寸(MYD文件)到达了2TB,最年夜索引尺寸(MYI)仍旧为4G。
由此默许的4G限定被冲破了。关于个中的道理,实在很复杂:假定你有一个日志本,下面有10页纸能够写器材,编排目次只必要1个字节(由于0~9就够了)。假如你把这簿子又塞进两张纸,酿成12页,1个字节的目次空间就没法寻址到前面的两页中,进而发生了毛病。下面谁人ALTER语句中的数值都是我为包管乐成,取的对照年夜的值(由于ALTER一次其实是太慢了,没工夫在那乱实验),相称于告知数据库,这个簿子有1000000000页,每页均匀有15000个字节。如许数据库便晓得这是很年夜的一个簿子,因而尽心尽力的拿出了100页(假定说)做目次编排,如许这个新的目次就能够寻址到日志本的一切内容了。毛病消散。

唯一的弱点就是,目次占用的空间多了一些,但已微不足道了,做了这类改动实在4G的文件尺寸巨细只增年夜了1M多,十分使人奋发。
即使对于MySQL的商业化的企业版来说,也没有高昂的许可证成本,当你将其与像甲骨文和微软之类的大型专有商业数据库比较的话。

谁可相欹 发表于 2015-1-24 16:01:32

习惯敲命令行的朋友可能会爽一些。但是功能有限。适合机器跑不动SQLServerManagementStudio的朋友使用。

只想知道 发表于 2015-2-2 10:25:57

大侠们有推荐的书籍和学习方法写下吧。

乐观 发表于 2015-2-7 18:07:12

现在是在考虑:如果写到服务器端,我一下搞他个10个存储过程导过去,那久之服务器不就成垃圾箱了吗?即便优化了我的中间层.

海妖 发表于 2015-2-22 22:11:42

这就引发了对varchar和char效率讨论的老问题。到底如何分配varchar的数据,是否会出现大规模的碎片?

再见西城 发表于 2015-3-7 04:03:53

其实可以做一下类比,Oracle等数据库产品老早就支持了java编程,而且提供了java池参数作为用户配置接口。但是现在有哪些系统大批使用了java存储过程?!连Oracle自己的应用都不用为什么?!

灵魂腐蚀 发表于 2015-3-14 11:46:35

如果是将来做数据库的开发设计,就应该详细学习T-SQL的各种细节,包括T-SQL的程序设计、存储过程、触发器以及具体使用某个开发语言来访问数据库。
页: [1]
查看完整版本: 绝无经由的MySQL数据库单一表冲破4G限定的完成办法