1、背景
线上数据库内存异常增长,导致数据库内存告警,问题追踪排查到数据库出现批量数据导入和慢查询。
2、故障出现
1)分析慢日志
a、由于没有符合查询条件的索引导致的慢SQL。
b、由于查询SQL复杂导致的慢查询。
2)将复杂查询提供给RD,并且对无索引的SQL添加索引
3)添加索引
表结构:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(10) NOT NULL,
`age` tinyint(4) NOT NULL,
`is_del` bit(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
增加name和is_del联合索引:
alter table test add index idx_name_is_del(name,is_del);
4)前端业务出现通过name 和 is_del 过滤数据为空(索引添加前过滤正常)
5)删除联合索引idx_name_is_del,业务恢复
3、故障原因分析:
业务SQL:
select * from test where name=‘liu’ and is_del='0';
原因分析:
对于bit 类型的数值
不使用索引时:mysql 检索bit的值是不管是数值还是字符,mysql会对where 条件进行类型转化,将字符转换为数值,并比较数值对应的ascii码,如果值为1,则返回结果,否则,结果为空。
select * from test where name=‘liu’ and is_del='0';
分析:数据库中数据存储的为数值对应的ascii码
is_del='0' //字符'0' 转换为数值0,数值0对的应的ascii码与 is_del对比
############################
使用索引时:bit位在索引中存储的格式是二进制类型,即'0'/'1'bit位,且不会对字符串进行数值转换。
select * from test where name=‘liu’ and is_del='0';
分析:索引中数据的存储为二进制类型 b'0' 或者 b'1'
is_del='0' //字符'0' 对应的数值是48,对应的二进制是'00110000'
所以可得条件始终为假