加入收藏 | 设为首页 | 会员中心 | 我要投稿 常州站长网 (https://www.0519zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MySQL性能优化之Innodb事务系统,值得收藏

发布时间:2019-09-04 14:14:14 所属栏目:MySql教程 来源:波波说运维
导读:副标题#e# 今天主要分享下Innodb事务系统的一些优化相关,以下基于mysql 5.7。 一、Innodb中的事务、视图、多版本 1. 事务 在Innodb中,每次开启一个事务时,都会为该session分配一个事务对象。而为了对全局所有的事务进行控制和协调,有一个全局对象trx_sy

在5.7中,事务系统维持了一个全局事务ID数组,每个活跃读写事务的ID都被加入到其中,在事务提交时从其中删除,这样打开视图时只需要使用memcpy 拷贝该数组即可,无需遍历链表。在读写链表较长(高并发下)的场景,该优化可以显著的提升性能。

3. 用户需要显式开启只读事务,才会放入只读事务链表

mysql5.7将只读事务链表从其中彻底移除了,取而代之的是,所有事务都以只读模式打开。

例如如下事务序列:

  1. BEGIN; 
  2. SELECT; //事务开始,不分配事务ID,不分配回滚段; 
  3. UPDATE; //分配事务ID并插入全局事务数组和事务对象集合中,分配回滚段; 
  4. COMMIT; 

而对于BEGIN;SELECT;SELECT;COMMIT这样的序列,整个事务周期既不分配事务ID,也不分配回滚段。

4. 隐式锁转换为显式锁的开销

Innodb对于类似INSERT操作,采用的是隐式锁的方式,隐式锁不是锁,只是一种称呼而已,只有在需要的时候,才会转换为显式锁。例如如下:

  1. Session 1: BEING; INSERT INTO t1(pk, val) VALUES (1,2); //不创建锁对象 
  2. Session 2: UPDATE t1 SET valval=val+1 WHERE pk=1; //创建两个锁对象,一个是为session1创建一个记录锁对象,另外一个是给自己创建一个等待类型的记录锁对象,然后session2加入锁等待队列。 

在Session 2中为Session1创建锁对象的过程即是所谓的隐式锁向显式锁转换。 当session2扫描到session 1插入的记录时,发现session 1的事务依然活跃,就会进入转换逻辑。

在5.6版本中,其转换过程如下:

  • 持有lock_sys->mutex
  • 2持有trx_sys->mutex;根据事务ID,扫描读写事务链表,找到对应的事务对象;释放trx_sys->mutex;
  • 创建显式锁对象
  • 释放lock_sys->mutex

可以看到,在该操作的过程中,全程持有lock_sys->mutex,持有锁的原因是防止事务提交掉。当读写事务链表非常长时(例如高并发写入时),这种开销将是不可接受的。

在5.7版本中,上述逻辑则优化成:

(1)  持有trx_sys->mutex

  • 根据事务ID找到对应的事务对象(直接查找trx_sys->rw_trx_set,其保存了trx_id和事务对象的映射关系,因此无需扫描读写事务链表)
  • 增加事务对象引用计数(++trx->n_ref)
  • 释放trx_sys->mutex

(2) 持有lock_sys->mutex;

  • 创建显式锁对象;
  • 释放lock_sys->mutex;

(3) 递减事务对象引用计数

在事务commit,释放记录锁前,会先判断引用记录数是否为0,如果不为0,表示正有其他事务为其转换显式锁,这时候需要等待,直到计数为0,才能进入释放事务记录锁阶段。

总的来说,该优化减少了隐式锁转换时持有LOCK_sys->mutex的时间,从而提升性能。

【编辑推荐】

  1. 11条MySQL规范,你知道的有几个?
  2. 图解MySQL索引:B-树、B+树
  3. 五大常见的MySQL高可用方案
  4. MySQL 进行 Docker 容器化之体验与感悟
  5. 如何在磁盘上查找 MySQL 表的大小
【责任编辑:赵宁宁 TEL:(010)68476606】
点赞 0

(编辑:常州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读