去o形式所逼,哪天您用mysql了,尤其是并发量大的情况下,您肯定也会遇到类似的性能问题,分享此记录仅供参考。
原库为oracle11.2.0.4,新mysql生产环境版本:mysql 8.0.29 centos linux release 7.4.1708 (core)
mysql的源码安装可参考以前写过的一篇文章:https://www.modb.pro/db/450057
1.故障现象:
说实话mysql这块经验较少,用户要求分批迁移割接用户上线(一定用户量3000个后,系统性能明显扛不住了,所以暂时割接部分用户达可承受阶段)后发现原先在oracle上0.01秒执行的存储过程,在mysql竟然需要3以上秒,有时甚至50多秒。
2.故障分析:
看慢语句评估rows_examined:25559(在2-3万条记录左右),明显走了全表扫描。如果走索引,自然不会超过2条。
,但提取单条语句explain查看执行计划却是能走索引。
明显不正常,怀疑是否有参数配置不合适???
尝试分析相关表,并不起作用:analyze local table test_table;
只能继续baidu,google分析,根据上述的现象,参看了:
我觉得就是字符集不匹配导致的不走索引。
相关知识:
查看当前的字符集配置:character_set_client,character_set_connection,character_set_server都是utf8mb3,而character_set_server是utf8mb4
查看表配置:其中字段是utf8,而表是utf8mb4
查看存储过程配置:
3.故障处理:
开发人员根据建议,做了相关调整测试:
mysql参数文件参考:(以后初始化就参考该参数文件即可)
[client]
port=3307
socket=/home/mysql/mysql.sock
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
port=3307
user=mysql
socket=/home/mysql/mysql.sock
basedir=/home/mysql/mysql
datadir=/home/mysql/data
lower-case-table-names=1 #不区分大小写
default_authentication_plugin=mysql_native_password
#skip-grant-tables
innodb_buffer_pool_size=100g #物理内存256g足够,根据情况调
slow_query_log=on #开启记录慢日志
slow_query_log_file=/home/mysql/data/radiusp-slow.log #开启记录慢sql文件
long_query_time=2 #日志记录超过2秒的慢sql
log_queries_not_using_indexes=off
max_connections=1000 #根据情况调
innodb_flush_log_at_trx_commit=2 #提升写性能,默认是1
skip-log-bin #单机没用到恢复,主从,所以取消
#以下最关键字符集设置
character_set_server=utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='set names utf8mb4'
skip-character-set-client-handshake = true
建库参考:
create database testdb default character set utf8mb4 collate utf8mb4_0900_ai_ci;
建表参考(注意字段设置字符集):
create table test_table (
`acctsessionid` varchar(60) character set utf8mb4 collate utf8mb4_0900_ai_ci default null,
`loginname` varchar(30) character set utf8mb4 collate utf8mb4_0900_ai_ci default null,
`recdate` varchar(20) character set utf8mb4 collate utf8mb4_0900_ai_ci default null,
`nasport` varchar(16) character set utf8mb4 collate utf8mb4_0900_ai_ci default null,
`framedip` varchar(20) character set utf8mb4 collate utf8mb4_0900_ai_ci default null,
unique key `currsession_pk` (`acctsessionid`) using btree,
key `currsession_loginname` (`loginname`) using btree,
key `currsession_recdate` (`recdate`) using btree
) engine=innodb default charset=utf8mb4 collate=utf8mb4_0900_ai_ci row_format=dynamic;
检查配置命令:
show variables like 'charater%';
show table status like 'test_table' \g
show procedure status like 'p_test' \g
show create table test_table \g
show create procedure p_test \g
下图是最终正常结果:
4.处理结果:
最终0.01秒返回结果,效率极大提升从300~5000倍不等,不单是存储过程性能问题解决了,还有原先调用自定义函数的sql性能(改表字段字符集之前也超2秒)也正常了,慢语句不再出现。后续可安排割接更多用户到此环境了。
经过此次教训:发现mysql环境务必保证客户端、服务器端、库、表、字段等字符集设置一致,否则mysql优化器可能做隐式转换导致执行计划不正常,从而极大影响性能。