去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分析,根据上述的现象,参看了:https://baijiahao.baidu.com/s?id=1742728867212386956&wfr=spider&for=pc&qq-pf-to=pcqq.discussion
https://www.cnblogs.com/magicaltravel/p/7404936.html
我觉得就是字符集不匹配导致的不走索引。
相关知识:
查看当前的字符集配置: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优化器可能做隐式转换导致执行计划不正常,从而极大影响性能。