我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL怎么一个杀掉数据库空闲事务

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL怎么一个杀掉数据库空闲事务

小编给大家分享一下MySQL怎么一个杀掉数据库空闲事务,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

  我们经常遇到一个情况,就是网络断开或程序Bug导致COMMIT/ROLLBACK语句没有传到数据库,也没有释放线程,但是线上事务锁定等待严重,连接数暴涨,尤其在测试库这种情况很多,线上也偶有发生,于是想为MySQL增加一个杀掉空闲事务的功能。下面亿速云小编来讲解下MySQ如何一个杀掉数据库空闲事务?

  MySQ如何一个杀掉数据库空闲事务

  通过MySQL Server层有很多不确定因素,最保险还是在存储引擎层实现,我们用的几乎都是InnoDB/XtraDB,所以就基于Percona来修改了,Oracle版的MySQL也可以照着修改。

  需求:

  1. 一个事务启动,如果事务内最后一个语句执行完超过一个时间(innodb_idle_trx_timeout),就应该关闭链接。

  2. 如果事务是纯读事务,因为不加锁,所以无害,不需要关闭,保持即可。

  虽然这个思路被Percona的指出Alexey Kopytov可能存在“Even though SELECT queries do not place row locks by default (there are exceptions), they can still block undo log records from being purged.”的问题,但是我们确实有场景SELECT是绝对不能kill的,除非之后的INSERT/UPDATE/DELETE发生了,所以我根据 我们的业务特点来修改。

  跟Percona的Yasufumi Kinoshita和Alexey Kopytov提出过纯SELECT事务不应被kill,但通过一个参数控制的方案还没有被Alexey Kopytov接受,作为通用处理我提出了用两个变量分别控制纯读事务的空闲超时时间和有锁事务的空闲超时时间,还在等待Percona的回复,因为这个 方案还在测试,就先不开放修改了,当然如果你很熟悉MYSQL源码,我提出这个思路你肯定知道怎么分成这两个参数控制了。

  根据这两个需 求我们来设计方法,首先想到这个功能肯定是放在InnoDB Master Thread最方便,Master Thread每秒调度一次,可以顺便检查空闲事务,然后关闭,因为在事务中操作trx->mysql_thd并不安全,所以一般来说最好在 InnoDB层换成Thread ID操作,并且InnoDB中除了ha_innodb.cc,其他地方不能饮用THD,所以Master Thread中需要的线程数值,都需要在ha_innodb中计算好传递整型或布尔型返回值给master thread调用。

  首先,我们要增加一个参数:idle_trx_timeout,它表示事务多久没有下一条语句发生就超时关闭。

  在storage/innodb_plugin/srv/srv0srv.c的“”注释下增加如下代码注册idle_trx_timeout变量。

  if (srv_idle_trx_timeout && trx_sys) {

  trx_t* trx;

  time_t now;

  rescan_idle:

  now = time(NULL);

  mutex_enter(&kernel_mutex);

  trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); # 从当前事务列表里获取第一个事务

  while (trx) { # 依次循环每个事务进行检查

  if (trx->conc_state == TRX_ACTIVE

  && trx->mysql_thd

  && innobase_thd_is_idle(trx->mysql_thd)) { # 如果事务还活着并且它的状态时空闲的

  ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd); # 获取线程最后一个语句的开始时间

  ulong thd_id = innobase_thd_get_thread_id(trx->mysql_thd); #获取线程ID,因为存储引擎内直接操作THD不安全

  if (trx->last_stmt_start != start_time) { # 如果事务最后语句起始时间不等于线程最后语句起始时间说明事务是新起的

  trx->idle_start = now; # 更新事务的空闲起始时间

  trx->last_stmt_start = start_time; # 更新事务的最后语句起始时间

  } else if (difftime(now, trx->idle_start) # 如果事务不是新起的,已经执行了一部分则判断空闲时间有多长了

  > srv_idle_trx_timeout) { # 如果空闲时间超过阈值则杀掉链接

  

  mutex_exit(&kernel_mutex);

  thd_kill(thd_id); # 杀链接

  goto rescan_idle;

  }

  }

  trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); # 检查下一个事务

  }

  mutex_exit(&kernel_mutex);

  }

  代码往下找在innobase_system_variables结构体内加上:

  MySQ如何一个杀掉数据库空闲事务

  if (srv_idle_trx_timeout && trx_sys) {

  trx_t* trx;

  time_t now;

  rescan_idle:

  now = time(NULL);

  mutex_enter(&kernel_mutex);

  trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); # 从当前事务列表里获取第一个事务

  while (trx) { # 依次循环每个事务进行检查

  if (trx->conc_state == TRX_ACTIVE

  && trx->mysql_thd

  && innobase_thd_is_idle(trx->mysql_thd)) { # 如果事务还活着并且它的状态时空闲的

  ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd); # 获取线程最后一个语句的开始时间

  ulong thd_id = innobase_thd_get_thread_id(trx->mysql_thd); #获取线程ID,因为存储引擎内直接操作THD不安全

  if (trx->last_stmt_start != start_time) { # 如果事务最后语句起始时间不等于线程最后语句起始时间说明事务是新起的

  trx->idle_start = now; # 更新事务的空闲起始时间

  trx->last_stmt_start = start_time; # 更新事务的最后语句起始时间

  } else if (difftime(now, trx->idle_start) # 如果事务不是新起的,已经执行了一部分则判断空闲时间有多长了

  > srv_idle_trx_timeout) { # 如果空闲时间超过阈值则杀掉链接

  

  mutex_exit(&kernel_mutex);

  thd_kill(thd_id); # 杀链接

  goto rescan_idle;

  }

  }

  trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); # 检查下一个事务

  }

  mutex_exit(&kernel_mutex);

  }

  有了这个变量,我们需要在Master Thread(storage/innodb_plugin/srv/srv0srv.c )中执行检测函数查找空闲事务。在loop循环的if (sync_array_print_long_waits(&waiter, &sema)判断后加上这段判断

  if (srv_idle_trx_timeout && trx_sys) {

  trx_t* trx;

  time_t now;

  rescan_idle:

  now = time(NULL);

  mutex_enter(&kernel_mutex);

  trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); # 从当前事务列表里获取第一个事务

  while (trx) { # 依次循环每个事务进行检查

  if (trx->conc_state == TRX_ACTIVE

  && trx->mysql_thd

  && innobase_thd_is_idle(trx->mysql_thd)) { # 如果事务还活着并且它的状态时空闲的

  ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd); # 获取线程最后一个语句的开始时间

  ulong thd_id = innobase_thd_get_thread_id(trx->mysql_thd); #获取线程ID,因为存储引擎内直接操作THD不安全

  if (trx->last_stmt_start != start_time) { # 如果事务最后语句起始时间不等于线程最后语句起始时间说明事务是新起的

  trx->idle_start = now; # 更新事务的空闲起始时间

  trx->last_stmt_start = start_time; # 更新事务的最后语句起始时间

  } else if (difftime(now, trx->idle_start) # 如果事务不是新起的,已经执行了一部分则判断空闲时间有多长了

  > srv_idle_trx_timeout) { # 如果空闲时间超过阈值则杀掉链接

  

  mutex_exit(&kernel_mutex);

  thd_kill(thd_id); # 杀链接

  goto rescan_idle;

  }

  }

  trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); # 检查下一个事务

  }

  mutex_exit(&kernel_mutex);

  }

  其中trx中的变量是新加的,在storage/innodb_plugin/include/trx0trx.h的trx_truct加上需要的变量。

