数据库笔记搬迁

 
 
Mysql相关
mysql 分为 server 层和存储引擎
server层
  • 连接器:管理连接权限验证
  • 查询缓存:命中缓存直接换回查询结果
  • 分析器:分析语法
  • 优化器:生成执行计划,选择索引
  • 执行器:操作索引返回结果
server层
  • 连接器:管理连接权限验证
  • 查询缓存:命中缓存直接换回查询结果
  • 分析器:分析语法
  • 优化器:生成执行计划,选择索引
  • 执行器:操作索引返回结果
 
Mybatis
加载过程
mybatis底层还是采用原生的jdbc对数据库进行操作
解析配置文件,创建sqlSessionFactory建造者模式,
初始化Configuration对象,解析mappers节点时,会读取该节点下所有的mapper文件,
然后进行解析,并将解析后的结果存到configuration对象中。
对于每一次请求,创建一个sqlSession,然后对应mybatis里的
 
配置文件的基本结构
configuration —— 根元素
properties —— 定义配置外在化
settings —— 一些全局性的配置
typeAliases —— 为一些类定义别名
typeHandlers —— 定义类型处理,也就是定义java类型与数据库中的数据类型之间的转换关系
objectFactory
plugins —— Mybatis的插件,插件可以修改Mybatis内部的运行规则
environments —— 配置Mybatis的环境
environment
transactionManager —— 事务管理器
dataSource —— 数据源
databaseIdProvider
mappers —— 指定映射文件或映射类
 
下面我们简单分析下其中4个Builder:
1⃣️XMLConfigBuilder
解析mybatis中configLocation属性中的全局xml文件,内部会使用XMLMapperBuilder解析各个xml文件。
2⃣️XMLMapperBuilder
遍历mybatis中mapperLocations属性中的xml文件中每个节点的Builder,比如user.xml,内部会使用XMLStatementBuilder处理xml中的每个节点。
3⃣️XMLStatementBuilder
解析xml文件中各个节点,比如select,insert,update,delete节点,内部会使用XMLScriptBuilder处理节点的sql部分,遍历产生的数据会丢到Configuration的mappedStatements中。
4⃣️XMLScriptBuilder
解析xml中各个节点sql部分的Builder。
 
mybatis sql执行流程:
Configuration MyBatis所有的配置信息都保存在Configuration对象之中,配置文件中的大部分配置都会存储到该类中
SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能
Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数等
ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所对应的数据类型
ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
TypeHandler 负责java数据类型和jdbc数据类型(也可以说是数据表列类型)之间的映射和转换
MappedStatement MappedStatement维护一条<select|update|delete|insert>节点的封装
SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
BoundSql 表示动态生成的SQL语句以及相应的参数信息
 
缓存
一级缓存是SqlSession级别的缓存,每个SqlSession对象都有一个哈希表用于缓存数据,不同SqlSession对象之间缓存不共享。同一个SqlSession对象对象执行2遍相同的SQL查询,在第一次查询执行完毕后将结果缓存起来,这样第二遍查询就不用向数据库查询了,直接返回缓存结果即可。MyBatis默认是开启一级缓存的。
二级缓存是mapper级别的缓存,二级缓存是跨SqlSession的,多个SqlSession对象可以共享同一个二级缓存。不同的SqlSession对象执行两次相同的SQL语句,第一次会将查询结果进行缓存,第二次查询直接返回二级缓存中的结果即可。MyBatis默认是不开启二级缓存的,可以在配置文件中使用如下配置来开启二级缓存:
 
索引
优点:可以快速检索,减少I/O次数,加快检索速度;根据索引分组和排序,可以加快分组和排序;
缺点:索引本身也是表,因此会占用存储空间,索引表的维护和创建需要时间成本;
 
分类:主键索引 唯一索引 普通索引 全文索引 联合索引;
类型:BTree索引(B+Tree索引),哈希索引(无法进行范围查找),全文索引;
 
