开发者社区> 重庆八怪> 正文

MySQL:Innodb 关于Handler_commit每次DML增加2的原因

简介: 简单描述一下,也是本人的问的,水平有限,如果有误请谅解。 原问题如下@mysqDBA: 请教一个问题。我每次insert一条语句,查询show global status like 'Handler_commit'; 发现每次增加值是2,难道不应该是1吗? 最简单的insert into tab.
+关注继续查看

简单描述一下,也是本人的问的,水平有限,如果有误请谅解。


原问题如下@mysqDBA:

请教一个问题。我每次insert一条语句,查询show global status like 'Handler_commit'; 发现每次增加值是2,难道不应该是1吗?

最简单的insert into table a values(1);

一、问题展示

语句如下:

mysql> flush status;
Query OK, 0 rows affected (0.10 sec)

mysql> set  sql_log_bin=1;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into testm values(16,'gaopeng',34);
Query OK, 1 row affected (0.15 sec)

mysql> show status like '%commit%';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| Com_commit     | 0     |
| Com_xa_commit  | 0     |
| Handler_commit | 2     |
+----------------+-------+
3 rows in set (0.01 sec)

问为什么 Handler_commit是2而不是1。

二、原因分析

其实对于这个问题只要看看这个Handler_commit指标增加的方式就可以看出原因。实际上这个指标出现在ha_commit_low函数中如下:

for (; ha_info; ha_info= ha_info_next)
    {
      int err;
      handlerton *ht= ha_info->ht();
      if ((err= ht->commit(ht, thd, all)))
      {
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
        error=1;
      }
      DBUG_ASSERT(!thd->status_var_aggregated);
      thd->status_var.ha_commit_count++; //此处增加
      ha_info_next= ha_info->next();
      if (restore_backup_ha_data)
        reattach_engine_ha_data_to_thd(thd, ht);
      ha_info->reset(); /* keep it conveniently zero-filled */
    }

可以清楚的看到ha_commit_count实际就是调用ht->commit的次数,由于有多个Handler的存在,因此这里需要调用多次。对于开启binlog+innodb的这种结构来讲分别要做:

  • binlog的commit
  • Innodb的commit

后面会看到实际binlog的commit什么都没做,但是这是一种协议。
那么如果我们关闭binlog可以发现Handler_commit为1了如下:



mysql> set  sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into testm values(15,'gaopeng',34);
Query OK, 1 row affected (0.10 sec)

mysql>  show status like '%commit%';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| Com_commit     | 0     |
| Com_xa_commit  | 0     |
| Handler_commit | 1     |
+----------------+-------+
3 rows in set (0.01 sec)

三、binlog commit栈帧

#0  binlog_commit (hton=0x3485e30, thd=0x7fff2c014430, all=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:1833
#1  0x0000000000f64104 in ha_commit_low (thd=0x7fff2c014430, all=false, run_after_commit=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/handler.cc:1923
#2  0x000000000185772b in MYSQL_BIN_LOG::process_commit_stage_queue (this=0x2e01c80, thd=0x7fff2c014430, first=0x7fff2c014430)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8647
#3  0x0000000001858f5d in MYSQL_BIN_LOG::ordered_commit (this=0x2e01c80, thd=0x7fff2c014430, all=false, skip_commit=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9318
#4  0x000000000185700c in MYSQL_BIN_LOG::commit (this=0x2e01c80, thd=0x7fff2c014430, all=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8440
#5  0x0000000000f63df8 in ha_commit_trans (thd=0x7fff2c014430, all=false, ignore_global_read_lock=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/handler.cc:1818

但是实际上binlog_commit什么都没做,因为在此之前他已经做完了需要做的事情比如flush、sync等

static int binlog_commit(handlerton *hton, THD *thd, bool all)
{
  DBUG_ENTER("binlog_commit");
  /*
    Nothing to do (any more) on commit.
   */
  DBUG_RETURN(0);
}

四、Innodb commit接口

#0  innobase_commit (hton=0x2e9edd0, thd=0x7fff2c014430, commit_trx=false) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/handler/ha_innodb.cc:4652
#1  0x0000000000f64104 in ha_commit_low (thd=0x7fff2c014430, all=false, run_after_commit=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/handler.cc:1923
#2  0x000000000185772b in MYSQL_BIN_LOG::process_commit_stage_queue (this=0x2e01c80, thd=0x7fff2c014430, first=0x7fff2c014430)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8647
#3  0x0000000001858f5d in MYSQL_BIN_LOG::ordered_commit (this=0x2e01c80, thd=0x7fff2c014430, all=false, skip_commit=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9318
#4  0x000000000185700c in MYSQL_BIN_LOG::commit (this=0x2e01c80, thd=0x7fff2c014430, all=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8440
#5  0x0000000000f63df8 in ha_commit_trans (thd=0x7fff2c014430, all=false, ignore_global_read_lock=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/handler.cc:1818

实际上innodb comit才是需要真正做的,这里包含一些事情要做,比如事物状态的改变,资源的释放。

