技术分享 | 大事务阻塞 show master status

风风火火
• 阅读 1128

作者:王福祥

爱可生 DBA 团队成员,负责客户的数据库故障处理以及调优。擅长故障排查及性能优化。对数据库相关技术有浓厚的兴趣,喜欢分析各种逻辑。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


MySQL 主从复制功能可以搭建从库来为 MySQL 创建一套在线的备份系统,但是自身不能独立实现切换;需要借助第三方高可用工具。然而当自身有大事务在运行时会阻塞一些 show 语句;例如“show master status”,造成误判。

场景模拟

1、构造两千万行数据,以事务的形式删除

技术分享 | 大事务阻塞 show master status

2、新建会话执行 show master status ,在 sql 语句运行期间执行成功。在 commit 期间被阻塞。

技术分享 | 大事务阻塞 show master status

3、show master status 处于 starting 状态,也就是语句开始执行的第一个阶段,启动阶段,准备资源。

技术分享 | 大事务阻塞 show master status

4、查看 stack 信息,show master status 是在获取 lock_log 锁时被阻塞

#6  0x0000000000ee8278 in MYSQL_BIN_LOG::get_currrent_log (this=0x1e839c0 <mysql_bin_log>, linfo=0x7f3ea82e62d0, need_lock_log=<optimized out>) at /export/home/pb2/build/sb_0-32013917-1545390211.74/mysql-5.7.25/sql/binlog.cc:5514
......
#6  0x0000000000eef824 in MYSQL_BIN_LOG::change_stage (this=<optimized out>, thd=<optimized out>, stage=<optimized out>, queue=<optimized out>, leave_mutex=<optimized out>, enter_metux=0x1e839c8 <mysql_bin_log+8>) at /export/home/pb2/build/sb_0-32013917-1545390211.74/mysql-5.7.25/sql/binlog.cc:9170

5、最终因事务过大,最终 show master status 超时,导致了故障切换。

其原因为 commit 与 show master status 之间的阻塞等待现象,接下来分析一下原因。

原因分析:commit

commit 流程分为以下几个阶段(以5.7.25为例),为原子性操作,一次性写入。

1、prepare 阶段主要作用为刷 redo 、undo ;此时 binlog 只涉及到一些准备动作。参照 binlog_prepare 函数。

