本文为墨天轮数据库管理服务团队原创内容,如需转载请联系小墨(VX:modb666)并注明来源。
作者:蔡璐
墨天轮数据库管理服务团队技术顾问
十年数据库技术顾问经验,所服务的行业包括银行、消费、政企、电信运营商、制造业等;个人专项数据库领域:MySQL,PostgreSQL、openGauss,擅长数据库架构设计、容灾解决方案及数据库的日常管理、疑难故障诊断、性能优化、迁移升级改造等。
2.1 环境信息
2.2 查看11月27日awr日志中processlit及其他时间段processlist及系统负载和数据库负载
该insert执行较慢但未发现锁等待;查看其他时间段awr该sql 也有执行,但未发现执行时间长的问题;查看系统负载和数据库负载,系统负载和数据库负载都不高。

2.3 查看insert插入慢时间点的redo刷盘及缓冲池
insert插入慢时间点的redo刷盘及缓冲池状态都正常


2.4 检查数据库参数配置,未发现异常



2.5 检查出现慢sql时间点的事务记录,未发现锁等待

2.6 检查出现慢sql时间点SEMAPHORE信息即等待信号量(semaphore)
注意:该等待不是常规意义上的事务之间的锁等待,而是数据页或者内存结构上的的latch等待,所以在会话和事务上看不到锁等待。

2.7 查找信号量堵塞信息其中一个事务信息
通过被阻塞的tread 140147689268992 查找到对应的thread id 为27039902,在会话中即为客户发现的insert慢语句,确认insert 执行较慢的语句是因为等待140156298594048持有的latch锁导致阻塞


2.8 查找信号量堵塞信息堵塞源140156298594048对应的信息
查看140156298594048 ,但在awr和数据库中皆未查找到该tread对应的事务信息,猜测是数据库内部线程(通过对应的bug说明该进程为数据库后台收集表统计信息进程),inset堵塞较久是因为该表数据量较大超过8000W,所有后台线程收集统计信息持有的latch锁较长。
统计当前保留的awr中140156298594048出现的所有次数共300多次

2.9 验证其他时间点140156298594048出现时现象和本次insert堵塞是否一致
通过11月26日awr确认140156298594048该线程同样堵塞了其他的会话,和本次insert产生的堵塞现象完全一致;但因为堵塞的时间较短业务未产生明显感知;


2.10 通过jira查看MariaDB数据库bug列表
该问题普遍存在于mariadb多个版本:
该问题为后台线程在收集统计信息时锁定了索引页导致了insert在更新索引时等待数据页latch锁释放导致了偶尔会出现执行时间较长的问题;如果信号量等待600s超时可能会引起mysql服务crash。
3.1 通过信号量信息中latch等待给出的提示,分析MariaDB 10.3.27 源码文件`btr0cur.cc 1357行、ict0dict.cc 2130行、dict0stats.cc 1969行`如下:
case BTR_MODIFY_TREE:
/* Most of delete-intended operations are purging.
Free blocks and read IO bandwidth should be prior
for them, when the history list is glowing huge. */
if (lock_intention == BTR_INTENTION_DELETE
&& trx_sys.history_size() > BTR_CUR_FINE_HISTORY_LENGTH
&&buf_get_n_pending_read_ios()) {
x_latch_index:
mtr_x_lock_index(index, mtr);
} else if (index->is_spatial()
&& lock_intention <= BTR_INTENTION_BOTH) {
/* X lock the if there is possibility of
pessimistic delete on spatial index. As we could
lock upward for the tree */
goto x_latch_index;
} else {
mtr_sx_lock_index(index, mtr);
}
upper_rw_latch = RW_X_LATCH;
break;
dict0dict.cc 2130行:
#endif /* BTR_CUR_ADAPT */
new_index->page = unsigned(page_no);
rw_lock_create(index_tree_rw_lock_key,&new_index->lock,
SYNC_INDEX_TREE);
new_index->n_core_fields = new_index->n_fields;
dict_mem_index_free(index);
index = new_index;
return DB_SUCCESS;
}

dict0stats.cc 1969行
在获取索引树root节点前加SX锁
index and saves them to the index
members stat_n_diff_key_vals[], stat_n_sample_sizes[], stat_index_size and
stat_n_leaf_pages. This function can be slow.
@param[in] index index to analyze
@return index stats */
/* Release the X locks on the root page taken by btr_get_size() */
mtr.commit();
switch (size) {
case ULINT_UNDEFINED:
dict_stats_assert_initialized_index(index);
DBUG_RETURN(result);
case0:
/* The root node of the tree is a leaf */
size = 1;
}
result.n_leaf_pages = size;
mtr.start();
mtr_sx_lock_index(index,&mtr);
root_level = btr_height_get(index, &mtr);
n_uniq = dict_index_get_n_unique(index);
参考文档:
THE END

墨天轮从乐知乐享的数据库技术社区蓄势出发,全面升级,提供多类型数据库管理服务。墨天轮数据库管理服务旨在为用户构建信赖可托付的数据库环境,并为数据库厂商提供中立的生态支持。
服务官网:https://www.modb.pro/service

点击进入作者个人主页
本文分享自微信公众号 - 墨天轮(enmocs)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。