什么是Mysql驱动
先通过maven引入一段配置
mysql驱动用来和数据库建立连接。
各种语言编写的代码,通过Mysql驱动去访问数据库。
什么是数据库连接池
处理多线程并发请求数据库建立连接,以及线程不断销毁和创建的效率问题。
常见的连接池:DBCP,C3P0, Druid
Mysql的连接池维护了与系统之间的多个数据库连接。系统跟Mysql建立连接的时候会传递过来账号,密码,库表权限。
Mysql架构设计
查询解析器
把传过来的sql解析成Mysql能看懂得语句
查询优化器
对sql语句进行优化,选择最优路径
执行器
用来调用存储引擎
存储引擎
用来操作磁盘
整体流程
首先会有一个线程去获取数据库连接池中的请求sql,通过Mysql内部sql接口进行接收,传给SQL解析器对sql解析成Mysql能够读懂的语言,解析之后,把sql交给查询优化器,对sql进行优化,选择出最优路径,就是执行计划,通过执行器按照执行计划,去调用存储引擎对磁盘数据进行操作。
存储引擎InnoDB
InnoDB中重要结构–bufferPool
sql语句在执行增删改查的时候会先将磁盘中的数据读取到内存中,内存中用来存储磁盘缓存数据的区域就存储在bufferpool缓冲池中。用来加快sql的执行速度。
innoDB提供的undolog和redolog
由于数据的增删改查都在内存的bufferpool中,如果某条数据在内存中进行了修改,但是此时磁盘中还没有进行存储,此时如果宕机或者断电,就无法将内存中的数据同步到磁盘中。
undolog:用来记录数据修改之前的记录,用来做回滚操作。
redolog:用来记录数据修改之后的值,用来断电恢复数据。事务提交之后,会将数据优先写入redolog。
binlog:mysql提供的日志、
bufferpool中的链表都有什么作用
mysql从磁盘读取数据都是读取一个内存页,在bufferpool中也是以一个一个的内存页进行存储的。每个缓存页会绑定一个描述数据,通过描述数据之间进行链表链接。
free链表:用来记录bufferPool中有哪些缓存页还空着,可以用来存放数据
flush链表:用来记录bufferPool中的数据页是脏数据,(就是数据进行了更新操作,但是还没有刷回磁盘)。每次进行刷盘的时候,就会把数据页从flush链表中删除,增加到free链表中。
lru链表:通过lru规则,把经常读取的数据放在链表的最前面不被清理掉,不经常使用的数据就会被移动到链表的尾部,从尾部开始进行刷盘。
因为mysql有预读机制,当去查询一条数据的时候,会把相邻的数据一起读进缓存,这样将就会导致之前使用频繁的数据被挤到链表的最后,导致提前被刷盘。所以lru链表采用了冷热链表的方法来解决这个问题。 lru链表被分成两个部分,前半部分为热数据区域,后半部分为冷数据。当数据刚开始被读进内存的时候,他会被放在lru链表的冷数据头部。当过了一秒钟之后再次被调用的数据,就会被移动到热数据区域的头部。为了避免频繁移动链表带来的开销,所以链表的前四分之一部分进行使用的时候不需要移动。
Mysql多事务并发隔离级别
MVCC机制:multi-version concurrent control 多版本并发控制机制
多个事务并发运行的时候,同时脏写一个数据,会产生脏写,脏读,不可重复读,幻读。、
脏写,两个事务更新一个数据,一个人回滚了,把另一个人的数据回滚没了
脏读: 就是一个事务读到另一个事务没提交时候的修改数据,然后另一个事务回滚了,下次读取不到了
不可重复读: 就是多次读写,别的事务多次修改并提交,导致多次读取的数值不一样。
幻读: 范围查询,每次查到的数据不一样,就是别的事务进行了插入。
针对这些问题有了 RU,RR,RR,和串行四个隔离级别。
RU:只能避免脏写
RC:避免脏写和脏读
RR: 避免脏读,脏写,不可重复读
串行让事务串行执行,避免所有问题
Mysql实现了MVCC机制,基于undolog多版本链条+readView机制。默认RR级别、
我们数据库中的每行数据,除了我们肉眼看见的数据,还有几个隐藏字段,得开天眼才能看到。分别是db_trx_id、db_roll_pointer、db_row_id。
db_trx_id:代表当前事务的id
db_roll_pointer:回滚指针,指向上一个版本的地址。
Read_View:读视图
Read View几个属性
trx_ids: 当前系统活跃(未提交)事务版本号集合。
low_limit_id: 创建当前read view 时“当前系统最大事务版本号+1”。
up_limit_id: 创建当前read view 时“系统正处于活跃事务最小版本号”
creator_trx_id: 创建当前read view的事务版本号;
Read View可见性判断条件
db_trx_id < up_limit_id || db_trx_id == creator_trx_id(显示)
如果数据事务ID小于read view中的最小活跃事务ID,则可以肯定该数据是在当前事务启之前就已经存在了的,所以可以显示。
或者数据的事务ID等于creator_trx_id ,那么说明这个数据就是当前事务自己生成的,自己生成的数据自己当然能看见,所以这种情况下此数据也是可以显示的。
db_trx_id >= low_limit_id(不显示)
如果数据事务ID大于read view 中的当前系统的最大事务ID,则说明该数据是在当前read view 创建之后才产生的,所以数据不显示。如果小于则进入下一个判断
db_trx_id是否在活跃事务(trx_ids)中
不存在:则说明read view产生的时候事务已经commit了,这种情况数据则可以显示。
已存在:则代表我Read View生成时刻,你这个事务还在活跃,还没有Commit,你修改的数据,我当前事务也是看不见的。