mysqld with valgrind

使用编译脚本编译MariaDB

现在进入源代码目录并执行符合你的配置的编译脚本,比如:

cd $maria-source-dir # ex: ~/repos/maria/trunk

BUILD/compile-pentium64-max           # 为64位intel/amd编译(带所有选项)
BUILD/compile-pentium-max             # 为32位pentum编译(带所有选项)

BUILD/compile-pentium64-debug-max     # 为64位intel/amd编译(带调试选项)  
BUILD/compile-pentium64-valgrind-max  # 为64位intel/amd编译测试(带valgrind)
注:Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。

这里有许多涵盖不同配置和处理器架构的编译脚本。

你可以在运行时加上 --print 选项,来查看编译脚本都做了什么。

在使用一个编译脚本编译MariaDB后,用以下的命令安装MariaDB:

sudo make install
手动编译MariaDB

如果没有相应的脚本,你也可以直接执行编译命令:

cd $maria-source-dir # ex: ~/repos/maria/trunk
BUILD/autorun.sh
./configure
make
sudo make install
如果使用上面的命令编译出现问题,你也可以通过下面的方法显示编译参数细节方便查询:

make VERBOSE=1
MariaDB starting with 5.5

关于cmake

MariaDB 5.5及更高版本使用cmake编译。autorun.sh脚本、配置脚本和Makefile都重新修改了,所以你仍然可以使用上面的命令作为书写(仍然建议您使用适当的编译脚本),只是已经和以前版本的方式不同了。

我们建议你需要上面的编译脚本,或者,一个较为理想的编译MariaDB的编译脚本,但你可以,如果你选择使用cmake命令手动编译MariaDB。以下是一个使用默认编译选项的简单例子:

cmake .
make
sudo make install
cmake的配置选项可以通过下面的命令显示:

cmake . -LH
下面是一个使用cmake置配选项的例子:

cmake . -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/mariadb
首次启动MariaDB

在安装MariaDB后(使用 sudo make install),但在第一次启动MariaDB之前应该先:

确保你安装MariaDB的目录为mysql用户所有。(如果用户不存在,你需要创建)
运行 mysql_install_db 脚本来生成所需的系统表。
范例:

# 下面假设“mysql”用户已经存在,并且MariaDB安装在 /usr/local/mysql
chown -R mysql /usr/local/mysql/
scripts/mysql_install_db --user=mysql
/usr/local/mysql/bin/mysqld_safe --user=mysql &
MariaDB until 5.3

最大化编译命令行

下面的配置命令行是我们在最大化编译时使用的(包含所有我们认为相关的选项),也是我们大多数二进制编译时所使用的:

./configure --prefix=/usr/local/mysql --enable-assembler \
--with-extra-charsets=complex  --enable-thread-safe-client  --with-big-tables \
--with-plugin-maria --with-aria-tmp-tables --without-plugin-innodb_plugin \
--with-mysqld-ldflags=-static --with-client-ldflags=-static --with-readline \
--with-ssl --with-plugins=max-no-ndb --with-embedded-server --with-libevent \
--with-mysqld-ldflags=-all-static  --with-client-ldflags=-all-static \
--with-zlib-dir=bundled --enable-local-infile
显示完整的选项列表:

./configure --help
测试MariaDB

你可以使用下面的任何一种方式来测试你编译的MariaDB

make test
或者

cd mysql-test ; ./mysql-test-run --force
上面的方法都是从源目录运行的,在运行之前没有必要 'sudo make install'

 

 

http://blog.chinaunix.net/uid-28364803-id-3508914.html

mysql bug#64624: 备库开启query cache后导致crash的分析 2012-11-10 23:50:11
分类: Mysql/postgreSQL
主库:mysql-5.1.48
备库:percona server 5.5.18(query cache on)

重现:
备库在valgrind下启动:
点击(此处)折叠或打开
valgrind --leak-check=full --trace-children=yes --log-file=$HOME/valgrind.1 ./bin/mysqld --defaults-file=my.s.s.cnf

主库上执行:
点击(此处)折叠或打开
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;