static int binlog_prepare(handlerton *hton, THD *thd, bool all)
{
  DBUG_ENTER("binlog_prepare");
  if (!all)
  {
    thd->get_transaction()->store_commit_parent(mysql_bin_log.
      m_dependency_tracker.get_max_committed_timestamp());

  }

2、flush 阶段主要作用为持久化 redo ;获取 lock_log 锁阻塞其他组事务写入,以及生成 flush 队列(第一个事务为 leader ,随后为 follower )以及写入 binlog ,此时是内存写但不刷盘,参照 process_flush_stage_queue 函数

int
MYSQL_BIN_LOG::process_flush_stage_queue(my_off_t *total_bytes_var,
                                         bool *rotate_var,
                                         THD **out_queue_var)
{
  DBUG_ENTER("MYSQL_BIN_LOG::process_flush_stage_queue");
  #ifndef DBUG_OFF
  // number of flushes per group.
  int no_flushes= 0;
  #endif
  DBUG_ASSERT(total_bytes_var && rotate_var && out_queue_var);
  my_off_t total_bytes= 0;
  int flush_error= 1;
  mysql_mutex_assert_owner(&LOCK_log);

3、sync 阶段作用为释放 lock_log 锁,获取 lock_sync 锁阻塞其他事务组刷盘,并根据 sync_binlog 决定刷盘策略。

 if (change_stage(thd, Stage_manager::SYNC_STAGE, wait_queue, &LOCK_log, &LOCK_sync))
  {
    DBUG_PRINT("return", ("Thread ID: %u, commit_error: %d",
                          thd->thread_id(), thd->commit_error));
    DBUG_RETURN(finish_commit(thd));
  }

4、commit 阶段释放 lock_sync 锁,获取 lock_commit 锁并等待 follower 事务提交,提交后释放该锁以及清空 binlog 缓存以及判断是否刷新并归档 binlog

原因分析:show master status

show master status 其作用为从最后一份 binlog 文件中获取 Executed_Gtid 信息以及该 binlog 所执行的gtid信息。其函数入口为:https://github.com/mysql/mysq... 624行并获取 lock_log 锁:

int MYSQL_BIN_LOG::get_current_log(LOG_INFO* linfo, bool need_lock_log/*true*/)
{
  if (need_lock_log)
    mysql_mutex_lock(&LOCK_log);
  int ret = raw_get_current_log(linfo);
  if (need_lock_log)
    mysql_mutex_unlock(&LOCK_log);
  return ret;
}

结论

案例中的例子是单个大事务,因此不涉及组提交的 sync 阶段,从 commit(flush 阶段)以及 show master status 的步骤中可以看出,两步操作之间的阻塞原因为 lock_log 锁的争用引起的,该锁的性质为 lock_log 日志锁,而并非MDL以及引擎层锁,如果事务越大,flush 阶段写入 binlog 期间以及持有锁的时间就会越长;从而阻塞其他事务提交以及 binlog 的 show 操作,因此对应的解决方案为:

1、大事务会造成io暴涨、主从延时以及事务阻塞等问题,在 MGR 环境中甚至会造成复制中断,mysql 需要避免大事务。

2、binlog 是持续在变化的文件,show master status 语句可改为 select @@global.gtid_executed ;来获取 GTID 信息。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
P2P技术如何拯救一家直播网站
!(https://oscimg.oschina.net/oscnet/23810a4a1fef4d659388100f4228782b.jpg)众所周知运维成本是直播网站最大的成本组成,运维成本则主要体现在带宽,而伴随主播与用户对视频清晰度以及连麦的需求不断提升,直播带宽也在与日俱增。本文整理自学霸君音视频技术负责人袁荣喜在LiveVi
Wesley13 Wesley13
3年前
Java中Class对象详解
<divclass"htmledit\_views"id"content\_views"<phttps://blog.csdn.net/mcryeasy/article/details/52344729<br</p<p待优化整理总结</p<p</p<h1style"padding:0px;fontfamily:'apple
Stella981 Stella981
3年前
IE iframe cookie问题(p3p)
前段时间碰到一个问题,就是在IE下,使用iFrame嵌入页面时,该页面的会话级别的cookie无法写入,导致服务端始终无法获取JSESSIONID,每次都是产生一个新的,使得Session无法使用。只需要设置P3PHTTPHeader,在隐含iframe里面跨域设置cookie就可以成功。ASP直接在头部加了头部申明,测试有效。
Wesley13 Wesley13
3年前
P2P技术详解(三):P2P中的NAT穿越(打洞)方案详解(进阶分析篇)
1、引言接本系列的上一篇《P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解(基本原理篇)(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Flinks.jianshu.com%2Fgo%3Fto%3Dhttp%253A%252F%252Fwww.52im
Stella981 Stella981
3年前
DBeaver笔记
<divclass"markdown\_views"<p公司使用的是PostgreSQL数据库,可以使用pgAdmin或者DBeaver进行连接该数据库。个人更喜欢用DBeaver,因为其界面更加美观,操作也相对简单。对于习惯了eclipse的开发者来说,DBeaver绝对是个不错的选择。</p<blockquote<pDBeaver
Stella981 Stella981
3年前
ASMSupport教程4.2
<h24.2生成Return操作</h2<p这一节我们将讲述如何生成return操作,我们将生成如下代码:</p<divstyle"paddingbottom:0px;margin:0px;paddingleft:0px;paddingright:0px;display:inline;float:none;pa
Wesley13 Wesley13
3年前
P2P技术揭秘.P2P网络技术原理与典型系统开发
Modular.Java(2009.06)\.Craig.Walls.文字版.pdf:http://www.t00y.com/file/59501950(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.t00y.com%2Ffile%2F59501950)\More.E
Wesley13 Wesley13
3年前
HP
本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/clb929/article/details/51085983\HPSocket官方网站:http://www.jessma.org\HPSocket项目主页:http://www.oschina.net/p/hpsocket\HP
Stella981 Stella981
3年前
JFinal使用笔记2
大部分步骤按cf官方的教程就可以了。遇到的问题如下:1、使用C3p0Plugin配置数据库连接,代码如下//配置C3p0数据库连接池插件//C3p0Pluginc3p0PluginnewC3p0Plugin(getProperty("jdbcUrl"),getProperty("user"),getP
Wesley13 Wesley13
3年前
CDN+P2P在大规模直播&实时直播的技术实践
摘要:本次分享将介绍爱奇艺多类型的直播业务现状,以及直播整体技术架构和客户端直播网络模块Livenet的实现。回顾直播技术顺应业务多样化的演进过程,包括从偏P2P架构发展到结合CDN&P2P混合架构,为多端适配而实现的多协议支持和切换等演变,直播P2P和直播推流SDK的技术实现等。演讲/周志伟整理/LiveVideoStack
Stella981 Stella981
3年前
Neo4j 的一些使用心得
<divclass"htmledit\_views"id"content\_views"<p<br</p<p<spanstyle"color:rgb(70,70,70);fontfamily:simsun;fontsize:14px;lineheight:21px;"由对图数据的处理需求,看到了图数据库(GraphData
风风火火
风风火火
Lv1
你所见即我,好与坏都不反驳。
文章
5
粉丝
0
获赞
0