BTree是多路搜索树,查找复杂度为h*log(n),一般来说树的高度是很小的,一般为3左右;
B+Tree中的非叶子结点不存储数据,只存储键值;
B+Tree的叶子结点没有指针,所有键值都会出现在叶子结点上,且key存储的键值对应的数据的物理地址;
非叶子节点只存key,大大滴减少了非叶子节点的大小,那么每个节点就可以存放更多的记录,树更矮了,I/O操作更少了。所以B+Tree拥有更好的性能。
B树:一棵m阶B树是一棵平衡的m路搜索树
B+树:一棵m阶B树是一棵平衡的m路搜索树,同时数据节点只存在于叶子节点中,且叶子节点间增加了横向的指针
 
 
 
 
 
MyIsam InnoDb
MyISAM存储引擎的mysql对表会存储三个文件,后缀名 MYI(索引文件),后缀名MYD(数据文件),后缀名frm(表字段结构文件)。
在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址读取相应的数据记录
 
而对于InnoDB存储引擎的表会存储两个文件,后缀名frm(表字段结构文件),后缀名ibd(数据文件)。
在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,在走一遍主索引。 因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。
 
当数据库一条记录里包含多个字段时,一棵B+树就只能存储主键,如果检索的是非主键字段,则主键索引失去作用,又变成顺序查找了。
这时应该在第二个要检索的列上建立第二套索引。 这个索引由独立的B+树来组织。有两种常见的方法可以解决多个B+树访问同一套表数据的问题,一种叫做聚簇索引(clustered index ),一种叫做非聚簇索引(secondary index)。这两个名字虽然都叫做索引,但这并不是一种单独的索引类型,而是一种数据存储方式。
对于聚簇索引存储来说,行数据和主键B+树存储在一起,辅助键B+树只存储辅助键和主键,主键和非主键B+树几乎是两种类型的树。
对于非聚簇索引存储来说,主键B+树在叶子节点存储指向真正数据行的指针,而非主键。
 
 
 
 
 
事务
特性ACID:Atomicity(原子性),Consistency(一致性),Isolation(隔离性),Durability(持久性)
Spring对事务的支持,确实很强大,但是从本质上来讲:事务是否生效取决数据库底层是否支持(比如MySQL的MyISAM引擎就不支持事务,Spring能奈何!),同时一个事务的多个操作需要在同一个Connection上。事务也往往是在业务逻辑层来控制。
 
在方法执行前后进行拦截,然后在目标方法开始之前创建并加入事务,执行完目标方法后根据执行情况提交或回滚事务。
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。DataSource(sqlSessionFactory)、TransactionManager(事务管理器)这两部分只是会根据数据访问方式有所变化。
Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给持久化机制所提供的相关平台框架的事务来实现。
 
关于Connection和Session的区别:
Connection(连接)是一个物理概念,是指一个通过网络建立的客户端和专有服务器或调度器之间的一个网络连接
Session(会话)是一个逻辑概念,他存在于实例中,一个Connection可以拥有多个Session,也可以没有Session,同一个Connection上的多个Session之间不会相互影响
datasource数据源是注入给sessionfactory的,然后关联到session中。
 
 
隔离级别
1⃣️脏读(未提交读):事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2⃣️不可重复读(已提交读):事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
3⃣️幻读(可重复读):系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
4⃣️串行;
注:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
 
事务隔离级别针对的是读这种情况,如果是两个事务同时update,则一个事务是会被阻塞的,直到另一个事务提交才解决,所以可以认为update底层是串行执行的?
可重复读情况下,另一个事务就算提交了,这个事务里前后读取的值也不会变化。
select @@tx_isolation
 
 
传播行为
1.PROPAGATION_REQUIRED – 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
2.PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。
3.PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。
4.PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。
5.PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作
 
 
事务readonly:不能更新数据
数据库连接池:
DBCP(spring推荐)、C3P0(Hibernate推荐)、HikariCP、BoneCP、Proxool、JBoss DataSource、Druid。
 
Druid
替换DBCP和C3P0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池
可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。
 
 
SQL优化
mysql优化:mysql服务器的优化,各种参数常量设定,查询语句优化,主从复制,软硬件升级,容灾备份
什么样的sql不走索引?
1⃣️索引参与计算/使用函数计算
2⃣️like前%
3⃣️类型不一致
4⃣️存在or
5⃣️is null not null
 
 
MySQL有三种锁的级别:页级、表级、行级。
>>> mysql锁
可以显式的关闭Gap Lock:
1:把事务隔离级别改成:Read Committed,提交读、不可重复读。SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
2:修改参数:innodb_locks_unsafe_for_binlog 设置为1。
 
