您的位置:首页 > 数据库 > MySQL

7.5. 优化MySQL服务器

2013-06-15 23:12 393 查看
7.4.8. MySQL如何计算打开的表当运行mysqladmin status时,将看见象这样的一些东西:Uptime: 426 Running threads: 1 Questions:11082Reloads: 1 Open tables: 12
如果你仅有6个表,Open tables值为12可能有点令人困惑。MySQL是多线程的,因此许多客户可以同时在同一个表上进行查询。为了使多个客户线程在同一个表上有不同状态的问题减到最小,表被每个并发进程独立地打开。这样需要额外的内存但一般会提高性能。对于MyISAM表,数据文件需要为每个打开表的客户提供一个额外的文件描述符。(索引文件描述符在所有线程之间共享)。下一节中提供了该主题的更多的信息。参见7.4.9节,“MySQL如何打开和关闭表”7.4.9. MySQL如何打开和关闭表table_cache、max_connections和max_tmp_tables系统变量影响服务器保持打开的文件的最大数量。如果你增加这些值其中的一个或两个,会遇到操作系统为每个进程打开文件描述符的数量强加的限制。许多操作系统允许你增加打开的文件的限制,尽管该方法随系统的不同而不同。查阅操作系统文档以确定是否可以增加限制以及如何操作。table_cache与max_connections有关。例如,对于200个并行运行的连接,应该让表的缓存至少有200 *N,这里N是可以执行的查询的一个联接中表的最大数量。还需要为临时表和文件保留一些额外的文件描述符。确保操作系统可以处理table_cache设置所指的打开的文件描述符的数目。如果table_cacheis设得太高,MySQL可能为文件描述符耗尽资源并拒绝连接,不能执行查询,并且很不可靠。还必须考虑到MyISAM存储引擎需要为每个打开的表提供两个文件描述符。可以在mysqld_safe中使用--open-files-limit启动选项来增加MySQL适用的文件描述符的数量。参见A.2.17节,“文件未找到”。打开表的缓存可以保持在table_cache条。默认为64;可以用mysqld的--table_cache选项来更改。请注意MySQL可以临时打开更多的表以执行查询。在下面的条件下,未使用的表将被关闭并从表缓存中移出:・ 当缓存满了并且一个线程试图打开一个不在缓存中的表时。・ 当缓存包含超过table_cache个条目,并且缓存中的表不再被任何线程使用。・ 当表刷新操作发生。当执行FLUSH TABLES语句或执行mysqladmin flush-tablesmysqladmin refresh命令时会发生。当表缓存满时,服务器使用下列过程找到一个缓存入口来使用:・ 当前未使用的表被释放,以最近最少使用顺序。・ 如果缓存满了并且没有表可以释放,但是一个新表需要打开,缓存必须临时被扩大。如果缓存处于一个临时扩大状态并且一个表从在用变为不在用状态,它被关闭并从缓存中释放。对每个并发访问打开一个表。这意味着,如果2个线程访问同一个表或在同一个查询中访问表两次(例如,将表连接为自身时),表需要被打开两次。每个并行的打开要求在表缓存中有一个条目。任何表的第一次打开占2个文件描述符:一个用于数据文件另一个用于索引文件。表的每一次额外使用仅占一个数据文件的文件描述符。索引文件描述符在所有线程之间共享。如果你正用HANDLERtbl_nameOPEN语句打开一个表,将为该线程专门分配一个表。该表不被其它线程共享,只有线程调用HANDLERtbl_nameCLOSE或线程终止后才被关闭。表关闭后,被拉回表缓存中(如果缓存不满)。参见13.2.3节,“HANDLER语法”。可以通过检查mysqld的状态变量Opened_tables确定表缓存是否太小:mysql> SHOW STATUS LIKE'Opened_tables';+---------------+-------+| Variable_name | Value |+---------------+-------+| Opened_tables | 2741 |+---------------+-------+如果值很大,即使你没有发出许多FLUSH TABLES语句,也应增加表缓存的大小。参见5.3.3节,“服务器系统变量”5.3.4节,“服务器状态变量”7.4.10. 在同一个数据库中创建多个表的缺陷如果在同一个数据库目录中有许多MyISAM表,打开、关闭和创建操作将会很慢。如果对许多不同的表执行SELECT语句,当表缓存满时,将有一点开销,因为对每个必须打开的表,另外一个必须被关闭。可以通过使表缓存更大些来减少这个开销。7.5. 优化MySQL服务器7.5.1. 系统因素和启动参数的调节7.5.2. 调节服务器参数7.5.3. 控制查询优化器的性能7.5.4. 编译和链接怎样影响MySQL的速度7.5.5. MySQL如何使用内存7.5.6. MySQL如何使用DNS7.5.1. 系统因素和启动参数的调节我们从系统级因素开始,因为必须尽早地进行部分决策以获得较大性能。在其它情况下,快速浏览该节就足够了。但是,了解一下更改该层次的参数能够获得多少性能提高是很有意义的。使用的操作系统很重要。为了更好地使用多CPU机器,应使用Solaris(因为其线程工作得很好)或Linux(因为2.4和以后的内核有很好的SMP支持)。请注意默认情况旧的Linux内核有一个2GB的文件大小限制。如果有这样的一个内核并且需要文件大于2GB,应得到ext2文件系统的大文件支持(LFS)补丁。其它文件系统例如ReiserFS和XFS没有此2GB限制。将MySQL用于生产前,我们建议你在想用的平台上对它进行测试。其它技巧:・ 如果有足够的RAM,可以移除所有的交换设备。有些操作系统即使有自由内存也使用交换设备。・ 使用--skip-external-lockingMySQL选项以避免外部锁定。该选项默认开启。请注意只要你只运行一个服务器,--skip-external-locking选项不影响MySQL的功能。只要记住运行myisamchk之前关闭服务器(或锁定并刷新相关表)。在一些系统上该选项是强制的,因为在任何情况下外部锁定均不工作。不能使用--skip-external-locking的唯一情况是对相同的数据运行多个MySQL服务器(非客户)的情况,或者如果没有事先告诉服务器刷新并锁定一个表即运行myisamchk来检查(非修复)该表。请注意一般不建议使用多个MySQL服务器来并行访问相同的数据,除了使用MySQL Cluster时。即使使用--skip-external-locking,仍然可以使用LOCK TABLES和UNLOCK TABLES。7.5.2. 调节服务器参数可以用这个命令得到mysqld服务器默认缓存区的大小:shell> mysqld --verbose --help这个命令生成所有mysqld选项和可配置变量的列表。输出包括默认值并且看上去象这样:help TRUEabort-slave-event-count 0allow-suspicious-udfs FALSEauto-increment-increment 1auto-increment-offset 1automatic-sp-privileges TRUEbasedir /home/jon/bin/mysql/bdb FALSEbind-address (No default value)character-set-client-handshake TRUEcharacter-set-server latin1character-sets-dir /home/jon/bin/mysql/share/mysql/charsets/chroot (No default value)collation-server latin1_swedish_cicompletion-type 0concurrent-insert 1。。。。
如果有一个mysqld服务器正在运行,通过连接它并执行这个命令,可以看到实际上使用的变量的值:mysql> SHOW VARIABLES;还可以通过下面的语句看到运行服务器的统计和状态指标:mysql>SHOW STATUS;使用mysqladmin还可以获得系统变量和状态信息:shell> mysqladmin variablesshell> mysqladmin extended-status关于所有系统和状态变量的完全描述参见5.3.3节,“服务器系统变量”5.3.4节,“服务器状态变量”。MySQL使用完全可以升级的算法,因此通常运行时可以用很少的内存。然而,通常情况若给MySQL更多的内存性能会更好。当调节MySQL服务器时,要配置的两个最重要的变量是key_buffer_size和table_cache。在试图更改其它变量前你应先确信已经适当地配置了这些变量。下面的例子显示了部分典型的不同的运行时配置的变量值。・ 如果至少有256MB内存和许多表,想要在中等数量的客户时获得最大性能,应使用:・ shell> mysqld_safe --key_buffer_size=64M --table_cache=256 \--sort_buffer_size=4M--read_buffer_size=1M &・ 如果只有128MB内存和少量表,但仍然要进行大量的排序,可以使用:・ shell> mysqld_safe --key_buffer_size=16M --sort_buffer_size=1M如果有许多并行连接,交换问题会发生,除非mysqld已经配置成为每个连接分配很少的内存。如果有足够的内存用于所有连接,mysqld会执行得更好。・ 对于少量内存和大量连接,应使用:・ shell> mysqld_safe --key_buffer_size=512K --sort_buffer_size=100K \--read_buffer_size=100K&或甚至为:shell> mysqld_safe--key_buffer_size=512K --sort_buffer_size=16K \--table_cache=32 --read_buffer_size=8K \--net_buffer_length=1K &如果正对远远大于可用内存的表执行GROUP BY或ORDER BY操作,应增加read_rnd_buffer_size的值以加速排序操作后面的行读取。如果已经安装了MySQL,support-files目录包含一些不同的my.cnf示例文件:my-huge.cnf、my-大.cnf、my-medium.cnf和my-small.cnf。可以使用这些文件来优化系统。请注意如果在命令行中为mysqldmysqld_safe指定一个选项,它只在该次服务器调用中保持有效。要想每次服务器运行时使用该选项,将它放在选项文件中。要想看参数更改的效果,应执行:shell> mysqld --key_buffer_size=32M--verbose ---help变量值列于输出的最后。确保--verbose和---help选项在最后。否则,在命令行中列于它们后面的选项的效果不会反映到输出中。关于调节InnoDB存储引擎的信息,参见15.2.11节,“InnoDB性能调节提示”7.5.3. 控制查询优化器的性能查询优化器的任务是发现执行SQL查询的最佳方案。因为“好”方案和“坏”方案之间的性能差别会巨大(也就是说,秒相对于小时或甚至天),大多数查询优化器,包括MySQL的查询优化器,总或多或少地在所有可能的查询评估方案中搜索最佳方案。对于联接查询,MySQL优化器所调查的可能的方案数随查询中所引用的表的数目呈指数增长。对于小数量的表(典型小于7-10),这不是一个问题。然而,当提交的查询更大时,查询优化所花的时间会很容易地成为服务器性能的主要瓶颈。查询优化的一个更加灵活的方法是允许用户控制优化器详尽地搜索最佳查询评估方案。一般思想是优化器调查的方案越少,它编译一个查询所花费的时间越少。另一方面,因为优化器跳过了一些方案,它可能错过一个最佳方案。优化器关于方案数量评估的行为可以通过两个系统变量来控制:・ optimizer_prune_level变量告诉优化器根据对每个表访问的行数的估计跳过某些方案。我们的试验显示该类“有根据的猜测”很少错过最佳方案,并且可以大大降低查询编辑次数。这就是为什么默认情况该选项为on(optimizer_prune_level=1)。然而,如果你认为优化器错过了一个更好的查询方案,则该选项可以关闭(optimizer_prune_level=0),风险是查询编辑花费的时间更长。请注意即使使用该启发,优化器仍然可以探测呈指数数目的方案。・ optimizer_search_depth变量告诉优化器对于每个未完成的“未来的”方案,应查看多深,以评估是否应对它进一步扩大。optimizer_search_depth值较小会使查询编辑次数大大减小。例如,如果optimizer_search_depth接近于查询中表的数量,对12、13或更多表的查询很可能需要几小时甚至几天的时间来编译。同时,如果用optimizer_search_depth等于3或4编辑,对于同一个查询,编译器编译时间可以少于1分钟。如果不能确定合理的optimizer_search_depth值,该变量可以设置为0,告诉优化器自动确定该值。7.5.4. 编译和链接怎样影响MySQL的速度下列大多数测试是在Linux上并用MySQL基准进行的,但是它们能对其它操作系统和工作负载给出一些指示。当你用-static链接时,可以得到最快的可执行文件。在Linux上,最好用pgcc和-O3编译服务器。为了用这些选项编译“sql_yacc.cc”,需要大约200M内存,因为gccpgcc需要大量的内存使所有函数嵌入(inline)。在配置MySQL时,也应该设定CXX=gcc以避免包括libstdc++库(它不需要)。请注意对于某些版本的pgcc,生成的二进制只能运行在真Pentium处理器上,即使你使用编译器选项说明你想让最终的代码在所有x586-类处理器上工作(例如AMD)。只通过使用一个较好的编译器或较好的编译器选项,在应用中能得到10-30%的加速。如果你自己编译SQL服务器,这特别重要!当我们测试Cygnus CodeFusion或Fujitsu编译器时,二者均还没足够不出错来让MySQL启用优化进行编译。标准MySQL二进制分发编译为支持所有字符集。当你自己编译MySQL时,应只包括将使用的字符集的支持。通过configure的--with-charset选项来控制。这里是我们做过的一些测量表:・ 如果你使用pgcc并用-O6编译,mysqld服务器比用gcc2.95.2快11%。・ 如果你动态地链接(没有-static),在Linux中结果慢了13%。注意你仍能在客户应用程序中使用动态链接MySQL库。只有服务器对性能是关键的。・ 如果你用strip mysqld剥离mysqld二进制,生成的二进制可以快4%。・ 对于在同一主机上运行的客户与服务器之间的连接,如果你使用TCP/IP而非Unix套接字文件进行连接,结果慢7.5%。(在Unix中,如果你连接localhost主机,MySQL默认使用一个套接字文件)。・ 对于从客户到服务器的TCP/IP连接,从另一台主机连接一台远程服务器要比连接同一主机上的服务器慢8-11%,即使通过100Mb/s以太网进行连接。・ 当使用安全连接运行我们的基准测试时(所有数据用内部SSL支持进行加密),性能比未加密连接慢55%。・ 如果你用--with-debug=full编译,大多数查询慢20%。部分查询时间会很长;例如,MySQL基准的运行要慢35%。如果你使用--with-debug(没有=full),速度只下降15%。对于用--with-debug=full编译的mysqld版本,可以用--skip-safemalloc选项启动以便在运行时禁用内存检查。执行速度则接近用--with-debug配置的时候。・ 在Sun UltraSPARC-Iie上,用Forte 5.0编译的服务器比用gcc3.2编译的要快4%。・ 在Sun UltraSPARC-Iie上,用Forte 5.0编译的32位模式服务器比64位模式服务器要快4%。・ 用gcc2.95.2编译带-mcpu=v8 -Wa的UltraSPARC,使用-xarch=v8plusa选项性能会提高4%。・ 在Solaris 2.5.1上,在单个处理器上MIT-pthreads比带原生线程的Solaris慢8-12%。如果有更大的负载/cpus,差别应该更大。・ 在Linux-x86上使用gcc编译而不用帧指针(-fomit-frame-pointeror-fomit-frame-pointer -ffixed-ebp),可以使mysqld快1-4%。MySQL AB提供的Linux上的二进制MySQL分发一般用pgcc编译。我们必须返回到常规gcc,因为pgcc中有一个bug,使生成的二进制不能在AMD上运行。我们将继续使用gcc直到该bug被解决。同时,如果你有一个非AMD机,你可以用pgcc编译构建一个更快的二进制。标准MySQL Linux二进制是通过静态链接,以使它更快并且更加易于移植。7.5.5. MySQL如何使用内存下面的列表中列出了mysqld服务器使用内存的一些方法。在适用的地方,给出了内存相关的系统变量名:・ 键缓存(变量key_buffer_size)被所有线程共享;服务器使用的其它缓存则根据需要分配。参见7.5.2节,“调节服务器参数”。・ 每个连接使用具体线程的空间:o 堆栈(默认64KB,变量thread_stack)o 连接缓存区(变量net_buffer_length)o 结果缓存区(变量net_buffer_length)连接缓存区和结果缓存区可以根据需要动态扩充到max_allowed_packet。当某个查询运行时,也为当前查询字符串分配内存。・ 所有线程共享相同的基本内存。・ 只有压缩MyISAM表映射到内存。这是因为4GB的32位内存空间不足以容纳大多数大表。当64位地址空间的系统变得越来越普遍后,我们可以增加常规的内存映射支持。・ 对表进行顺序扫描的请求将分配一个缓存区(变量read_buffer_size)。・ 当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区(变量read_rnd_buffer_size)以避免硬盘搜索。・ 所有联合在一个令牌内完成,并且大多数联合甚至可以不用临时表即可以完成。大多数临时表是基于内存的(HEAP)表。具有大的记录长度的临时表(所有列的长度的和)或包含BLOB列的表存储在硬盘上。如果某个内部heap(堆积)表大小超过tmp_table_size,MySQL可以根据需要自动将内存中的heap表改为基于硬盘的MyISAM表。还可以通过设置mysqld的tmp_table_size选项来增加临时表的大小,或设置客户程序中的SQL选项SQL_BIG_TABLE。参见13.5.3节,“SET语法”。・ 进行排序的大多数请求将分配一个排序缓存区,并根据结果集的大小为两个临时文件分配零。参见A.4.4节,“MySQL将临时文件储存在哪里”。・ 几乎所有解析和计算在局部内存中完成。小项目不需要内存,因此避免了普通的慢内存分配和释放。只为不期望的大字符串分配内存;使用函数malloc()和free()来完成。・ 对于每个打开的MyISAM表,索引文件打开一次;数据文件为每个并行运行的线程打开一次。对于每个并行线程,将分配一个表结构、一个每个列的列结构和大小为3 *N的缓存区(其中N是最大行的长度,而不是计算BLOB列)。一个BLOB列需要5至8个字节加上BLOB数据的长度。MyISAM存储引擎维护一个额外的行缓存区供内部应用。・ 对于每个具有BLOB列的表,将对缓存区进行动态扩大以读入大的BLOB值。如果你扫描一个表,则分配一个与最大的BLOB值一样大的缓存区。・ 所有使用的表的句柄结构保存在高速缓存中并以FIFO管理。默认情况,高速缓存有64个入口。如果某个表同时被两个运行的线程使用,高速缓存则为该提供两个入口。参见7.4.9节,“MySQL如何打开和关闭表”。・ 当并行执行的线程结束时,FLUSH TABLE语句或mysqladmin flush-table命令可以立即关闭所有不使用的表并将所有使用中的表标记为已经关闭。这样可以有效释放大多数使用中的内存。FLUSH TABLE在关闭所有表之前不返回结果。ps和其它系统状态程序可以报导mysqld使用很多内存。这可以是在不同的内存地址上的线程栈造成的。例如,Solaris版本的ps将栈间未用的内存算作已用的内存。你可以通过用swap -s检查可用交换区来验证它。我们用商业内存漏洞探查器测试了mysqld,因此应该有没有内存漏洞。7.5.6. MySQL如何使用DNS当新的客户连接mysqld时,mysqld创建一个新的线程来处理请求。该线程先检查是否主机名在主机名缓存中。如果不在,线程试图解析主机名:・ 如果操作系统支持线程安全gethostbyaddr_r()和gethostbyname_r()调用,线程使用它们来执行主机名解析。・ 如果操作系统不支持线程安全调用,线程锁定一个互斥体并调用gethostbyaddr()和gethostbyname()。在这种情况下,在第1个线程解锁互斥体前,没有其它线程可以解析不在主机名缓存中的主机名。你可以用--skip-name-resolve选项启动mysqld来禁用DNS主机名查找。然而,在这种情况下,你只可以使用MySQL中的授权表中的IP号。如果你有一个很慢的DNS和许多主机,你可以通过用--skip-name-resolve禁用DNS查找或增加HOST_CACHE_SIZE定义(默认值:128)并重新编译mysqld来提高性能。你可以用--skip-host-cache选项启动服务器来禁用主机名缓存。要想清除主机名缓存,执行FLUSH HOSTS语句或执行mysqladmin flush-hosts命令。如果你想要完全禁止TCP/IP连接,用--skip-networking选项启动mysqld7.6. 磁盘事宜7.6.1. 使用符号链接・ 磁盘搜索是巨大的性能瓶颈。当数据量变得非常大以致于缓存性能变得不可能有效时,该问题变得更加明显。对于大数据库,其中你或多或少地随机访问数据,你可以确信对读取操作需要至少一次硬盘搜索,写操作需要多次硬盘搜索。要想使该问题最小化,应使用搜索次数较少的磁盘。・ 通过链接文件到不同的磁盘或对硬盘分段来增加可用磁盘锭数量(因此降低搜索成本):o 使用符号链接这说明,对于MyISAM表,你符号链接索引文件和/或数据文件,从它们数据目录内的通常位置到另一个硬盘(也可以被条纹化)。这将使搜索和读次数达到最好,假定硬盘不再为其它目的使用。参见7.6.1节,“使用符号链接”。o 分条分条意味着你有许多磁盘,将第1个块放到第1个硬盘,第2个块放到第2个磁盘,并且第N块在(Nmod number_of_disks)磁盘上等等。这意味着如果正常数据大小小于分条大小(或完全匹配),能够得到最佳性能。分条完全取决于操作系统和分条大小,因此用不同的条纹大小对应用程序进行基准测试。参见7.1.5节,“使用自己的基准”。分条的不同速度完全依赖于参数。依赖于怎样设置条纹参数和硬盘数量,可以根据不同数量级别得到不同的标准。你必须进行选择以便优化随机或顺序存取。・ 为了高可靠性你可能想使用RAID 0+1(条纹加镜像),但在这种情况下,需要2*N块磁盘来保持N个磁盘的数据。如果你肯为它花钱,这可能是最好的选项。然而,你可能还必须投资一部分资金到卷管理软件中以便有效地管理它。・ 一个较好的选择是根据数据类型的重要性程度改变RAID级别。例如,保存可以在RAID 0硬盘上重新生成的不太重要的数据,但保存真正重要数据(例如主机信息和日志)到RAID 0+1或RAID N硬盘。如果你有许多写操作,RAID N可能会存在问题,因为需要时间来更新校验位。・ 在Linux上,通过配置磁盘接口时使用hdparm,你可以获得更多的性能。(在一般负载下达到100%并不困难。)下面的hdparm选项应该非常适用于MySQL,并且可能适用于许多其它应用程序: hdparm -m 16 -d 1请注意,当使用该命令时,性能和可靠性依赖于硬件,因此我们强烈建议,使用hdparm后,完全测试你的系统。为获取更多详细信息,请查阅hdparm手册帮助页。如果hdparm使用的不好,会导致文件系统破坏,因此试验之前请做好每个备份!・ 也可以设置数据库使用的文件系统参数:如果不需要知道文件最后一次访问的时间(这对数据库服务器并没有实际的用途),可以用-o noatime选项安装文件系统。这将跳过对文件系统中的节点的最后一次访问时间的更新,从而能够避免一些硬盘搜索。在许多操作系统中,用-o async选项安装,可以将文件系统设置为异步更新。如果电脑相当稳定,这应该给予你更高的性能而不需要牺牲太多的可靠性。(该标志是Linux中默认开启。)7.6.1. 使用符号链接7.6.1.1. Unix上使用针对数据库的符号链接7.6.1.2. Unix平台上使用表的符号链接7.6.1.3. Windows平台上使用关于数据库的符号链接你可以将表和数据库从数据库目录移动到其它的位置并且用指向新位置的符号链接进行替换。你可能需要这样作,例如,移动数据库到一个有更多空闲空间的文件系统中或通过将表分散到不同的磁盘上以增加系统的访问速度。推荐的方法值需要将数据库通过符号链接指到不同的磁盘。符号链接表仅作为是最后的办法。7.6.1.1. Unix上使用针对数据库的符号链接在Unix中,符号链接一个数据库的方法是,首先在一些有空闲空间的硬盘上创建一个目录,然后从MySQL数据目录中创建它的一个符号链接。shell> mkdir /dr1/databases/testshell> ln -s /dr1/databases/test /path/to/datadirMySQL不支持链接一个目录到多个数据库。用一个符号链接替换一个数据库目录,只要你不在数据库之间制作符号链接。假定你有一个数据库db1在MySQL数据目录下,然后生成一个符号链接db2指向db1:shell> cd /path/to/datadirshell> ln -s db1 db2对于db1中的任何表tbl_a,在db2也出现并且还是表tbl_a。如果一个客户更新db1.tbl_a并且另一个客户更新db2.tbl_a,可能会出现问题。然而,如果你真的需要这样做,可以通过改变源文件mysys/my_symlink.c来实现,在该文件中你应查找下面的语句:if (!(MyFlags &MY_RESOLVE_LINK) || (!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode)))将该语句修改为:if (1)请注意,对于所有的Windows服务器,默认启用符号链接支持。7.6.1.2. Unix平台上使用表的符号链接你不应在没有完全可操作的realpath()调用的系统中对表进行符号链接。(Linux和Solaris支持realpath())。可以通过发出一个SHOW VARIABLES LIKE 'have_symlink'语句,检查系统是否支持符号链接。只有MyISAM表完全支持符号链接。对于其它表类型,如果试图在操作系统中的文件上用前面的任何语句使用符号链接,可能会出现奇怪的问题。对于MyISAM表的符号链接的处理如下:・ 在数据目录指,一定会有表定义文件、数据文件和索引文件。数据文件和索引文件可以移到别处和在数据目录中符号链接替代。表定义文件不能进行符号链接替换。・ 可以分别通过符号链接将数据文件和索引文件指到不同的目录。・ 如果mysqld没有运行,符号链接可以从服务器命令行使用ln -s手动完成。同样,通过使用DATA DIRECTORY和INDEX DIRECTORY选项创建表,你可以指示运行的MySQL服务器执行符号链接。参见13.1.5节,“CREATE TABLE语法”。・ myisamchk不用数据文件或索引文件替换符号链接。它直接工作在符号链接指向的文件。任何临时文件创建在数据文件或索引文件所处的目录中。・ 注释:当你删掉一个表时,如果该表使用了符号链接,符号链接和该符号链接指向的文件都被删除掉。这就是你不应以系统root用户运行mysqld或允许系统用户对MySQL数据库目录有写访问权限的原因。・ 如果你用ALTER TABLE ... RENAME重命名一个表并且不将表移到另一个数据库,数据库目录中的符号链接被重新命名为一个新名字并且数据文件和索引文件也相应地重新命名。・ 如果你用ALTER TABLE ... RENAME移动一个表到另一个数据库,表移动到另一个数据库目录。旧的符号链接和其所指向的文件被删除。换句话说,新表不再被链接。・ 如果不使用符号链接,你应对mysqld使用--skip-symbolic-links选项以确保没有人能够使用mysqld来删除或重新命名数据目录之外的文件。表符号链接还不支持以下操作:・ ALTER TABLE忽略DATA DIRECTORY和INDEX DIRECTORY表选项。・ BACKUP TABLE和RESTORE TABLE不考虑符号链接。・ .frm文件必须绝不能是一个符号链接(如前面所述,只有数据和索引文件可以是符号链接)。如果试图这样做(例如,生成符号链接)会产生不正确的结果。假定你在MySQL数据目录下有一个数据库db1,该数据库有一个表tbl1,并且在db1目录中你制作了一个符号链接tbl2指向tbl1:・ shell> cd /path/to/datadir/db1・ shell> ln -s tbl1.frm tbl2.frm・ shell> ln -s tbl1.MYD tbl2.MYD・ shell> ln -s tbl1.MYI tbl2.MYI如果一个线程读取db1.tbl1同时另一个线程更新db1.tbl2会发生问题:o 查询缓存将变为“傻瓜”(它没有办法知道tbl1是否被更新,因此它返回过时的结果)。o tbl2上的ALTER语句也会失败。7.6.1.3. Windows平台上使用关于数据库的符号链接Windows的mysqld-max和mysql-max-nt服务器使用-DUSE_SYMDIR选项编译成。允许你放置数据库目录到一个不同的硬盘,通过设置一个符号链接指向它。这类似于Unix中的符号链接,尽管设置链接的过程不同。符号链接默认为启用。如果你不需要,使用skip-symbolic-links选项来禁用它:[mysqld]skip-symbolic-links在Windows中,通过在数据目录中创建一个文件,该文件包含目标目录的路径,你可以为MySQL数据库创建一个符号链接。该文件应该被命名为db_name.sym,其中db_name是数据库名。假定MySQ数据目录是C:\mysql\data并且你想要数据库foo放置在D:\data\foo。设置一个符号链接如下所示:1. 确保D:\data\foo目录存在,如果必要创建它。如果你在数据目录内有一个命名为foo的数据库目录,你应移动它到D:\data目录。否则,符号链接无效。为避免出现问题,当你移动数据库目录时服务器不应该运行。2. 创建一个文本文件C:\mysql\data\foo.sym,该本文文件包含路径名D:\data\foo\。此后,数据库foo创建的所有表将创建在D:\data\foo文件中。请注意,如果在MySQL数据目录中存在同名的数据库目录,不能使用符号链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: