2.12.1. Linux注意事项

本节讨论发现的在 Linux中出现的问题。前面几节描述了一般操作系统相关的问题,使用二进制或源码分发版时可能出现的问题和安装后的问题。后面几节讨论在具体 Linux平台上出现的问题。

请注意这些问题的大多数出现在旧的Linux 版本中。如果你运行最新的版本,可能不会发现这些问题。

2.12.1.1. Linux操作系统注意事项

MySQL至少需要 Linux 2.0版本。

警告:我们已经发现在SMP系统中Linux 2.2.14 MySQL会出现一些奇怪的问题。我们还收到来自一些MySQL用户的报告说他们用内核2.2.14使用MySQL时遇到了严重的稳定性问题。如果你正使用该内核,应当升级到2.2.19 (或更新版)或到2.4内核。如果你有一个多CPU盒,应当考虑使用2.4,因为它能大大加速。你的系统将会更稳定。

当使用LinuxThreads时,你应当至少可以看见有三个mysqld 进程在运行。这些实际上是线程。有一个线程是LinuxThreads管理器,一个线程处理连接,另一个线程处理告警和信号。

2.12.1.2. Linux二进制分发版说明

MySQLLinux-Intel二进制和 RPM发布配置为最高的可能速度。我们一直在尝试使用可用的最快的稳定的编译器。

二进制发布用-staticis连接,说明一般情况你不需要关心系统库的版本。你也不需要安装LinuxThreads。用-staticis连接的程序稍微大于动态连接程序,但也稍微快一些(3-5%)。但是,静态连接程序的一个问题是你不能使用用户定义函数(UDF)。如果你将要写或使用UDF(只适用于CC++ 编程人员),你必须使用动态链接自己编译MySQL

二进制分发版的一个已知问题是在使用libc的旧的Linux系统(例如Red Hat 4.xSlackware)上,你会遇到一些(非致命)主机名解析问题。如果系统使用libc没有使用glibc2,你可能会遇到一些主机名解析和getpwnam()问题。这是因为glibc依靠一些外部库来执行主机名解析和getpwent(), 即使用-staticis编译也如此。这些问题出现在两个方面:

·         当运行mysql_install_db时,你会看见下面的错误消息:

·                Sorry, the host 'xxxx' could not be looked up

你可以通过执行mysql_install_db --force来解决该问题,并不在mysql_install_db中执行resolveip测试。不利方面是 你不能在授权表中使用主机名:除了localhost,必须使用IP号。如果你正使用不支持force的旧版本MySQL,必须使用文本编辑器手动卸载mysql_install中的resolveip测试。

·         当你尝试用--user选项运行mysqld你还会看见下面的错误:

·                getpwnam: No such file or directory

要解决该问题,使用su命令启动mysqld,不要指定--user选项。这样使系统自己更改mysqld进程的用户IDmysqld不再需要这样做。

另一个解决办法可以解决两个问题,即不使用二进制分发版。获得MySQL源码分发版(RPMtar.gz格式)并安装。

在一些Linux 2.2版本中,当客户端通过TCP/IP建立大量与mysqld服务器的新连接时,你可能会遇到错误Resource temporarily unavailable。该问题是Linux在你关闭TCP/IP套接字的时间和系统实际释放该套接字的时间之间有一个延迟。只有有限数目的TCP/IP时段有空间,因此如果客户端试图在短时间内建立许多新TCP/IP连接时,你会遇到源不可用错误。例如,当你通过TCP/IP运行MySQL test-connect基准测试时你会看见该错误。

我们已经多次向不同的 Linux 邮件列表询问该问题,但是一直没有找到合适的解决办法。唯一知道的“解决办法”是客户端使用永久连接,或,如果你在同一机器上运行数据库服务器和客户端,使用Unix套接字文件来连接,不要使用TCP/IP连接。

2.12.1.3. Linux源码分发版说明