>>> mysql大数据量使用limit分页,随着页码的增大,查询效率越低下
对limit分页问题的性能优化方法
利用表的覆盖索引来加速分页查询
我们都知道,利用了索引查询的语句中如果只包含了那个索引列(覆盖索引),那么这种情况会查询很快。
因为利用索引查找有优化算法,且数据就在查询索引上面,不用再去找相关的数据地址了,这样节省了很多时间。另外Mysql中也有相关的索引缓存,在并发高的时候利用缓存就效果更好了。
 
1⃣️在我们的例子中,我们知道id字段是主键,自然就包含了默认的主键索引。现在让我们看看利用覆盖索引的查询效果如何:
这次我们之间查询最后一页的数据(利用覆盖索引,只包含id列),如下:
select id from product limit 866613, 20 0.2秒
相对于查询了所有列的37.44秒,提升了大概100多倍的速度
 
2⃣️那么如果我们也要查询所有列,有两种方法,一种是id>=的形式,另一种就是利用join,看下实际情况:
SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20
查询时间为0.2秒,简直是一个质的飞跃啊,哈哈
 
3⃣️另一种写法
SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id
查询时间也很短,赞!
其实两者用的都是一个原理嘛,所以效果也差不多
 
 
 
主从复制
1. 主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlog中;
2. 从:io线程——在使用start slave 之后,负责从master上拉取 binlog 内容,放进 自己的relay log中;
3. 从:sql执行线程——执行relay log中的语句;
 
 
>>> Mysql redo、undo、bin、relay log 区别
事务的简化过程
假设有A、B两个数据,值分别为1,2,现在修改为3、4
1. 事务开始。
2. 记录A=1到undolog。
3. 修改A=3。
4. 记录A=3到redolog。
5. 记录B=2到undolog。
6. 修改B=4。
7. 记录B=4到redolog,将redolog写入磁盘。
8. 事务提交。
 
既然redo log可以实现数据重做,那为什么要使用binlog?
因为redo log是Innodb实现的物理日志,一旦涉及到多种存储引擎,无法进行重做。
 
relay(中继) log:
从节点单独进程会将binlog 拷贝至本地 relaylog中。
从节点定时重放relay log。
 
 
>>> 事务是如何通过日志来实现基本流程如下:
因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的
状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。
 
 
>>> MySQL binlog的几种日志录入格式以及区别
1.Statement:每一条会修改数据的sql都会记录在binlog中。
2.Row:不记录sql语句上下文相关信息,仅保存哪条记录被修改。
3.Mixedlevel: 是以上两种level的混合使用 ,一般的语句修改使用statment格式保存binlog,如一些函数,statement无法完成主从复制的操作,则 采用row格式保存binlog,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,
 
查看慢sql日志是否开启:show variables like '%slow_query_log%'
 
如何监控你们的数据库的?你们的慢日志都是怎么查询的?
监控的工具有很多,例如zabbix,lepus,我这里用的是lepus(天兔),袋鼠云,druid。
 
是否做过主从一致性校验,如果有,怎么做的,如果没有,你打算怎么做?
主从一致性校验有多种工具 例如checksum、mysqldiff、pt-table-checksum等
 
 
分库分表
 
 
 
 
 
线上mysql版本5.6
数据库内存24000MB
最大连接数2000
 
 
 
时序时空数据库
Time Series & Spatial Temporal Database,简称 TSDB)是一种高性能、低成本、稳定可靠的在线时序时空数据库服务,提供高效读写、高压缩比存储、时序数据插值及聚合计算等服务,广泛应用于物联网(IoT)设备监控系统、企业能源管理系统(EMS)、生产安全监控系统和电力检测系统等行业场景;除此以外,还提供时空场景的查询和分析的能力。

猜你喜欢

转载自www.cnblogs.com/novalist/p/11621349.html