This appendix helps you port MySQL to other operating systems. Do
check the list of currently supported operating systems first. See
Section 2.1.1, “Operating Systems Supported by MySQL”. If you have created a new port of MySQL,
please let us know so that we can list it here and on our Web site
(http://www.mysql.com/), recommending it to other
users.
Note: If you create a new port of MySQL, you are free to copy and
distribute it under the GPL license, but it does not make you a
copyright holder of MySQL.
A working POSIX thread library is needed for the server. On Solaris
2.5 we use Sun PThreads (the native thread support in 2.4 and
earlier versions is not good enough), on Linux we use LinuxThreads
by Xavier Leroy, <Xavier.Leroy@inria.fr>.
The hard part of porting to a new Unix variant without good native
thread support is probably to port MIT-pthreads. See
mit-pthreads/README and Programming POSIX
Threads (http://www.humanfactor.com/pthreads/).
It is also possible to use another user level thread package named
FSU Pthreads (see
http://moss.csc.ncsu.edu/~mueller/pthreads/). This
implementation is being used for the SCO port.
See the thr_lock.c and
thr_alarm.c programs in the
mysys directory for some tests/examples of
these problems.
Both the server and the client need a working C++ compiler. We use
gcc on many platforms. Other compilers that are
known to work are SPARCworks, Sun Forte, Irix cc,
HP-UX aCC, IBM AIX xlC_r),
Intel ecc/icc and Compaq cxx).
To compile only the client use ./configure
--without-server.
There is currently no support for only compiling the server, nor is
it likely to be added unless someone has a good reason for it.
Note: Before you start debugging
mysqld, first get the test programs
mysys/thr_alarm and
mysys/thr_lock to work. This ensures that your
thread installation has even a remote chance to work!
If you are using some functionality that is very new in MySQL, you
can try to run mysqld with the
--skip-new (which disables all new, potentially
unsafe functionality) or with --safe-mode which
disables a lot of optimization that may cause problems. See
Section A.4.2, “What to Do If MySQL Keeps Crashing”.
If mysqld doesn't want to start, you should
verify that you don't have any my.cnf files
that interfere with your setup! You can check your
my.cnf arguments with mysqld
--print-defaults and avoid using them by starting with
mysqld --no-defaults ....
If mysqld starts to eat up CPU or memory or if
it “hangs,” you can use mysqladmin
processlist status to find out if someone is executing a
query that takes a long time. It may be a good idea to run
mysqladmin -i10 processlist status in some
window if you are experiencing performance problems or problems
when new clients can't connect.
The command mysqladmin debug dumps some
information about locks in use, used memory and query usage to the
MySQL log file. This may help solve some problems. This command
also provides some useful information even if you haven't compiled
MySQL for debugging!
If the problem is that some tables are getting slower and slower
you should try to optimize the table with OPTIMIZE
TABLE or myisamchk. See
Chapter 5, Database Administration. You should also check
the slow queries with EXPLAIN.
If you have some very specific problem, you can always try to
debug MySQL. To do this you must configure MySQL with the
--with-debug or the
--with-debug=full option. You can check whether
MySQL was compiled with debugging by doing: mysqld
--help. If the --debug flag is listed
with the options then you have debugging enabled.
mysqladmin ver also lists the
mysqld version as mysql ...
--debug in this case.
If you are using gcc or
egcs, the recommended
configure line is:
This avoids problems with the libstdc++
library and with C++ exceptions (many compilers have problems
with C++ exceptions in threaded code) and compile a MySQL
version with support for all character sets.
If you suspect a memory overrun error, you can configure MySQL
with --with-debug=full, which installs a memory
allocation (SAFEMALLOC) checker. However,
running with SAFEMALLOC is quite slow, so if
you get performance problems you should start
mysqld with the
--skip-safemalloc option. This disables the
memory overrun checks for each call to
malloc() and free().
If mysqld stops crashing when you compile it
with --with-debug, you probably have found a
compiler bug or a timing bug within MySQL. In this case, you can
try to add -g to the CFLAGS
and CXXFLAGS variables above and not use
--with-debug. If mysqld
dies, you can at least attach to it with gdb
or use gdb on the core file to find out what
happened.
When you configure MySQL for debugging you automatically enable
a lot of extra safety check functions that monitor the health of
mysqld. If they find something
“unexpected,” an entry is written to
stderr, which safe_mysqld
directs to the error log! This also means that if you are having
some unexpected problems with MySQL and are using a source
distribution, the first thing you should do is to configure
MySQL for debugging! (The second thing is to send mail to a
MySQL mailing list and ask for help. See
Section 1.7.1.1, “The MySQL Mailing Lists”. Please use the
mysqlbug script for all bug reports or
questions regarding the MySQL version you are using!
In the Windows MySQL distribution, mysqld.exe
is by default compiled with support for trace files.
E.1.2. Creating Trace Files
If the mysqld server doesn't start or if you
can cause it to crash quickly, you can try to create a trace
file to find the problem.
To do this, you must have a mysqld that has
been compiled with debugging support. You can check this by
executing mysqld -V. If the version number
ends with -debug, it's compiled with support
for trace files. (On Windows, the debugging server is named
mysqld-debug rather than
mysqld as of MySQL 4.1.)
Start the mysqld server with a trace log in
/tmp/mysqld.trace on Unix or
C:\mysqld.trace on Windows:
shell> mysqld --debug
On Windows, you should also use the
--standalone flag to not start
mysqld as a service. In a console window, use
this command:
C:\> mysqld-debug --debug --standalone
After this, you can use the mysql.exe
command-line tool in a second console window to reproduce the
problem. You can stop the mysqld server with
mysqladmin shutdown.
Note that the trace file become very
big! If you want to generate a smaller trace file,
you can use debugging options something like this:
This only prints information with the most interesting tags to
the trace file.
If you make a bug report about this, please only send the lines
from the trace file to the appropriate mailing list where
something seems to go wrong! If you can't locate the wrong
place, you can ftp the trace file, together with a full bug
report, to ftp://ftp.mysql.com/pub/mysql/upload/
so that a MySQL developer can take a look a this.
On most systems you can also start mysqld
from gdb to get more information if
mysqld crashes.
With some older gdb versions on Linux you
must use run --one-thread if you want to be
able to debug mysqld threads. In this case,
you can only have one thread active at a time. We recommend you
to upgrade to gdb 5.1 ASAP as thread debugging works much better
with this version!
NTPL threads (the new thread library on Linux) may cause
problems while running mysqld under
gdb. Some symptoms are:
mysqld hangs during startup (before it
writes ready for connections).
mysqld crashes during a
pthread_mutex_lock() or
pthread_mutex_unlock() call.
In this case you should set the following environment variable
in the shell before starting gdb:
LD_ASSUME_KERNEL=2.4.1
export LD_ASSUME_KERNEL
When running mysqld under
gdb, you should disable the stack trace with
--skip-stack-trace to be able to catch
segfaults within gdb.
In MySQL 4.0.14 and above you should use the
--gdb option to mysqld. This installs an
interrupt handler for SIGINT (needed to stop
mysqld with ^C to set
breakpoints) and disable stack tracing and core file handling.
It's very hard to debug MySQL under gdb if
you do a lot of new connections the whole time as
gdb doesn't free the memory for old threads.
You can avoid this problem by starting mysqld
with -O thread_cache_size= 'max_connections
+1'. In most cases just using -O
thread_cache_size=5' helps a lot!
If you want to get a core dump on Linux if
mysqld dies with a SIGSEGV signal, you can
start mysqld with the
--core-file option. This core file can be used
to make a backtrace that may help you find out why
mysqld died:
shell> gdb mysqld core
gdb> backtrace full
gdb> exit
If you have problems debugging threads with
gdb, you should download gdb 5.x and try this
instead. The new gdb version has very
improved thread handling!
Here is an example how to debug mysqld:
shell> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # Do this when mysqld crashes
If mysqld hangs you can try to use some
system tools like strace or
/usr/proc/bin/pstack to examine where
mysqld has hung.
strace /tmp/log libexec/mysqld
If you are using the Perl DBI interface, you
can turn on debugging information by using the
trace method or by setting the
DBI_TRACE environment variable.
E.1.4. Using a Stack Trace
On some operating systems, the error log contains a stack trace
if mysqld dies unexpectedly. You can use this
to find out where (and maybe why) mysqld
died. See Section 5.10.1, “The Error Log”. To get a stack trace, you
must not compile mysqld with the
-fomit-frame-pointer option to gcc. See
Section E.1.1, “Compiling MySQL for Debugging”.
If the error file contains something like the following:
mysqld got signal 11;
The manual section 'Debugging a MySQL server' tells you how to use a
stack trace and/or the core file to produce a readable backtrace that may
help in finding out why mysqld died
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack range sanity check, ok, backtrace follows
0x40077552
0x81281a0
0x8128f47
0x8127be0
0x8127995
0x8104947
0x80ff28f
0x810131b
0x80ee4bc
0x80c3c91
0x80c6b43
0x80c1fd9
0x80c1686
you can find where mysqld died by doing the
following:
Copy the preceding numbers to a file, for example
mysqld.stack.
Make a symbol file for the mysqld server:
nm -n libexec/mysqld > /tmp/mysqld.sym
Note that most MySQL binary distributions (except for the
"debug" packages, where this information is included inside
of the binaries themselves) ship with the above file, named
mysqld.sym.gz. In this case, you can
simply unpack it by doing:
This prints out where mysqld died. If
this doesn't help you find out why mysqld
died, you should make a bug report and include the output
from the above command with the bug report.
Note however that in most cases it does not help us to just
have a stack trace to find the reason for the problem. To be
able to locate the bug or provide a workaround, we would in
most cases need to know the query that killed
mysqld and preferable a test case so that
we can repeat the problem! See
Section 1.7.1.3, “How to Report Bugs or Problems”.
E.1.5. Using Log Files to Find Cause of Errors in mysqld
If mysqld dies or hangs, you should start
mysqld with --log. When
mysqld dies again, you can examine the end of
the log file for the query that killed
mysqld.
If you are using --log without a file name, the
log is stored in the database directory as
host_name.log In
most cases it is the last query in the log file that killed
mysqld, but if possible you should verify
this by restarting mysqld and executing the
found query from the mysql command-line
tools. If this works, you should also test all complicated
queries that didn't complete.
If you find the text mysqld restarted in the
error log file (normally named
hostname.err) you probably have found a
query that causes mysqld to fail. If this
happens, you should check all your tables with
myisamchk (see
Chapter 5, Database Administration), and test the queries
in the MySQL log files to see if one doesn't work. If you find
such a query, try first upgrading to the newest MySQL version.
If this doesn't help and you can't find anything in the
mysql mail archive, you should report the bug
to a MySQL mailing list. The mailing lists are described at
http://lists.mysql.com/, which also has links to
online list archives.
If you have started mysqld with
myisam-recover, MySQL automatically checks
and tries to repair MyISAM tables if they are
marked as 'not closed properly' or 'crashed'. If this happens,
MySQL writes an entry in the hostname.err
file 'Warning: Checking table ...' which is
followed by Warning: Repairing table if the
table needs to be repaired. If you get a lot of these errors,
without mysqld having died unexpectedly just
before, then something is wrong and needs to be investigated
further. See Section 5.2.1, “mysqld Command-Line Options”.
It's not a good sign if mysqld did die
unexpectedly, but in this case one shouldn't investigate the
Checking table... messages but instead try to
find out why mysqld died.
E.1.6. Making a Test Case If You Experience Table Corruption
If you get corrupted tables or if mysqld
always fails after some update commands, you can test whether
this bug is reproducible by doing the following:
Take down the MySQL daemon (with mysqladmin
shutdown).
Make a backup of the tables (to guard against the very
unlikely case that the repair does something bad).
Check all tables with myisamchk -s
database/*.MYI. Repair any wrong tables with
myisamchk -r
database/table.MYI.
Make a second backup of the tables.
Remove (or move away) any old log files from the MySQL data
directory if you need more space.
Start mysqld with
--log-bin. See
Section 5.10.4, “The Binary Log”. If you want to find a query
that crashes mysqld, you should use
--log --log-bin.
When you have gotten a crashed table, stop the
mysqld server.
Restore the backup.
Restart the mysqld server
without--log-bin
Re-execute the commands with mysqlbinlog
update-log-file | mysql. The update log is saved
in the MySQL database directory with the name
hostname-bin.#.
If the tables are corrupted again or you can get
mysqld to die with the above command, you
have found reproduceable bug that should be easy to fix! FTP
the tables and the binary log to
ftp://ftp.mysql.com/pub/mysql/upload/ and
enter it into our bugs system at
http://bugs.mysql.com/. (Please note that the
/pub/mysql/upload/ FTP directory is not
listable, so you'll not see what you've uploaded in your FTP
client.) If you are a support customer, you can use the
MySQL Customer Support Center
https://support.mysql.com/ to alert the MySQL
team about the problem and have it fixed as soon as
possible.
You can also use the script mysql_find_rows
to just execute some of the update statements if you want to
narrow down the problem.
E.2. Debugging a MySQL Client
To be able to debug a MySQL client with the integrated debug
package, you should configure MySQL with
--with-debug or
--with-debug=full. See
Section 2.8.2, “Typical configure Options”.
Before running a client, you should set the
MYSQL_DEBUG environment variable:
This causes clients to generate a trace file in
/tmp/client.trace.
If you have problems with your own client code, you should attempt
to connect to the server and run your query using a client that is
known to work. Do this by running mysql in
debugging mode (assuming that you have compiled MySQL with
debugging on):
If your client crashes at some 'legal' looking code, you should
check that your mysql.h include file matches
your MySQL library file. A very common mistake is to use an old
mysql.h file from an old MySQL installation
with new MySQL library.
E.3. The DBUG Package
The MySQL server and most MySQL clients are compiled with the DBUG
package originally created by Fred Fish. When you have configured
MySQL for debugging, this package makes it possible to get a trace
file of what the program is debugging. See
Section E.1.2, “Creating Trace Files”.
This section summaries the argument values that you can specify in
debug options on the command line for MySQL programs that have
been built with debugging support. For more information about
programming with the DBUG package, see the DBUG manual in the
dbug directory of MySQL source distributions.
It's best to use a recent distribution for MySQL 5.0 to get the
most updated DBUG manual.
You use the debug package by invoking a program with the
--debug="..." or the -#...
option.
Most MySQL programs have a default debug string that is used if
you don't specify an option to --debug. The
default trace file is usually
/tmp/program_name.trace on Unix and
\program_name.trace on Windows.
The debug control string is a sequence of colon-separated fields
as follows:
<field_1>:<field_2>:...:<field_N>
Each field consists of a mandatory flag character followed by an
optional ‘,’ and comma-separated
list of modifiers:
flag[,modifier,modifier,...,modifier]
The currently recognized flag characters are:
Flag
Description
d
Enable output from DBUG_<N> macros for the current state. May be
followed by a list of keywords which selects output only
for the DBUG macros with that keyword. An empty list of
keywords implies output for all macros.
D
Delay after each debugger output line. The argument is the number of
tenths of seconds to delay, subject to machine
capabilities. For example, -#D,20
specifies a delay of two seconds.
f
Limit debugging and/or tracing, and profiling to the list of named
functions. Note that a null list disables all functions.
The appropriate d or
t flags must still be given; this flag
only limits their actions if they are enabled.
F
Identify the source file name for each line of debug or trace output.
i
Identify the process with the PID or thread ID for each line of debug or
trace output.
g
Enable profiling. Create a file called dbugmon.out
containing information that can be used to profile the
program. May be followed by a list of keywords that select
profiling only for the functions in that list. A null list
implies that all functions are considered.
L
Identify the source file line number for each line of debug or trace
output.
n
Print the current function nesting depth for each line of debug or trace
output.
N
Number each line of debug output.
o
Redirect the debugger output stream to the specified file. The default
output is stderr.
O
Like o, but the file is really flushed between each
write. When needed, the file is closed and reopened
between each write.
p
Limit debugger actions to specified processes. A process must be
identified with the DBUG_PROCESS macro
and match one in the list for debugger actions to occur.
P
Print the current process name for each line of debug or trace output.
r
When pushing a new state, do not inherit the previous state's function
nesting level. Useful when the output is to start at the
left margin.
S
Do function _sanity(_file_,_line_) at each debugged
function until _sanity() returns
something that differs from 0. (Mostly used with
safemalloc to find memory leaks)
t
Enable function call/exit trace lines. May be followed by a list
(containing only one modifier) giving a numeric maximum
trace level, beyond which no output occurs for either
debugging or tracing macros. The default is a compile time
option.
Some examples of debug control strings that might appear on a
shell command line (the -# is typically used to
introduce a control string to an application program) are:
In MySQL, common tags to print (with the d
option) are enter, exit,
error, warning,
info, and loop.
E.4. Comments about RTS Threads
I have tried to use the RTS thread packages with MySQL but
stumbled on the following problems:
They use old versions of many POSIX calls and it is very tedious
to make wrappers for all functions. I am inclined to think that it
would be easier to change the thread libraries to the newest POSIX
specification.
Some wrappers are currently written. See
mysys/my_pthread.c for more info.
At least the following should be changed:
pthread_get_specific should use one argument.
sigwait should take two arguments. A lot of
functions (at least pthread_cond_wait,
pthread_cond_timedwait()) should return the
error code on error. Now they return -1 and set
errno.
Another problem is that user-level threads use the
ALRM signal and this aborts a lot of functions
(read, write,
open...). MySQL should do a retry on interrupt
on all of these but it is not that easy to verify it.
The biggest unsolved problem is the following:
To get thread-level alarms I changed
mysys/thr_alarm.c to wait between alarms with
pthread_cond_timedwait(), but this aborts with
error EINTR. I tried to debug the thread
library as to why this happens, but couldn't find any easy
solution.
If someone wants to try MySQL with RTS threads I suggest the
following:
Change functions MySQL uses from the thread library to POSIX.
This shouldn't take that long.
Compile all libraries with the
-DHAVE_rts_threads.
Compile thr_alarm.
If there are some small differences in the implementation,
they may be fixed by changing
my_pthread.h and
my_pthread.c.
Run thr_alarm. If it runs without any
“warning,” “error,” or aborted
messages, you are on the right track. Here is a successful run
on Solaris:
Main thread: 1
Thread 0 (5) started
Thread: 5 Waiting
process_alarm
Thread 1 (6) started
Thread: 6 Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6 Slept for 1 (1) sec
Thread: 6 Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6 Slept for 2 (2) sec
Thread: 6 Simulation of no alarm needed
Thread: 6 Slept for 0 (3) sec
Thread: 6 Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6 Slept for 4 (4) sec
Thread: 6 Waiting
process_alarm
thread_alarm
Thread: 5 Slept for 10 (10) sec
Thread: 5 Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6 Slept for 5 (5) sec
Thread: 6 Waiting
process_alarm
process_alarm
...
thread_alarm
Thread: 5 Slept for 0 (1) sec
end
E.5. Differences Between Thread Packages
MySQL is very dependent on the thread package used. So when
choosing a good platform for MySQL, the thread package is very
important.
There are at least three types of thread packages:
User threads in a single process. Thread switching is managed
with alarms and the threads library manages all
non-thread-safe functions with locks. Read, write and select
operations are usually managed with a thread-specific select
that switches to another thread if the running threads have to
wait for data. If the user thread packages are integrated in
the standard libs (FreeBSD and BSDI threads) the thread
package requires less overhead than thread packages that have
to map all unsafe calls (MIT-pthreads, FSU Pthreads and RTS
threads). In some environments (for example, SCO), all system
calls are thread-safe so the mapping can be done very easily
(FSU Pthreads on SCO). Downside: All mapped calls take a
little time and it's quite tricky to be able to handle all
situations. There are usually also some system calls that are
not handled by the thread package (like MIT-pthreads and
sockets). Thread scheduling isn't always optimal.
User threads in separate processes. Thread switching is done
by the kernel and all data are shared between threads. The
thread package manages the standard thread calls to allow
sharing data between threads. LinuxThreads is using this
method. Downside: Lots of processes. Thread creating is slow.
If one thread dies the rest are usually left hanging and you
must kill them all before restarting. Thread switching is
somewhat expensive.
Kernel threads. Thread switching is handled by the thread
library or the kernel and is very fast. Everything is done in
one process, but on some systems, ps may
show the different threads. If one thread aborts, the whole
process aborts. Most system calls are thread-safe and should
require very little overhead. Solaris, HP-UX, AIX and OSF/1
have kernel threads.
In some systems kernel threads are managed by integrating user
level threads in the system libraries. In such cases, the thread
switching can only be done by the thread library and the kernel
isn't really “thread aware.”