测试环境信息如下:

  • OS:Ubuntu 16.04 LTS
  • Mysql:Mysql 5.7.18,使用docker images运行的实例

Mysql如何处理client请求

在Mysql中,连接管理线程(Connection manager threads)用于处理来自客户端的TCP/IP连接请求,它会将每个client connection关联到一个专门的mysql thread,这个thread负责处理通过connection发出的所有请求(也包含请求的安全认证)。

Mysql thread

mysql thread并非操作系统上的真实线程,只是mysql中的一个对象,但是会与os thread(操作系统真实的线程)关联起来。下面了解下如果查看mysql thread。

最简单的方式是使用 show processlist 查看当前连接,这个命令与查看information_schema.processlist表效果一致。

每一个连接进来时,都可以在看到一条新的记录。可以通过不断打开与关闭连接来测试,每次打开一个连接后在 processlist 中将会多出一条记录,连接关闭后这条记录也会被移除。

如果当前连接正在进行事务处理,也可以通过information_schema.innodb_trx 事务表查看,其中trx_mysql_thread_id字段为mysql thread id,与processlist中id一致

如果启用了mysql的性能监控功能( 通过SHOW VARIABLES LIKE 'performance_schema'查看 ),可以通过performance_schema.threads 查看,其中有PROCESSLIST_ID,与上面的两个ID保持一致。

Mysql OS thread

虽然每次打开连接,可以看到一个新的 mysql thread 产生,但是OS并不一定会为每个连接创建一个新的os thread。

首先,看看mysqld进程对应的所有os线程。

执行命令 ps -ef | grep mysql 得到mysqld的PID(进程ID)为 16286

  1. 999 16286 16267 4 22:39 ? 00:00:00 mysqld
  2. ubuntu 16362 9909 0 22:39 pts/1 00:00:00 grep --color=auto mysql

通过top -H -p 16286 查看进程下的所有线程:

mysqld下有27个线程,PID为每个线程的ID。mysql thread和os thread并不能直接匹配起来。

可以通过一个例子来看看mysql thread与os thread的关系。

运行两个事务,每个事务往 test表中插入1000W条记录,事务处理时间较长。

在 processlist 表中可以看到两个执行 insert 操作的mysql thread.

在os threads中将会使用两个thread来进行实际的处理,top命令可以看到mysqld进程下的线程占用的CPU和内存情况。

也可以进行如下测试,会发现一些有趣的事情:

  • 使用一个connection连接并按顺序执行几个事务,会使用不同的os thread来进行处理,当然,也可能是同一个os thread(如果只有一个os thread可用,所有事务会有同一个os thread处理;如果有多个os thread可用,将会轮换使用不同的os thread)。
  • 如果kill掉任意一个os thread,mysql server将会shutdown。因此,不要尝试kill掉某个事务对应的os thread,毫无意义,mysql重新启动后,原先的事务该干的事还是得一样干完,以保证事务的ACID特性
  • 如果你kill mysql thread,将不会影响到实际的os thread,但是该mysql thread将被删除。假如你正在执行一个 insert 事务且已经插入了100W数据,如果kill mysql thread,事务对应的trx_mysql_thread_id会设置为0,然后事务开始执行rollback

connection,mysql thread,os thread之间的关系

本小节的探讨基于 thread_handling=one-thread-per-connection,即线程模型是为每个连接分配一个mysql thread

三者的关联如下:

  • mysql会为每个connection创建一个对应mysql thread,连接关闭后,mysql thread生命周期也终止。这个mysql thread可以在processlist、threads表中查看
  • 每个mysql threard将与一个os thread关联在一起,mysql thread销毁后,os thread不会被销毁,可以继续给其他mysql thread使用
  • 如果所有os thread都被mysql thread用光了,下一个connection请求时将会创建新的os thread

下面做一个小测试:

假定max_connections=151, 使用以下语句应用中循环1000次不断获取连接并且不释放连接

  1. DriverManager.getConnection(url, user, password);

