博客 > 谈谈SequoiaDB线程状态切换那点事儿

谈谈SequoiaDB线程状态切换那点事儿

 2020-09-22  SequoiaDB,原理解析
SequoiaDB 数据库采用多线程模型,线程可分为用户线程和系统线程。用户线程是指用于处理用户任务的线程,系统线程则是为系统内部维护数据结构及一致性和处理后台任务的线程。在分布式模式下,当数据库接收到用户的一个请求时,数据库会启用很多不同类型的线程为用户服务,了解线程状态的转换关系有助于监控和了解数据库的运行状态。因此,在本篇文章中,笔者想和大家分享一下 SequoiaDB 线程的状态是如何转换的。


SequoiaDB 线程状态

SequoiaDB 数据库线程的状态共有5种,其状态之间的转换关系如下图所示:

image.png


• Creating,创建状态,通常是线程池中已没有空闲线程可用与处理用户任务或系统任务时,需要新建线程,此时线程处于 Creating 状态。

• Running,运行状态,当处于 Creating 状态的线程完成资源分配和一系列的初始化动作后,线程被激活,或者处于 Waiting 状态的线程接收到用户或者系统下一阶段的请求后,开始处理用户任务或系统任务,此时线程处于 Running 状态。

• Waiting,等待状态,当处于 Running 状态的线程处理完本阶段的任务后,开始等待下一阶段的任务处理请求,此时线程处于 Waiting 状态。

• Idle,空闲状态,在等待任务请求过程中,用户连接断开后,线程会回归线程池,此时线程处于 Idle 状态。

• Destroying,销毁状态,当线程在线程池空闲超过于空闲超时时间,系统会将空闲连接销毁,释放占用的系统资源,或者处于 Waiting 或 Running 状态的线程所绑定的会话被杀掉,此时正在被销毁的线程处于 Destroy 状态。

SequoiaDB 数据库提供会话快照监控线程的活动状态,但由于线程处于 Creating 和 Destroying 状态的时间极其短暂,很难通过会话快照监控到。通常情况下,通过会话快照基本上都可以监控到处于 Running,Waiting,Idle 状态的线程。


演示

接下来,笔者给大家演示如何利用会话快照,查看和分析线程状态的转换关系。笔者的演示环境安装的数据库版本为 3.4.1,数据库数据节点和协调节点均开启了事务,事务隔离级别为RC,其他版本的演示步骤与之相似。演示的线程状态转换关系如下图所示:

image.png

  • 打开服务器终端,称为终端1,在命令行中建立数据库连接,创建集合 company.employee,并且开启事务,插入一条记录

sdb 'db = new Sdb()'
sdb 'db.transBegin()'
sdb 'db.createCS("company").createCL("employee")'
sdb 'db.company.employee.insert({"id":1,"ename":"xjh","age":27})'

image.png

  • 新打开服务器终端,称为终端2,在命令行中建立数据库连接并且清空 company.employee 集合的数据

sdb 'db = new Sdb()'
sdb 'db.company.employee.remove()'

image.png

  • 在终端1,通过会话快照查看数据库当前连接到协调节点 sdbserver1:11810 的用户线程(注意:此处以排除了当前会话连接对应的线程)

sdb 'db.exec("select * from $SNAPSHOT_SESSION where NodeName in (\"sdbserver1:11810\") and Type=\"Agent\" and LastOpType <> \"SQL\"")'

image.png

从上图可以获知,终端2的会话对应的线程 TID 为37732,此时阻塞等待终端1的会话所持有的 company.employee 集合的记录锁(IsBlocked值为 true),线程处于 Running 状态( Status 值为 Running)。可能有些读者会觉得疑惑,为什么阻塞等待记录锁,线程的状态却是 Running 呢?笔者是这样理解的, 因为SequoiaDB 线程的状态并没有 Blocked(阻塞)状态,而线程 Running 状态的定义是正在处理用户任务的线程,此时线程 37732 确实是正在执行清空集合 company.employee 的操作,只是需要获得终端1的会话所持有的记录锁后才能继续往下执行,所以线程的状态为 Running。


  • 在终端1,提交事务,终端2的清空 company.employee 集合的操作继续执行,不再阻塞

sdb 'db.transCommit()'

image.png

  • 在终端1,重新通过会话快照查看终端2的会话对应的线程(TID=37732)状态,此时由于线程已经完成清空集合 company.employee 任务,等待下一阶段的任务请求,处于 Waiting 状态

image.png

  • 在终端2,关闭数据库连接

sdb 'db.close()'
  • 在终端1,重新通过会话快照查看终端2的会话对应的线程(TID=37732)状态,由于会话连接已经关闭,此时线程处于 Idle 状态

sdb 'db.exec("select * from $SNAPSHOT_SESSION where NodeName in (\"sdbserver1:11810\") and TID=37732)'

image.png


总结

SequoiaDB 数据库采用多线程模型,线程可分为用户线程和系统线程,分别负责处理用户任务和系统任务,线程状态可分为五种,并提供会话快照监控用户线程和系统线程。本文向大家介绍了线程状态的转换方式,希望帮助大家进一步监控和掌握数据库的运行状态。

准备开始体验 SequoiaDB 巨杉数据库?