出错结果:
点击(此处)折叠或打开
Thread 21:
Conditional jump or move depends on uninitialised value(s)
    at 0x5A6743: Query_cache::send_result_to_client(THD*, char*, unsigned int) (sql_cache.cc:2051)
    by 0x5EDE27: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:5756)
    by 0x800B79: Query_log_event::do_apply_event(Relay_log_info const*, char const*, unsigned int) (log_event.cc:3398)
    by 0x800157: Query_log_event::do_apply_event(Relay_log_info const*) (log_event.cc:3166)
    by 0x572005: Log_event::apply_event(Relay_log_info const*) (log_event.h:1135)
    by 0x56B1A9: apply_event_and_update_pos(Log_event*, THD*, Relay_log_info*) (slave.cc:2351)
    by 0x56B6E9: exec_relay_log_event(THD*, Relay_log_info*) (slave.cc:2511)
    by 0x56D8F6: handle_slave_sql (slave.cc:3329)
    by 0x3A01806D63: start_thread (pthread_create.c:308)

原因分析:
理论上讲,只有SQL导致数据变更了才会写binlog,而select语句是不会被备库复制执行的,那为何备库在do_apply_event时会访问query cache?

因为mysql执行sql的入口是mysql_parse,对于从主库上复制过来的binlog,如果是SQL形式(DDL或者binlog format为statement),会进入mysql_parse,
而mysql_parse的逻辑是首先查看query cache,如果不能返回结果就执行mysql_execute_command,并且对于select query,之后还会将结果写到query cache.

在Query_cache::send_result_to_client函数中会对sql语句进行检查,如果不是SELECT语句会直接返回,检查逻辑如下:

点击(此处)折叠或打开
if (!((i + 2 < query_length) &&
    ((my_toupper(system_charset_info, sql[i]) == 'S' &&
      my_toupper(system_charset_info, sql[i + 1]) == 'E' &&
      my_toupper(system_charset_info, sql[i + 2]) == 'L') ||
     sql[i] == '/')))
{
  DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
  goto err;
}

因此,备库复制执行binlog时虽然会进入到query cache,但是由于它们不是SELECT QUERY会直接返回,其实并没有真正访问query cache,然而上述判断逻辑也有出现问题的时候,那就是类似这样的SQL:
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
会和SELECT一样继续往下执行...,直到:

点击(此处)折叠或打开
size_t db_len;
memcpy((char *) &db_len, (sql + query_length + 1), sizeof(size_t));
if (thd->db_length != db_len) <-- 出错!
{
  ...
  DBUG_PRINT("qcache", ("Current database has changed since start of query"));
  goto err;
}

这是因为memcpy读到的未初始化的数据!

在alloc_query中,query buffer的内存布局如下:
+-------+-------+----------------------------------------+-------+
| Query |db len |        db_name                         | FLAGS |
+-------+-------+----------------------------------------+-------+
其中db len类型为size_t,保存db_name的长度

send_result_to_client中的计算tot_length的方式可以说明

点击(此处)折叠或打开
tot_length= query_length + 1 + sizeof(size_t) + thd->db_length + QUERY_CACHE_FLAGS_SIZE;

而在Query_log_event::Query_log_event函数中,data buffer如下:(下面的接在上面之后)
+--------+-----------+------+------+---------+----+
| catlog | time_zone | user | host | db name | \0 |
+--------+-----------+------+------+---------+----+
+-------+----------------------------------------+-------+
| Query | uninitiatlized space of size of db len | FLAGS |
+-------+----------------------------------------+-------+
其中为query buffer分配的空间从Query开始,比较可知,相对于alloc_query中的缺少了db len部分(sizeof(size_t))

在将其传入到send_result_to_client函数中时,就导致了memecpy读取未初始化的数据,从而使得条件不满足而退出query cache,但是这并不会导致任何问题,因为备库执行binlog本该不访问query cache,由于memcpy只是copy了未初始化的数据(后面还有空间)而并没有访问NULL pointer,因此不会出现问题,而这也是重现crash比较困难的原因!

但是,这里存在一个隐患,如果读取的未初始化数据db_len正好和thd->db_length相同,那么Query_cache::send_result_to_client还将继续执行下去,直到...

点击(此处)折叠或打开
memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
     (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);

悲剧发生了...tot_length是按照alloc_query中的内存布局计算出来的,但是实际传给send_result_to_client的query是缺少一个字段的,于是memcpy访问越界,导致slave crash

mysql官方和percona都为此bug提供了patch,percona通过thd->alloc重新分配了一个query buffer,而mysql官方直接修改了bug的源头,都放进来。

patch:
http://bazaar.launchpad.net/~mysql/mysql-server/5.5/revision/3837
https://bugs.launchpad.net/percona-server/+bug/915814

 

posted @ 2016-07-05 15:48  zengkefu  阅读(784)  评论(0编辑  收藏  举报