MySQL开发

本文详细介绍了MySQL的调试技巧,包括开启Debug日志、使用GDB进行core文件调试、测试用例集的执行以及GDB调试官方PATCH的定位。此外,还分享了如何将多个git commit合并为一个,以及常见MySQL故障的处理方法,如调整innodb_force_recovery参数等。

 

一.开启Debug日志

MySQL提供了trace机制方便定位

1.cmake时要开启编译选项-DWITH_DEBUG=1 -DCMAKE_BUILD_TYPE=Debug这两个参数

2.设置trace日志的路径,export MYSQL_DEBUG=d:t:O,/tmp/client.trace。如果不配置,默认保存在tmp/mysql.trace

3.mysql启动的时候,需要增加--debug参数,如:bin/mysqld --defaults-file=../etc/my_8130.cnf --debug

4.由于是处于调试模式,建议一个链接一个线程,即修改配置文件,配置:thread_handling =   0

5.开启trace日志后,可以利用 DBUG_PRINT("info", ("get_first_used_partition:%d",part_id)); 宏来调试输出

 

二、GDB调试

core文件调试

bt获取到调用堆栈后

f 数字:进入对于的函数堆栈

p 变量:变量如果是指针需要带*,对于this指针,p *this会打印出变量的结构体

打印变量格式化:set print pretty on

 

attach调试

1.attach pid 

2.设置断点,基于原函数  比如:b Item_func_murmurHashCodeAndMod::val_int

3.继续向下执行 c

4.触发断点后,执行bt

5.需要向下单步调试s(或者c直接向下执行)

6.清除所有断点:

先查看所有断点:info break

删除单个断点:delete 1 删除#1断点

删除所有断点:delete break

 

三.MySQL测试用例集

首先cmake的时候需要增加参数 -DINSTALL_MYSQLTESTDIR=${路径}

这个路径一般都放在和bin目录平级的目录,再cmake install说的时候自动安装拷贝到该目录

 

./mtr      执行所有的测试用例集

./mtr --suite="tdsql_hide_partitions"     执行suite目录下tdsql_hide_partitions目录下所有的测试集

./mtr --do-test="binlog_xa_prepared_disconnect" 执行t/目录下对于的test文件,如mysql-test/t/binlog_xa_prepared_disconnect.test

./mtr --mysqld="--lock_wait_timeout=100"     指定超时参数

注意:

1.mtr执行的时候可能会遇到result文件和实际执行结果是一样的,但是由于wiondws和unix下的换行编码问题,导致md5不一样,需要对windows下的result文件中的回车做转码处理:sed -i 's/\r//' 文件

2.mtr会在mysql-test/var/log下创建一个msyql临时实例用来测试

 

q其他参数:

nowarnings:mysql-test执行的时候遇到mysql错误日志中的warnings也会自动停止,所以我们一般要带上--nowarnings参数;

big-test:某些被标记为”big“的测试用例默认是不执行的,所以我们一般也带上参数--big-test;

force:一般情况下,一旦有测试用例失败mtr会自动退出,所以我们一般加上--force参数,发生错误后强制继续向下执行;

mysqld:指定mysqld启动的默认参数: --mysqld="--innodb_buffer_pool_size=3355648"

其他:--max-test-fail=1000  --retry-failure=0 --suite-timeout=600 --retry-failure=1 --testcase-timeout=10这几个参数顾名思义,是增加超时、容错以及重试的,建议也加上。

 

 ./mtr --parallel=8 --force --max-test-fail=1000  --retry-failure=0 --suite-timeout=600 --retry-failure=1 --testcase-timeout=10  --big-test --nowarnings  --mysqld="--innodb_buffer_pool_size=3355648" --suite="binlog"

./mtr --parallel=8 --force --max-test-fail=1000  --retry-failure=0 --suite-timeout=600 --retry-failure=1 --testcase-timeout=10  --big-test --nowarnings  --mysqld="--innodb_buffer_pool_size=3355648" --do-test="binlog_xa_prepared_disconnect"

 

