时间:2021-07-01 10:21:17 帮助过:32人阅读
本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/server_kill_idle_transaction.html 在上一篇文章里我们写了如何针对InnoDB清理空闲事务《如何杀掉空闲事务》
本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/server_kill_idle_transaction.html
在上一篇文章里我们写了如何针对InnoDB清理空闲事务《如何杀掉空闲事务》,在@sleebin9 的提示下,这个功能不仅可以针对InnoDB,也可以用于所有MySQL的事务引擎。
如何在Server层实现呢,sql/sql_parse.cc的do_command()函数是个好函数,连接线程会循环调用do_command()来读取并执行命令,在do_command()函数中,会调用my_net_set_read_timeout(net, thd->variables.net_wait_timeout)来设置线程socket连接超时时间,于是在这里可以下手。
主要代码:
830 /* 831 This thread will do a blocking read from the client which 832 will be interrupted when the next command is received from 833 the client, the connection is closed or "net_wait_timeout" 834 number of seconds has passed 835 */ 836 /* Add For Kill Idle Transaction By P.Linux */ 837 if (thd->active_transaction()) 838 { 839 if (thd->variables.trx_idle_timeout > 0) 840 { 841 my_net_set_read_timeout(net, thd->variables.trx_idle_timeout); 842 } else if (thd->variables.trx_readonly_idle_timeout > 0 && thd->is_readonly_trx) 843 { 844 my_net_set_read_timeout(net, thd->variables.trx_readonly_idle_timeout); 845 } else if (thd->variables.trx_changes_idle_timeout > 0 && !thd->is_readonly_trx) 846 { 847 my_net_set_read_timeout(net, thd->variables.trx_changes_idle_timeout); 848 } else { 849 my_net_set_read_timeout(net, thd->variables.net_wait_timeout); 850 } 851 } else { 852 my_net_set_read_timeout(net, thd->variables.net_wait_timeout); 853 } 854 /* End */
大家看明白了吗?其实这是偷梁换柱,本来在这里是要设置wait_timeout的,先判断线程是不是在事务里,就可以转而实现空闲事务的超时。
trx_idle_timeout 控制所有事务的超时,优先级最高
trx_changes_idle_timeout 控制非只读事务的超时
trx_readonly_idle_timeout 控制只读事务的超时
效果:
root@localhost : (none) 08:39:49> set autocommit = 0 ; Query OK, 0 rows affected (0.00 sec) root@localhost : (none) 08:39:56> set trx_idle_timeout = 5; Query OK, 0 rows affected (0.00 sec) root@localhost : (none) 08:40:17> use perf Database changed root@localhost : perf 08:40:19> insert into perf (info ) values('11'); Query OK, 1 row affected (0.00 sec) root@localhost : perf 08:40:26> select * from perf; ERROR 2006 (HY000): MySQL server has gone away No connection. Trying to reconnect... Connection id: 6 Current database: perf +----+------+ | id | info | +----+------+ | 7 | aaaa | | 9 | aaaa | | 11 | aaaa | +----+------+ 3 rows in set (0.00 sec)
完整的patch这里下载:
Note: There is a file embedded within this post, please visit this post to download the file.