下面关于 glibc的注意事项只适用你自己构建 MySQL时。如果在 x86机器上运行 Linux,在大多数情况下最好使用我们的二进制。我们将二进制连接到了我们能找到的打了最好补丁的 glibc版本,并使用了最优的编译器选项,尽力使它适合高负荷服务器。对于典型用户,即使对于超过 2GB限制的大量并行连接或表设置,在大多数情况下,我们的二进制仍然是最佳选择。阅读下面的内容后,如果你不清楚怎样做,先试用我们的二进制看它是否满足你的需求。如果你发现它不够完善,那么你可以尝试你自己的构建。在这种情况下,我们很希望能看到相关注释,以便我们下次可以构建更好的二进制。

MySQLLinux上使用 LinuxThreads 。如果你正在使用一个没有glibc2的老的Linux版本,你必须在尝试编译MySQL前安装LinuxThreads。你可以从 http://dev.mysql.com/downloads/os-linux.html获得LinuxThreads

注意:当你执行INSERT DELAYED时,所用的包括2.1.1及以前的glibc版本在pthread_互斥_timedwait()处理上有一个致命错误,如果你正在使用INSERT DELAYED,我们建议先升级glibc

请注意Linux 内核和LinuxThreads库默认情况下最多可以处理1,024个线程。如果你计划使用超过1,000个并行连接,需要对LinuxThreads进行一些更改,如下所示:

·         sysdeps/unix/sysv/linux/bits/local_lim.h中的PTHREAD_THREADS_MAX 增加到4096,将LinuxThreads/internals.h 中的STACK_SIZE减少到256KB。路径相对于glibc的根目录。(请注意如果STACK_SIZE为默认值2MBMySQL600-1000个连接时不稳定)

·         重新编译LinuxThreads,生成新的libpthreads.a库,并重新连接MySQL

可以从http://www.volano.com/linuxnotes.html 查阅关于LinuxThreads线程限制的详细信息。

还有一个问题会严重影响MySQL的性能,特别是在SMP系统中。在glibc 2.1LinuxThreads中,对于拥有很多只是短时间内占有互斥体的线程的程序,不能很好地执行互斥。结果出现荒谬的现象:在许多情况下,如果你使用未修改的LinuxThreads连接MySQL,从SMP中去掉卸载处理器实际上会提高MySQL的性能。我们提供了一个glibc 2.1.3的补丁来纠正该行为(http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch )

glibc 2.2.2,MySQL使用修改后的互斥,这样甚至比打了补丁的glibc 2.1.3还要好得多。但是,需要注意的是在某些条件下,当前glibc 2.2.2中的互斥代码会高旋,影响了MySQL的性能。通过优化mysqld进程到最高优先级,可以降低在这种情况下出现这种问题的可能性。我们还可以通过补丁来纠正高旋问题,可以从http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch下载。它集成高旋的纠正、线程最大数目和堆栈空间于一体。你需要用补丁patch -p0 </tmp/linuxthreads-2.2.2.patchLinuxThreads目录下使用。我们 希望在将来的glibc 2.2发布中能以某种形式将它包括进来。在任何情况下,如果你连接glibc 2.2.2,仍然需要纠正STACK_SIZE PTHREAD_THREADS_MAX我们希望在将来能将默认值纠正到某种程度上可以接受的值,适合高负荷MySQL设置,因此用来产生你自己的构建的  命令可以简化到到./configure; make; make install

我们建议你使用这些补丁来构建专用的libpthreads.a静态版本,并只使用它同MySQL实现静态链接。我们知道这些补丁对于MySQL很安全 并大大改善了它的性能,但是我们还不能断言它在其它应用程序上的效果如何。如果你需要将其它使用LinuxThreads的应用程序同打了补丁的静态版本的库连接,或构建一个打了补丁的共享版本,并将它安装到系统中,你将自己承担风险。

如果你在安装MySQL的过程中遇到任何奇怪的问题,或一些常用实用工具被悬挂起来,很可能是库或编译器相关问题。在这种情况下,使用我们的二进制来解决。

如果你连接你自己的MySQL客户端程序,运行时你会看见下面的错误:

ld.so.1: fatal: libmysqlclient.so.#:
open failed: No such file or directory

使用下面的方法可以避免该问题:

