MySQL中的长事务示例详解

  

  

"入门MySQL”系列文章已经完结,今后我的文章还是会以MySQL为主,主要记录下近期工作及学习遇到的场景或者自己的感悟想法,可能后续的文章不是那么连贯,但还是希望大家多多支持。言归正传,本篇文章主要介绍MySQL长事务相关内容,比如说我们开启的一个事务,一直没提交或回滚会怎样呢,出现事务等待情况应该如何处理,本篇文章将给你答案。

  

本篇文章并不聚焦于谈论事务隔离级别以及相关特性。而是介绍长事务相关危害以及监控处理方法。本文是基于MySQL5.7.23版本,不可重复读(RR)隔离级别所做实验。
  

  


  

  

首先我们先要知道什么是长事务,顾名思义就是运行时间比较长,长时间未提交的事务,也可以称之为大事务。这类事务往往会造成大量的阻塞和锁超时,容易造成主从延迟,要尽量避免使用长事务。

  

下面我将演示下如何开启事务及模拟长事务:

        #假设我们有一张stu_tb表,结构及数据如下   mysql>显示创建表stu_tb \ G   * * * * * * * * * * * * * * * * * * * * * * * * * * * 1。行 ***************************   表:stu_tb   创建表:创建表“stu_tb”(   increment_id int (11) NOT NULL AUTO_INCREMENT评论的自增主键的,   stu_id int (11) NOT NULL评论“学”号,   stu_name varchar(20)默认空评论的学生姓名”,   “create_time”默认时间戳NOT NULL CURRENT_TIMESTAMP评论“创建时间”,   “update_time”默认时间戳NOT NULL CURRENT_TIMESTAMP>   mysql>现在选择t。*, to_seconds (()) -to_seconds (t.trx_started)从INFORMATION_SCHEMA idle_time。INNODB_TRX t \ G   * * * * * * * * * * * * * * * * * * * * * * * * * * * 1。行 ***************************   trx_id: 6168   trx_state:跑步   trx_started: 2019-09-16 11:08:27   trx_requested_lock_id:零   trx_wait_started:零   trx_weight: 3   trx_mysql_thread_id: 11   trx_query:零   trx_operation_state:零   trx_tables_in_use: 0   trx_tables_locked: 1   trx_lock_structs: 3   trx_lock_memory_bytes: 1136   trx_rows_locked: 2   trx_rows_modified: 0   trx_concurrency_tickets: 0   trx_isolation_level:可重复读   trx_unique_checks: 1   trx_foreign_key_checks: 1   trx_last_foreign_key_error:零   trx_adaptive_hash_latched: 0   trx_adaptive_hash_timeout: 0   trx_is_read_only: 0   trx_autocommit_non_locking: 0   idle_time: 170      

在结果中idle_time是计算产生的,也是事务的持续时间。但事务的trx_query是空,这并不是说事务什么也没执行,一个事务可能包含多个SQL,如果SQL执行完毕就不再显示了。当前事务正在执行,innodb也不知道这个事务后续还有没有SQL,啥时候会提交。因此trx_query不能提供有意义的信息。

  

如果我们想看到这个事务执行过的SQL,看是否可以杀掉长事务,怎么办呢?我们可以联合其他系统表查询得到,具体查询SQL如下:

        mysql>现在选择(),(UNIX_TIMESTAMP(现在())- UNIX_TIMESTAMP (a.trx_started)) diff_sec, b.id, b.user b.host b.db, d。从information_schema SQL_TEXT。innodb_trx内加入   →information_schema。PROCESSLIST b   →>   mysql>现在选择(),(UNIX_TIMESTAMP(现在())- UNIX_TIMESTAMP (a.trx_started)) diff_sec, b.id, b.user b.host b.db, d。从information_schema SQL_TEXT。innodb_trx内加入   →information_schema。PROCESSLIST b   →>   #假设一个事务执行select * from stu_tb stu_id=1006更新的地方   #另外一个事务执行更新stu_tb设置stu_name=酢痵tu_id=1006      mysql>select * from sys.innodb_lock_waits \ G   * * * * * * * * * * * * * * * * * * * * * * * * * * * 1。行 ***************************   wait_started: 2019-09-16 14:34:32   wait_age: 00:00:03   wait_age_secs: 3   locked_table:“testdb”。“stu_tb”   locked_index: uk_stu_id   locked_type:记录   waiting_trx_id: 6178   waiting_trx_started: 2019-09-16 14:34:32   waiting_trx_age: 00:00:03   waiting_trx_rows_locked: 1   waiting_trx_rows_modified: 0   waiting_pid: 19   waiting_query:更新stu_tb设置stu_name=酢痵tu_id=1006   waiting_lock_id: 6178:47:4:7   waiting_lock_mode: X   blocking_trx_id: 6177   blocking_pid: 20   blocking_query:零   blocking_lock_id: 6177:47:4:7   blocking_lock_mode: X   blocking_trx_started: 2019-09-16 14:18:44   blocking_trx_age: 00:15:51   blocking_trx_rows_locked: 2   blocking_trx_rows_modified: 0   sql_kill_blocking_query:杀死查询20   sql_kill_blocking_connection:杀死20

MySQL中的长事务示例详解