对于跑失败的用例,分析其输出和r/*.result文件的内容对比,定位失败的原因。

参考资料:

https://www.jianshu.com/p/a2b4ccd14626

https://blog.csdn.net/yunqishequ1/article/details/51882952

https://www.iteye.com/blog/dinglin-804798


 

四.GDB调试&&官方PATCH定位

一般core问题都会有一个调用堆栈

#0  0x00007f57ac4158ac in pthread_kill () from /lib64/libpthread.so.0
#1  0x000000000078a23b in handle_fatal_signal (sig=11) at /data/home/jenkins/jobs/526/workspace/dev/mariadb-10.1.9/sql/signal_handler.cc:273
#2  <signal handler called>
#3  0x000000000060178c in part_of_refkey (root_cond=<value optimized out>, left_item=<value optimized out>, right_item=0x7f5645107a68)
    at /data/home/jenkins/jobs/526/workspace/dev/mariadb-10.1.9/sql/sql_select.cc:20375
    
#4  test_if_ref (root_cond=<value optimized out>, left_item=<value optimized out>, right_item=0x7f5645107a68)
    at /data/home/jenkins/jobs/526/workspace/dev/mariadb-10.1.9/sql/sql_select.cc:20003


一般找到最后一个调用堆栈的函数,搜索比如mysql bug part_of_refkey,或者mariadb bug part_of_refkey,通过google可以找到

找到bug之后,继续寻找patch

这里点开就是github上关于patch的说明,点开链接后查看内容

将url的末尾追加.patch,就是可以直接下载的patch

如果合并patch时报错,观察一下如果是mysqltest问题则可以忽略,如果代码问题则需要看懂patch手动合并。

 

 

五.git多个commit合并为一个

内核开发的时候经常会发现第一次commit之后,又发现bug结果多了一次commit,导致别人代码review时非常费劲

因而需要多个commit合并为一个

将前3个commit合并为一个

git rebase -i HEAD~3 

之后,会弹出一个vim,从上到下分别是第一次、第二次、第三次提交

将后两个pack改为s,保存vim退出

进入到另外一个日志窗口,会把第一次、第二次、第三次的commit log都list出来,我们可以修改(这里#注释不用管)

最后保存vim退出

git push -f

 

六.其他

mysql锁依赖关系查询

SELECT  
    r.trx_id waiting_trx_id,  
    r.trx_mysql_thread_id waiting_thread,  
    TIMESTAMPDIFF(  
        SECOND,  
        r.trx_wait_started,  
        CURRENT_TIMESTAMP  
    ) wait_time,  
    r.trx_query waiting_query,  
    l.lock_table waiting_table_lock,  
    b.trx_id blocking_trx_id,  
    b.trx_mysql_thread_id blocking_thread,  
    SUBSTRING(  
        p. HOST,  
        1,  
        INSTR(p. HOST, ':') - 1  
    ) blocking_host,  
    SUBSTRING(p. HOST, INSTR(p. HOST, ':') + 1) blocking_port,  
  
IF (p.COMMAND = 'Sleep', p.TIME, 0) idel_in_trx,  
 b.trx_query blocking_query  
FROM  
    information_schema.INNODB_LOCK_WAITS w  
INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id  
INNER JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_id  
INNER JOIN information_schema.INNODB_LOCKS l ON w.requested_lock_id = l.lock_id  
LEFT JOIN information_schema. PROCESSLIST p ON p.ID = b.trx_mysql_thread_id  
ORDER BY  
    wait_time DESC;

 

 

七.常见mysql故障处理以及问题处理

1.数据库强制启动,如果innodb文件损坏,或者遇到其他故障需要强制启动则修改innodb_force_recovery,调整对应的级别数字越大跳过的检查越多。innodb_force_recovery = 6
1(SRV_FORCE_IGNORE_CORRUPT):忽略检查到的corrupt页。
2(SRV_FORCE_NO_BACKGROUND):阻止主线程的运行,如主线程需要执行full purge操作,会导致crash。
3(SRV_FORCE_NO_TRX_UNDO):不执行事务回滚操作。
4(SRV_FORCE_NO_IBUF_MERGE):不执行插入缓冲的合并操作。
5(SRV_FORCE_NO_UNDO_LOG_SCAN):不查看重做日志,InnoDB存储引擎会将未提交的事务视为已提交。
6(SRV_FORCE_NO_LOG_REDO):不执行前滚的操作。

2.对于文件读写的错误,比较典型的是:InnoDB: File(unknow):'read' returned OS error 122
对于此类错误,一般通过调整innodb_flush_method参数可以解决(注释掉innodb_flush_method = O_DIRECT)

3.数据库输盘参数,对于写压力测试往往IO成为瓶颈,通过调整以下参数可以降低IO的开销
sync_binlog 默认为0,操作系统负责刷新mysql不负责刷新,重启机器会导致binlog丢失。强一致场景设置为1,每次强制刷盘。
innodb_flush_log_at_trx_commit 默认为2,由操作系统刷新,mysql不刷新,重启机器会导致redo丢失。强一致默认为1,每次强制刷盘。

4.对于cpu性能分析,一般比较常用的指令是perf top -p ${pid}

5.自动清理binlog,通过设置参数expire_logs_days=3

6.常用的工具集合

sysben压力测试工具

./sysbench --test=tests/db/oltp.lua --mysql-table-engine=innodb  --mysql-engine-trx=yes --oltp-table-size=10000 --mysql-user="${user}" --mysql-password="${password}" --mysql-db=test --mysql-host=${ip}  --mysql-port=24002 --oltp_tables_count=10 prepare

./sysbench --test=tests/db/oltp.lua --mysql-table-engine=innodb --mysql-engine-trx=yes --oltp-table-size=500000000 --mysql-user="${user}" --mysql-password="${password}" --mysql-db=test  --mysql-host=${ip}   --mysql-port=24002 --oltp-test-mode=complex --num-threads=100 --oltp_tables_count=10  --report-interval=5 --max-time=720 --max-requests=0 run

./sysbench --test=tests/db/oltp.lua --mysql-table-engine=innodb --mysql-engine-trx=yes --oltp-table-size=500000000 --mysql-user="${user}" --mysql-password="${password}" --mysql-db=test  --mysql-host=${ip}   --mysql-port=24002  --oltp_tables_count=10 cleanup

tpcc测试

./tpcc_load ${ip}:${port} tpcctest "${user}" "${password}" 10
./tpcc_start -h${ip} -P${port} -d tpcctest -u "${user}" -p "${password}" -w 10 -c 10 -r 120 -l 120

checksum

./pt-table-checksum --replicate=test.checksum --no-check-binlog-format --socket='/data/tdengine/data/4021/prod/mysql.sock' --user='${user}' --password='${password}'

SELECT db, tbl, CONCAT(db, '.', tbl) AS `table`, chunk, chunk_index,  lower_boundary, upper_boundary, COALESCE(this_cnt-master_cnt, 0)  AS cnt_diff, COALESCE(this_crc <> master_crc OR ISNULL(master_crc) <> ISNULL(this_crc), 0)  AS crc_diff, this_cnt, master_cnt, this_crc, master_crc FROM test.checksum  WHERE master_cnt <> this_cnt OR master_crc <> this_crc OR ISNULL(master_crc) <> ISNULL(this_crc)

pt-query-digest

./pt-query-digest --since="2016-01-22 00:00:00" --until="2016-01-22 12:00:00" --output=json

mydumper

./mydumper --host=${ip} --port=4020 --user="${user}" --password="${password}" --events --routines --triggers --less-locking --ignore-sysdb=1 --chunk-filesize=512 --complete-insert --db-list=cstsdb --outputdir=./backup_dir

./myloader --user=""${user}"sys_kp_new" --password="4^GAs10Ii0veS&9WaIUv" -h 10.231.136.34 --directory="/tmp/backup" -o  --enable-binlog

mysqldump

./mysqldump   -q  --default-character-set=utf8 --hex-blob   --skip-add-locks --skip-add-drop-table   --skip-lock-tables  -v --master-data=2 --single-transaction=1 --skip-disable-keys -c --skip-extended-insert  -u'{user}'  -p'{pass}' -h{ip} -P3306 --where"" db table >localfile.sql

pt-online-schema-change 

./pt-online-schema-change --user=${user} -p ${password} --socket=/data/4002/prod/mysql.sock --no-check-replication-filters --alter=CHARACTER SET utf8  COLLATE utf8_bin D=seven,t=t --noanalyze-before-swap --critical-load=Threads_running=800 --execute

跳过gtid

stop slave sql_thread;set global gtid_slave_pos = '+1';start slave sql_thread;
SET SESSION GTID_NEXT = '1b0c6d04-b349-11e9-b7ab-6c92bf6285f4:20289131';begin;commit

slave-skip-errors=1053,1146 #跳过指定类型的错误
slave-skip-errors=all #跳过所有错误

跳过权限表

skip-grant-tables

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值