·         -Wl,r/full/path/to/libmysqlclient.so标记连接客户端,不要使用-Lpath)

·         libmysqclient.so复制到/usr/lib

·         运行客户端程序前,将libmysqlclient.so所在目录的路径名增加到LD_RUN_PATH环境变量。

如果使用Fujitsu编译器 (fcc/FCC),编译MySQ时可能会出现一些问题,因为Linux头文件主要面向gcc。以下的configure行应当结合fcc/FCC使用:

CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE \
    -DCONST=const -DNO_STRTOLL_PROTO" \
CXX=FCC CXXFLAGS="-O -K fast -K lib \
    -K omitfp -K preex --no_exceptions --no_rtti -D_GNU_SOURCE \
    -DCONST=const -Dalloca=__builtin_alloca -DNO_STRTOLL_PROTO \
    '-D_EXTERN_INLINE=static __inline'" \
./configure \
    --prefix=/usr/local/mysql --enable-assembler \
    --with-mysqld-ldflags=-all-static --disable-shared \
    --with-low-memory

2.12.1.4. Linux后期安装注意事项

MySQL安装目录或MySQL源码树下的support-files目录下可以找到mysql.server。你可以将它安装为/etc/init.d/mysql,以便自动启动和关闭MySQL。请参见2.9.2.2节,“自动启动和停止MySQL”

如果MySQL不能打开足够的文件或连接,可能是你没有将Linux配置为处理足够的文件。

Linux 2.2及以上版本中,你可以检查分配的文件的数目:

shell> cat /proc/sys/fs/file -max
shell> cat /proc/sys/fs/dquot-max
shell> cat /proc/sys/fs/super-max

如果有超过16MB的内存,应当在启动脚本中增加如下内容(例如,在SuSE Linux中:/etc/init.d/boot.local)

echo 65536 > /proc/sys/fs/file-max
echo 8192 > /proc/sys/fs/dquot-max
echo 1024 > /proc/sys/fs/super-max

还可以用root从命令行运行echo命令,但是下一次重新启动计算机时这些设定值会丢掉。

另外,可以使用许多Linux分发版使用的sysctl工具设置启动参数(包括SuSE Linux 8.0和以后版本)。将下面的值放到文件 /etc/sysctl.conf中:

# Increase some values for MySQL
fs.file-max = 65536
fs.dquot-max = 8192
fs.super-max = 1024

你还应将以下内容加入/etc/my.cnf

[mysqld_safe]
open-files-limit=8192

这样服务器连接和打开文件的总数目可以达到8,192

LinuxThreadsSTACK_SIZE常数控制在寻址空间中线程堆栈的占用空间。它需要足够大,以保证每个线程堆栈有足够的空间,但是应足够小,防止某些线程的堆栈运行全局mysqld数据。遗憾的是,根据我们的发现,如果你用mmap()映射目前正使用的寻址,Linux成功运行  后不会映射映射区,将会清空整个地址页上的数据而不会返回错误信息。因此,mysqld或其它线程应用程序的安全依靠创建线程的代码的“绅士”行为。用户必须采取措施以确保在任何时间运行线程的数目相对线程堆栈应足够低,以防止全局堆内存。使用mysqld时,你应当为max_connections变量设置合理的值强制该行为。

