关于mysql:MySQL说原理

41次阅读

共计 2753 个字符,预计需要花费 7 分钟才能阅读完成。

1、JDBC Connection 实例是线程平安的吗?

Connection 实例是线程平安的吗?

能不能只创立一次,共享 Connection 对象?

答案是不能的,Connection 不是线程平安的,他会在多线程环境下,导致数据库操作的凌乱,特地是在事务存在的状况下:可能一个线程刚开启事务 con.setAutoCommit(true),而另一个线程间接提交事务 con.commit();
对于独自查问的状况,仿佛不会呈现数据错乱的状况。是因为在 JDBC 中,应用了锁进行同步

** 源码:**com.mysql.cj.jdbc.CallableStatement#executeQuery

connection 自身是线程不平安的,并且 connection 创立开销比拟大,所以个别应用数据库连接池来对立的治理 connection 对象,例如 druid 连接池,c3p0 连接池等等

数据库连接池

在应用数据库连接池时,一个线程中所有 DB 操作都是应用同一个 Connection 实例吗?
在 Spring 环境中,获取 connection 源码如下所示:
源码:org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection

非事务场景:在非事务创立中(同时没有应用 Spring 事务管理器),每一次拜访数据库,都是在 DataSource 中取出一个 Connection 实例,调用结束之后偿还资源,因而屡次调用,应该是不同的 Connection 实例

事务场景:在应用事务的状况下,实际上是在 ConnectionHolder 中获取的 Connection。而 ConnectionHolder 是在 TransactionSynchronizationManager 中获取的 resources 属性的值,即 connection 对象信息

源码:
org.springframework.transaction.support.TransactionSynchronizationManager#doGetResource

而 ThreadLocal<Map<Object,Object>> 线程上下文共享。即 Connection 对于与 Thread 绑定。因而在事务中无论操作多少次 DB,事实上都是操作的同一个 Connection 对象

2、MySQL 架构设计

SQL 接口:SQL 的规范来承受
SQL 解析器:了解这个 SQL 语句要干什么事件
查问优化器 :抉择一个最优的查问门路
执行器:执行器就会去依据咱们的优化器生成一套执行打算,而后不停的调用存储引擎的各种接口去实现 SQL 语句的执行打算
存储引擎:存储引擎其实就是执行 SQL 语句的,他会依照肯定的步骤去查问内存数据,更新磁盘数据,查问磁盘数据,等等,执行诸如此类的一系列的操作,MySQL 的架构设计中,SQL 接口,SQL 解析器,查问优化器其实都是通用的,他就是一套组件而已,然而存储引擎的话,他是反对各种各样的存储引擎的,比方咱们常见的 InnoDB、MyISAM、Memory 等等

3、InnoDB 内存构造

4、Buffer Pool

Buffer Pool: 缓冲池,简称 BP。其作用是用来缓存表数据与索引数据,缩小磁盘 IO 操作,提供效率
Buffer Pool 由缓存数据页和对缓存数据页进行形容的管制块组成,管制块中存储着对应缓存页的所属的表空间、数据页的编号、以及对应缓存页在 Buffer Pool 中的地址等信息
Buffer Pool 默认大小是 128M,以 Page 页为单位,Page 页默认大小 16kb,而管制块的大小为数据页的 5%,大略是 800 字节

留神:Buffer Pool 大小为 128M 指的就是缓存页的大小,管制块则个别占 5%,所以每次会多申请 6M 的内存空间用于寄存管制块

如何判断一个页是否在 Buffer Pool 中缓存?
MySQL 中有一个哈希表数据结构,它应用表空间号 + 数据页号,作为一个 key,而后缓存页对应的管制块作为 value

  • 当须要拜访某个页的数据时,先从哈希表中依据表空间号 + 页号看看是否存在对应的缓存页
  • 如果有,则间接应用;如果没有,就从 free 链表中选出一个闲暇的缓存页,而后把磁盘中对应的页加载到缓存页的地位

Page 页

Buffer Pool 的底层采纳链表数据结构治理 Page。在 InnoDB 拜访表记录和索引时会在 Page 页中缓存,当前应用能够缩小磁盘 IO 操作,晋升效率

Page 分类

Page 页依据状态分为三种类型 :

free page : 闲暇 page,未被应用
clean page : 被应用 page,数据没有被批改过
dirty page : 脏页,被应用 page,数据被批改过,页中数据和磁盘数据产生了不统一

Page 如何治理

针对下面所说的三种 page 类型,InnoDB 通过三种链表构造来保护和治理

  • free list : 示意闲暇缓冲区,治理 free page
    Buffer Pool 的初始化过程中,是先向操作系统申请间断的内存空间,而后把它划分成若干个管制块 & 缓存页的键值对
    free 链表是把所有闲暇的缓存页的管制块作为一个个的节点放到一个链表中,这个链表便称之为 free 链表
    基节点:free 链表中只有一个基节点是不记录缓存页信息(独自申请空间),它外面就寄存了 free 链表头节点地址,尾节点地址,还有 free 链表以后有多少个节点

    磁盘加载过程 :

    • 从 free 链表中取出一个闲暇的管制块(对应缓存页)
    • 把该缓存页对应的管制块的信息填上(例如:页所在的表空间、页号之类的信息)
    • 把该缓存页对应的 free 链表节点 (即:管制块) 从连贯中移除。示意该缓存页曾经被应用
  • flush list : 示意须要刷新到磁盘的缓冲区,治理 dirty page,外部 page 按批改工夫排序
    InnoDB 引擎为了进步解决效率,在每次批改缓存页后,并不是立即把批改刷新到磁盘上,而是在将来的某个工夫点进行刷新操作,所以须要应用到 flush 链表存储脏页,但凡被批改过的缓存页对应的管制块都会作为节点退出到 flush 链表

    脏页即存在于 flush 链表,也在 LRU 链表中,然而两种互不影响,LRU 链表负责管理 page 的可用性和开释,而 flush 链表负责管理脏页的刷盘操作

  • LRU list : 示意正在应用的缓冲区,治理 clean page 和 dirty page
    一般 LRU 算法
    LRU = Least Recently Used(最近起码应用) : 就是开端淘汰法,新数据从链表头部减少,开释空间的从开端淘汰

    • 当要拜访某个页时,如果不在 Buffer Pool,须要把该页加载到缓冲池,并且把缓存页对应的管制块作为节点增加到 LRU 链表的头部
    • 当要拜访某个页时,如果在 Buffer Pool 中,则间接把该页对应的管制块挪动到 LRU 链表的头部
    • 当须要开释空间时,从开端淘汰

    待持续。。。,喜爱的话,点赞加关注哈!

正文完
 0