最后select也会增加Handler_commit,增加为1。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
MySQL 8 默认的数据库表中的引擎都是InnoDB
看看mysql 8中使用非InnoDB引擎的表是
12 0
MySQL-体系结构以及常用存储引擎MyISAM和InnoDB初探
MySQL-体系结构以及常用存储引擎MyISAM和InnoDB初探
12 0
一文带你了解MySQL之InnoDB 记录结构【上篇】
到现在为⽌,MySQL对于我们来说还是⼀个⿊盒,我们只负责使⽤客户端发送请求并等待服务器返回结果,表中的数据到底存到了哪⾥?以什么格式存放的?MySQL是以什么⽅式来访问的这些数据?这些问题我们统统不知道?之前的文章我们大致知道MySQL服务器上负责对表中数据的读取和写⼊⼯作的部分是存储引擎,⽽服务器⼜⽀持不同类型的存储引擎,⽐如InnoDB、MyISAM、Memory等,不同的存储引擎⼀般是由不同的⼈为实现不同的特性⽽开发的,真实数据在不同存储引擎中存放的格式⼀般是不同的,甚⾄有的存储引擎⽐如Memory都不⽤磁盘来存储数据,也就是说关闭服务器后表中的数据就消失了。
19 0
一文带你了解MySQL之InnoDB 记录结构【下篇】
上一篇文章讲了InnoDB有Compact、Redundant、Dynamic、Compressed4种⾏格式,其中主要讲了Compact行格式,有记录的额外信息和记录的真实数据两⼤部分组成,建议看上篇看上篇看上篇,重要的话说三遍【直通车】,别跳篇。今天我们主要理解剩余的三种行格式和行数据溢出
20 0
一文带你了解MySQL之InnoDB 数据页结构
学完了记录结构,我们该学数据页的结构,前边我们简单的提了一下页的概念,它是Innodb管理存储空间的基本单位,页的大小默认16KB,InnoDB为了不同的目的而设计了许多种不同类型的页,比如存放表空间头部信息的页,存放Insert Buffer信息的页,存放INODE信息的页,存放undo日志信息的页等等等等。而我们聚焦的是那些存放我们表中记录的那种类型的页,官方称这种存放记录的页为索引(INDEX)页,鉴于我们还没有了解过索引是个什么东系,而这些表中的记录就是我们日常口中所称的数据,所以目前还是叫这种存放记录的页为数据页吧
17 0
一文带你了解MySQL之InnoDB表空间
通过前边的内容,相信大家都知道了表空间是一个抽象的概念,对于系统表空间来说,对应着文件系统中一个或多个实际文件;对于每个独立表空间来说,对应着文件系统中一个名为表名.ibd的实际文件。 大家可以把表空间想象成被切分为许多个页的池子,当我们想为某个表插入一条记录的时候,就从池子中捞出一个对应的页来把数据写进去。 本章内容会深入到表空间的各个细节中,带领大家在InnoDB存储结构的池子中畅游。由于本章中将会涉及比较多的概念,虽然这些概念都不难,但是却相互依赖,所以奉劝大家看的时候:不要跳着看
24 0
一文带你了解MySQL之InnoDB表空间
通过前边的内容,相信大家都知道了表空间是一个抽象的概念,对于系统表空间来说,对应着文件系统中一个或多个实际文件;对于每个独立表空间来说,对应着文件系统中一个名为表名.ibd的实际文件。 大家可以把表空间想象成被切分为许多个页的池子,当我们想为某个表插入一条记录的时候,就从池子中捞出一个对应的页来把数据写进去。 本章内容会深入到表空间的各个细节中,带领大家在InnoDB存储结构的池子中畅游。由于本章中将会涉及比较多的概念,虽然这些概念都不难,但是却相互依赖,所以奉劝大家看的时候:不要跳着看
22 0
一文带你了解MySQL之InnoDB统计数据是如何收集的
我们前边唠叨查询成本的时候经常用到一些统计数据,比如通过show table status可以看到关于表的统计数据,通过show index可以看到关于索引的统计数据,那么这些统计数据是怎么来的呢?它们是以什么方式收集的呢?本章将聚焦于InnoDB存储引擎的统计数据收集策略,看完本章后家就会明白为啥前边老说InnoDB的统计信息是不精确的估计值了
25 0
Mysql专栏 - mysql、innodb存储引擎、binlog的工作流程
这次新开了一个个人的mysql专栏,专门用于总结mysql的一些细节以及相关的案例总结,同时也包括了一些mysql的底层实现,在后续的篇章则是根据《mysql技术内幕innodb存储引擎》(第二版)来深入了解mysql中用的最多的存储引擎的内部细节。
29 0
MySQL的varchar水真的太深了——InnoDB记录存储结构
varchar(M) 能存多少个字符,为什么提示最大16383?innodb怎么知道varchar真正有多长?记录为NULL,innodb如何处理?某个列数据占用的字节数非常多怎么办?影响每行实际可用空间的因素有哪些?本篇围绕innodb默认行格式dynamic来说说原理。
32 0
+关注
重庆八怪
10年ORACLE/MYSQL DBA,有一定C/C++基础
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
高效MySQL的N个习惯
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
相关镜像