如果你自己构建MySQL,你可以为LinuxThreads打补丁以便更好地使用堆栈。请参见2.12.1.3节,“Linux源码分发版说明”。如果你不想为LinuxThreads打补丁,你应当将max_connections的值设置为不超过500。如果你有大的关键字缓冲区、大的堆内存表,或其它使mysqld分配大量内存的东西,或如果你用2GB的补丁运行2.2内核,max_connections的值应当更低。如果你正使用我们的二进制或RPM版本,可以安全地将max_connections设置为1500(假定没有大的关键字缓冲区或有大量数据的堆内存表。将LinuxThreads中的STACK_SIZE降低得越低,可以安全地创建越多的线程。我们推荐的值的范围为128KB256KB

如果你正使用大量的并行连接,在2.2内核中你可能会遇到一个“特性”,即通过对进程的分支或克隆子进程的行为进行罚分,来试图防止轰炸攻击。这样你增加并行客户端的数量时,MySQL不能正确响应。在单CPU系统中,我们已经发现该现象,即线程创建地很慢;连接MySQL的时间很长(长达1分钟),并且关闭的时间也很长。在多CPU系统中,我们已经观察到随着客户端数目的增加,查询速度逐渐下降。在寻求解决办法的过程中,我们收到了一个用户的内核补丁,他声称该补丁可以解决他的问题。从http://www.mysql.com/Downloads/Patches/linux-fork.patch可以下载该补丁。我们已经在开发和生产系统上对该补丁进行了广泛的测试。它可以大大改善MySQL的性能,而不会造成任何问题,我们向仍然在2.2内核运行高负荷服务器的用户推荐它。

2.4内核中已经对该问题进行了修复,因此如果你不满意当前系统的性能,不要为2.2 内核打补丁,在SMP系统中升级到2.4版要容易地多,升级不仅可以修复错误,还可以使SMP更好地加速。

我们已经在双CPU机器上在2.4内核中对MySQL进行了测试,发现MySQL的比例要好得多。1,000名客户查询时,还看不到速度有实质上的下降,MySQL的比例因子(最大吞吐量与一个客户端的吞吐量的比例)180%。我们在四-CPU系统中也观察到了类似的结果:当客户数目上升到1,000名时还没有实质上的减慢, 比例因子为300%。根据这些结果,对于使用2.2内核的高负荷SMP服务器,我们绝对建议升级到 2.4内核。

我们已经发现,在2.4内核中应使用可能的最高优先级来运行mysqld进程,以获得最佳性能。可以通过为mysqld_saferenice -20 $$命令来实现。在四-CPU系统中的测试中,提高优先级在400个客户时会使吞吐量增加60%

我们目前还想搜集关于MySQLfour-wayeight-way系统上用2.4内核执行的性能的更详细信息。如果你访问了这些系统并进行了一些基准测试,请将结果用email发送到<benchmarks@mysql.com>。我们将对它们进行审查以包括进手册中。

如果用ps运行mysqld服务器进程时发现进程死掉了,一半是MySQL中有缺陷或数据库表崩溃了。请参见A.4.2节,“如果MySQL依然崩溃,应作些什么”

如果mysqld死掉并给出SIGSEGV信号,要想在Linux中对内核进行调试,你可以用--core-file选项启动mysqld。注意你还可能需要通过向mysqld_safe添加ulimit -c 1000000或用--core-file-size=1000000启动mysqld_safe来加大内核文件的大小。请参见5.1.3节,“mysqld_safe:MySQL服务器启动脚本”

2.12.1.5. Linux x86注意事项

MySQL需要5.4.12或更新版本的libc。已知它可以在libc 5.4.46中工作。glibc 2.0.6和更新版本应当也可以工作。Red Hatglibc RPM有一些问题,因此如果你遇到问题,应看看是否有更新版。已知glibc 2.0.7-192.0.7-29 RPM可以工作。

如果你正使用Red Hat 8.0或更新的glibc 2.2.x库,你会看见mysqld执行gethostbyaddr()时会死掉。这是因为新的glibc库在执行该调用时需要大于128KB的堆栈空间。要想修复该问题,用--thread-stack=192K选项启动mysqld(MySQL 4以前的版本中应使用-O thread_stack=192KMySQL 4.0.10和以上版本中,该堆栈空间值即为默认值,因此你不会看见该问题。

如果你正使用gcc 3.0和以上版本编译MySQL,在编译MySQL前你必须先安装libstdc++v3库;如果不这样做,在联接过程中会遇到关于丢失__cxa_pure_virtual符号的错误。

在一些旧的Linux分发版中,configure会生成如下错误:

Syntax error in sched.h. Change _P to __P in the
/usr/include/sched.h file.
See the Installation chapter in the Reference Manual.

只需要按照错误消息的提示操作。对只有一条下划线的_P名再增加一条下划线,然后重新尝试。

编译时可能会出现警告。下面的警告可以忽略:

mysqld.cc -o objs-thread/mysqld.o
mysqld.cc: In function `void init_signals()':
mysqld.cc:315: warning: assignment of negative value `-1' to
`long unsigned int'
mysqld.cc: In function `void * signal_hand(void *)':
mysqld.cc:346: warning: assignment of negative value `-1' to
`long unsigned int'

如果mysqld启动时总是出现转储内核, 问题可能是你使用了旧的/lib/libc.a。尝试重新对其命名,然后删掉sql/mysqld并重新执行make install然后再次尝试。已经报导在部分Slackware安装中出现了该问题。

当链接mysqld时如果出现下面的错误,说明libg++.a安装不正确:

/usr/lib/libc.a(putc.o): In function `_IO_putc':
putc.o(.text+0x0): multiple definitiof `_IO_putc'

你可以使用libg++.a运行configure来避免该问题:

shell> CXX=gcc ./configure

2.12.1.6. Linux SPARC注意事项

在部分执行过程中, readdir_r()会中断。现象是 SHOW DATABASES语句总是返回空子集。可以在完成配置、进行编译前从 config.h中删掉 HAVE_READDIR_R来修复。

2.12.1.7. Linux Alpha注意事项

我们已经用我们的基准和测试套件在Alpha中测试了MySQL 5.1,看起来工作得不错。

我们目前在配置Alpha EV6处理器的Compaq DS20机器上,在SuSE Linux 7.0中对AXP、内核2.4.4-SMPCompaq C编译器(V6.2-505)Compaq C++编译器(V6.3-006)构建MySQL二进制软件包。

你可以从 http://www.support.compaq.com/alpha-tools/ 找到上述编译器。使用这些编译器,得到的MySQL性能比gcc要好9-14%

AlphaMySQL中,我们在编译选项中使用-arch generic标记,可以确保二进制在所有Alpha处理器中运行。我们还采用静态编译以避免库问题。configure命令应为:

CC=ccc CFLAGS="-fast -arch generic" CXX=cxx \
CXXFLAGS="-fast -arch generic -noexceptions -nortti" \
./configure --prefix=/usr/local/mysql --disable-shared \
    --with-extra-charsets=complex --enable-thread-safe-client \
    --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared
 

如果想要使用egcs,可以使用下面的configure行:

CFLAGS="-O3 -fomit-frame-pointer" CXX=gcc \
CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors \
    -fno-exceptions -fno-rtti" \
./configure --prefix=/usr/local/mysql --disable-shared

已知的在Linux-Alpha中运行MySQL的问题:

·         gdb 4.18 中不能调试线程应用程序。你应当使用gdb 5.1

·         使用gcc时如果你尝试静态链接mysqld,启动时映像会导致转储内核。换句话说,使用gcc时不要使用--with-mysqld-ldflags=-all-static

2.12.1.8. Linux PowerPC注意事项

MySQL应当可以在使用最新 glibc安装软件包 (glibc 2.0.7测试 )MkLinux上工作。

2.12.1.9. Linux MIPS注意事项

为了使 MySQLQube2(Linux Mips)上工作,需要最新的 glibc库。已知 glibc-2.0.7-29C2可以工作。还必须使用 egcs C++编译器 (egcs 1.0.2-9gcc 2.95.2或更新版 )

2.12.1.10. Linux IA-64注意事项

要想让MySQLLinux IA-64中编译,我们用 gcc 2.96构建时使用下面的configure命令:

CC=gcc \
CFLAGS="-O3 -fno-omit-frame-pointer" \
CXX=gcc \
CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \
    -fno-exceptions -fno-rtti" \
    ./configure --prefix=/usr/local/mysql \
    "--with-comment=Official MySQL binary" \
    --with-extra-charsets=complex

IA-64,MySQL客户端二进制使用共享库。这意味着如果你将我们的二进制分发版安装到/usr/local/mysql之外的其它位置,需要将libmysqlclient.so安装目录路径加到/etc/ld.so.conf文件或LD_LIBRARY_PATH环境变量中。

参见A.3.1节,“与MySQL客户端库的链接问题”

关注编程学问公众号