看完了这篇文章,相信你对“MySQL怎么一个杀掉数据库空闲事务”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MySQL怎么一个杀掉数据库空闲事务

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么新建一个mysql数据库

创建一个新 mysql 数据库:登录 mysql 服务器。使用 create database [db_name]; 语句创建数据库。使用 show databases; 语句验证数据库是否已创建。如何新建一个 MySQL 数据库创建一个
怎么新建一个mysql数据库
2024-08-05

MySQL怎么为每个数据库建立一个文件夹

在MySQL中,每个数据库都有一个对应的文件夹来存储相关的文件。要为每个数据库建立一个文件夹,可以按照以下步骤操作:1. 找到MySQL的数据目录(data directory)。可以在MySQL的配置文件my.cnf中查找该目录的位置。在
2023-10-18

Linux服务器中怎么创建一个oracle数据库

Linux服务器中怎么创建一个oracle数据库,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、创建数据库实例步骤:1. 打开xshell,新建会话,输入主机
2023-06-05

怎么创建一个创建MySQL数据库中的datetime类型

今天小编给大家分享一下怎么创建一个创建MySQL数据库中的datetime类型的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
2023-06-29

怎么在golang中实现mysql数据库事务的提交与回滚

这期内容当中小编将会给大家带来有关怎么在golang中实现mysql数据库事务的提交与回滚,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。golang适合做什么golang可以做服务器端开发,但golang
2023-06-14

本地mysql连接阿里云数据库服务器错误怎么回事?

本文主要探讨了本地mysql连接阿里云数据库服务器时可能会遇到的一些错误,以及如何解决这些问题。正文:随着云计算技术的不断发展,越来越多的企业和个人开始使用阿里云等云数据库服务。然而,在使用过程中,可能会遇到一些问题,例如本地mysql连接阿里云数据库服务器时遇到错误。那么,究竟是什么原因导致了这样的错误呢?又该
本地mysql连接阿里云数据库服务器错误怎么回事?
2023-12-09

怎么购买云服务器在同一个内网上的数据库

购买云服务器时,需要注意一些相关问题,例如服务器的配置、价格、可用性等。以下是常见的一些购买云服务器需要考虑的因素:内网:如果您要在不同的内网上使用数据库,需要使用不同的网络协议和路由器来避免互相干扰。因此,您需要选择内网带宽大的云服务器。服务器硬件:根据您的使用场景和预算,选择合适的服务器硬件。例如,您可能需要使用高性能的服务器来处理大量的数据,而预算有限的情况下可能就需要选择便宜的机架
2023-10-26

怎么购买云服务器在同一个内网上的数据库文件

如果您在同一个内部网上有多个数据库文件,并且想要在不同的内网之间共享这些文件数据,您可以购买云服务器(CloudComputing)来解决此问题。使用云服务器的好处包括:跨多种网络连接:在同一个云服务器上可以访问多个外部网络,因此可以轻松地分享数据,而无需担心网络连接不稳定或中断。更快的数据传输速度:云服务器可以为您提供高达每秒10GB的传输速度,这使得共享文件和数据成为可能。高可用性:云服务器具有自动负载均衡和故障转移功...
2023-10-26

Microsoft Power BI连接本地mysql 数据库 !power bi提示此连接器需要安装一个或多个其他组件才能使用怎么办!

最终解决方案竟然是卸载8.0.33版本,下载8.0.32版本…吐血,知道真相的我眼泪掉下来 大家可以直接跳到【亲测有用——知道真相的我眼泪掉下来】这一部分。 一、步骤 (一)从菜单栏点击进入mysql数据库 点击主页>获取数据>更多 选择
2023-08-24

编程热搜

目录