可以观察到以下现象:

  • mysql将不断的创建mysql thread,由于没有闲置的os thread可用,也将不断创建os thread
  • 当连接达到max_connections后,会报错:MySQLNonTransientConnectionException: Too many connections,同时mysql将无法再创建连接
  • 达到max_connections后,可以手工处理掉空闲时间很长的连接,也可以等待连接达到 wait_timeout 设置的时间后被自动close掉。wait_timeout默认是8小时

一般应用都会通过连接池与DB交互,同时会定期通过连接发送请求(mysql 可以发送select 1) 给DB以重置connection的空闲时间

通过mysql thread找到os thread

通过查看innodb status

如果有事务正在执行,通过 show engine innodb status 查看事务信息,下面是该命令输出的部分信息:

  1. ------------
  2. TRANSACTIONS
  3. ------------
  4. ...
  5. 1 lock struct(s), heap size 1136, 0 row lock(s), undo log entries 568226
  6. MySQL thread id 65, OS thread handle 139656030103296, query id 229749097 218.104.153.55 test update
  7. INSERT INTO test (uid, uid2, uid3)
  8. VALUES (UUID(), UUID(), UUID())

可以看到mysql thread为65,OS thread为139656030103296

MySQL thread id 65, OS thread handle 139656030103296

通过查看threads表

题外话之mysql 官方说明:访问threads表对mysql没有什么性能影响,但访问processlist表或者show processlist对性能有一定影响,因为它们都需要mutex(互斥)

performance.threads 表中有 thread_os_id 字段,存储了mysql thread和os thread的关系

关于 thread_os_id

thread_os_id 是操作系统定义的thread或task标识符:

  • 如果mysql thread在生命周期中与一个os thread关联,thread_os_id字段将包含os thread ID
  • 如果mysql thread在生命周期中没有和os thread关联,thread_os_id将为NULL

在windows下,thread_os_id可以在任务管理器中看到;在linux下,thread_os_id和gettid()方法对应,可以使用perl 、ps -L命令或者使用proc文件系统(/proc/[pid]/task/[tid])

不过查阅许多资料后也没有结果,我也没有找到合适的方式将thread_os_id与os线程直接对应起来,只能侧面判断。

有资料 提供了一个偏方:通过gdb attach 命令来调试正在运行的程序,但是这会导致mysqld进程被暂停,并没有实际意义,不过本身找到mysql thread对应的os thread也没什么意义。先贴一下通过gdb attach得到的数据:

先执行gdb attach 11646 ,再执行info threads 命令,输出如下:

包含了线程ID和对应的16进制ID,资料显示:16进制ID在show engine innodb status输出信息中是可以看到的,不过我在mysql 5.7.18版本的输出信息中并未找到16进制的线程ID数据。

总结

通过上述讲述和一些例子,可以了解到以下几点:

  • 连接管理线程会为每一个connection分配一个mysql thread来处理

  • mysql thread实际会使用某个os thread来处理请求

  • connection关闭或kill mysql thread时,mysql thread会销毁,但是os thread可以继续复用

Mysql thread 与 OS thread的更多相关文章

  1. Thread系列之Thread.Sleep(0)

    线程这一概念,可以理解成进程中的一个小单元.这个单元是一个独立的执行单元,但是与进程中的其他线程共享进程中的内存单元. 由于Cpu资源是有限的,所以进程中的多个线程要抢占Cpu,这也导致进程中的多个线 ...

  2. PHP版本VC6和VC9、Non Thread Safe和Thread Safe的区别

    链接:http://www.cnblogs.com/neve/articles/1863853.html 想更新个PHP的版本,PHP的windows版本已经分离出来了,见http://windows ...

  3. Part 92 Significance of Thread Join and Thread IsAlive functions

    Thread.Join & Thread.IsAlive functions Join blocks the current thread and makes it wait until th ...

  4. Thread thread2 = new Thread()

    Thread thread2 = new Thread() { @Override public void run() { test.function(); } }; thread1.start(); ...

  5. c++并发编程之thread::join()和thread::detach()

    thread::join(): 阻塞当前线程,直至 *this 所标识的线程完成其执行.*this 所标识的线程的完成同步于从 join() 的成功返回. 该方法简单暴力,主线程等待子进程期间什么都不 ...

  6. yum安装提示错误Thread/process failed: Thread died in Berkeley DB library

    问题描述: yum 安装更新提示 rpmdb: Thread/process failed: Thread died in Berkeley DB library 问题解决: 01.删除yum临时库文 ...

  7. 1,Thread 概念以及Thread 的6个状态

    Thread 有6个状态 , NEW, RUNNABLE , BLOCKED, WATTING, TIMED WAITING, TERMINATED 1.NEW至今尚未启动的线程的状态.2.RUNNA ...

  8. Thread之三:Thread Join()的用法

    一.join用法 join()和wait()不会释放锁,join()是Thread的方法,wait()是Object的方法 1.join方法定义在Thread类中,则调用者必须是一个线程 例如: Th ...

  9. Thread.sleep 与Thread.currentThread.sleep

    参考博客: https://blog.csdn.net/guangyinglanshan/article/details/51645053 公司项目近段时间要使用thread, 个人想去了解Threa ...

随机推荐

  1. 解决ScrollView嵌套RecyclerView的显示及滑动问题

        项目中时常需要实现在ScrollView中嵌入一个或多个RecyclerView.这一做法通常会导致如下几个问题 页面滑动卡顿 ScrollView高度显示不正常 RecyclerView内容 ...

  2. LaTeX语法笔记

    1.单词之间用空格分隔,段落之间用一整空行分隔,但是,如果在多输入空格或者空行也没有用处,系统还是把它当做一个空格或空行. 2.双引号:左侧用``(键盘左上角那个符号),右侧用'',即: ``'' , ...

  3. 使用vw做移动端页面的适配

    Flexible到今天也有几年的历史了,解救了很多同学针对于H5页面布局的适配问题.而这套方案也相对而言是一个较为成熟的方案.简单的回忆一下,当初为了能让页面更好的适配各种不同的终端,通过Hack手段 ...

  4. 菜鸟学Java(二十三)——Java内存分析

    我们常说的Java内存主要分为四大块(寄存器不在考虑之内,我们无法用代码来操控它):stack(栈).heap(堆).data segment(数据区).code segment(代码区).它们的主要 ...

  5. FFmpeg: AVCodecParameters 结构体分析

    /** * This struct describes the properties of an encoded stream. * * sizeof(AVCodecParameters) is no ...

  6. DIOCP-DIOCPv5的处理能力

    今天和BB讨论了下DiocpV5的单连接处理能力.一直没有做过这方面的测试,稍微试了一下. 把开始的时候客户端Sleep(10),为了测试处理能力,把Sleep(10)去掉了,20秒(实际应该算17秒 ...

  7. Node入门教程(9)第七章:NodeJs的文件处理

    Node的文件处理涉及到前面说的ptah模块,以及fs文件系统.stream流处理.Buffer缓冲器等模块.内容可能比较多,相关内容请以官网文档为主,此处主要以案例讲解为主,分享给大家一些常用的经典 ...

  8. [转]css实现左侧宽度自适应,右侧固定宽度

    原文地址:https://segmentfault.com/a/1190000008411418 页面布局中经常用会遇到左侧宽度自适应,右侧固定宽度,或者左侧宽度固定,右侧自适应.总之就是一边固定宽度 ...

  9. 红米3 MoKee 7.1.2_r36 自编译版/去魔趣中心、宙斯盾/息屏禁止刷新UI 2018年5月5日更新

    一.ROM简介 MoKee是基于CM二次修改的ROM,本地化系统:农历.归属地.OMS框架.状态栏显示网速/时间显秒等等. 二.ROM自编译DIY简介 1.Lawnchair桌面. 2.Via谷歌版浏 ...

  10. phpstrom 激活

    最新(2017年5月)PhpStorm 2017.1.2 .WebStorm 2017.1.PyCharm  2016.3激活方式 打开网址 http://idea.lanyus.com/ 选择获取注 ...