mysql知识点

1.聚簇索引和非聚簇索引的区别

索引类型和存储类型是相关的
1.innodb存储引擎索引和数据存放在ibd文件中,myisam存储引擎存放在myd文件中
2.区分聚簇索引和非聚簇索引的区别,只要区分数据和索引是否存放在一起
3.innodb存储数据,数据和索引必须存放在一起,如果有主键就使用主键,没有就使用唯一键,没有唯一键就使用rowid,因此和数据绑定到一起的就是聚簇索引,而为了避免数据冗余,其他索引的叶子节点也存储了聚簇索引的key值,索引innodb既有聚簇索引也有非聚簇索引,myisam只有非聚簇索引

2.事务的隔离级别

mysql的事务隔离级别,一共有4中,从低到高,依次为:
读未提交(Read uncommitted)
  如果一个事务开始进行写操作,另一个事务不允许进行写操作。但允许其他事务读取此行数据。该隔离级别可以通过“排他写锁”实现。避免了数据的更新丢失,
  但是,可能会出现“脏读”,就是我一个事务读取到了其他事务未提交的数据
  脏读:事务A开启事务,查询id=1的数据,事务b也开始事务查询id=1的数据,事务a修改这条数据,事务b读取到了事务a未提交的数据
读已提交(Read committed) 解决“脏读”
  读取数据的事务允许其他事务访问该行数据,但是如果是写事务,将会禁止其他事务访问该行。隔离级别避免了脏读,但是有可能出现不可重复读
  不可重复读:事务a先读取了数据,事务b再去修改了这条数据,并且提交,这个时候事务a再去读取数据,发现数据不一致

可重复读(Repeatable read)解决“不可重复读”
  可重复读是指在一个事务内,多次读取同一个数据,在这个事务a还没有结束的时候,另一个事务b也访问该条数据,即使这个事务b修改了这条数据,事务a两次读取到的结果也是一样的,所有叫可重复读。
  但是有可能出现“
幻读
幻读:事务a先开启事务,查询id=1的数据,发现不存在,事务b也开启事务,查询id=1的数据,发现也不存在,事务b这个时候添加了这条数据,然后进行了提交,事务a这个时候再去添加这条数据,发现添加不上也查找不到
序列化(Serializable)解决“幻读”
  提供了严格的事务隔离,事务只能一个一个进行,不能并发操作,但是对性能会有一定的影响
https://www.cnblogs.com/bkhdd/p/15262342.html

 3.mysql的主从复制原理

1.从库通过change master to语句连接主库,提供了连接的一切条件(user,password,port,),并且让从库知道,二进制日志文件的起点位置(file名posiontion号),
2.从库的I/O线程和主库的dump线程建立连接
3.从库根据change master to语句提供的file名和position号,I/O线程向主库发起binlog的请求
4.主库的dump线程根据从库的请求,将binglog以日志的方式发送给从库I/O线程
5.从库的I/O线程接收到binlog 日志后,将binlog保存在relay-log中,传送过来的信息,会记录到master.info中
6.从库的sql线程会读取relay-log,并把应用过的记录到relay-log.info中,默认情况下,已经应用过的relay,会被清理掉

4.怎么处理mysql的慢查询

1.开启慢查询日志,定位查询慢的语句
2.看看是否加载了额外的数据,加载了不需要的列,对sql语句进行优化和重写
3.看看sql执行情况,索引的利用率
4.如果表中的数据很大,可以考虑横向或者纵向的分表

5.mysql索引类型有哪些,对性能的影响

1.主键索引:不允许值为空
2.唯一索引:可以保证数据记录的唯一性,数据值不可以重复,允许值为空
3.全文索引: 可以极大的提高检索效率,判断字符是否包含的问题
4.联合索引:索引可以覆盖多个数据列
5.普通索引:允许被索引的数据列包含重复的值


索引可以提高查询速度,通过使用索引,可以在使用过程中使用优化隐藏器,提高查询速度

但是在修改,删除,增加,的时候会降低速度,因为还要去操作索引文件

索引会占用物理空间,如果要建立聚簇索引,需要的空间就会很大,一旦有很多的非聚簇索引,聚簇索引发生了改变,所有的非聚簇索引都会跟着改变

 6.索引结构有哪些

索引的结构和存储引擎有关,mysql中使用较多的有b+树索引,hash索引,innodb索引实现是b+树

b+树索引:
b+树是一个平衡的二叉树,从根节点到每个叶子节点的高度相差不超过1,而且每个叶子节点之间有指针关联,所以查询的时候可以使用指针,双向移动

hash索引:
hash索引就是利用了一定的hash算法,将键值经过hash计算换算成哈希值,检索的时候不用像b+数那样从根节点到叶子节点逐级查找,只需要一次hash算法,就可以定位到对应的值

如果是等值查询,hash索引就有一定的优势,只需要一次计算,就可以找到对应的位置,前提是一样的值,如果键值不是唯一的,那就需要先找到该键所在的位置,然后通过链表往后扫描,找到对应的值

hash索引也没有办法利用索引排序,以及像like这样的模糊范围查询,也不支持联合索引查询

 7.mysql为什么选用b+tree来作为数据结构

memery存储引擎默认使用hash结构,因为是基于内存的
1.如果使用hash,当我们计算一个值的时候,如果计算出来的值都一样,就会忘一个区域一直追加数据,就会导致哈希碰撞问题,hash数据也分布不均匀
2.使用hash会存储在内存中,数据量大,会非常占用内存资源
3.根据某个key值会定位到某个hash值,如果都是等值查询,就很慢了
但是memery都是基于内存的,只要分配一个公平的hash算法,其他都是在内存中执行就很快了

 8.mysql事务acid的底层实现原理



mysql的基础架构一共分为3层
第一层就是处理客户端连接,以及认证授权的
第二层就是服务器层,主要用于sql的解析,优化,分析,包括所有存储过程的实现
第三层是存储层,主要负责数据的存储和提取,事务的实现,也是通过存储引擎去实现的


原子性:事务的执行单元,包含一个或者多个sql语句,再执行过程中,要么成功,要么失败,当事务执行失败的时候会通过undo.log日志文件来进行事务的一个回滚操作,也就是说,当我们在事务中执行一条insert语句,在回滚的时候就会执行一条delete语句,做一个相反的操作
持久性:事务一旦提交,对数据库的改变是永久性的,通过redo.log来实现。数据库的数据是存储在磁盘当中的,当我们每次去访问数据的时候,如果每次都请求磁盘,I/O的效率会比较低,所以innodb提供了一个缓存buffer,
这个buffer包含了磁盘当中一些数据页的映射,会先从buffer中去读取,如果没有的话,再从磁盘当中读取。这个时候其实还用到了redo.log,再执行过程中,因为redo.log是预写式日志,在写入数据的时候,
会将数据先写到redo.log文件中,在写到buffer缓冲区当中,这样保证了数据不会丢失,实现了数据的持久性。
    1.为什么redo.log比buffer直接将数据写入到磁盘快呢,因为写入buffer持久化是随机写的I/O,每次修改的数据位置都是随机的。redo.log是进行追加,每次在文件的尾部追加命令,属于顺序io
2.buffer持久化是以page为单位的,mysql默认配置页是16k,每次修改需要将整页的数据写入,而redo.log只需要修改实际需要操作的部分
    redo.log有三种持久化的机制 可以根据innodb_flush_log_at_trx_commit来设置
0 代表当事务提交日志的时候,并不将缓冲区的redo日志写入磁盘的日志文件,而是等待主线程每秒刷新
1 代表同步写入,当事务提交的时候,同步将redo日志写入磁盘当中
2 代表异步写入磁盘,在提交事务的时候,不能保证文件一定会写入磁盘,提交事务的时候先提交到缓存文件,在隔一秒写入到磁盘中
隔离性:事务中执行过程中是互相隔离的,不被打扰的
一致性:事务在执行前后,数据处于一种合法的状态,数据库的完整性约束没有被破坏,表现在比如主键的唯一,字段类型大小符合。原子性,隔离性,持久性,都是为了保证数据库的一致性

 9.mvcc的理解

mvcc(多版本并发控制)
mvcc是基于“数据版本”对并发事务进行控制

基于undo.log(回滚日志)事务在每次执行的时候,会记录一个事务id,会根据这个事务编号来进行版本标识
并且undo.log版本链并不是立即删除,而是mysql 在确定该版本链不会被“引用”后才会进行删除

ReadView是在“快照读”sql执行是mvcc提取数据的依据
快照读:select 语句 ,直接查询语句
当前读:update,delete,insert ,类似这种语句,先查找在更新就叫当前读
ReadView是一种数据结构,包含4个字段
比如说有四个事务,
m_ids:当前活跃的事务id集合 1,2,3,4
min_trx_id:最小活跃事务编号 就是1
max_trx_id: 预分配事务编号,当前最大事务编号+1    就是5
cteator_trx_id:readview创建者的事务编号 就是4


版本链数据库访问规则:
1.判断当前事务id等于cteator_trx_id吗,成立说明,数据就是当前事务更改的,可以直接访问
2. 判断trx_id(事务id)< min_trx_id,如果当前事务id小于最小活跃事务id,说明事务已经提交,可以访问
3. 判断trx_id(事务id)> max_trx_id,如果当前事务id大于最大最大事务id,说明当前事务是在readview生成之后,才开启,不允许访问
4. 判断 min_trx_id <= trx_id <= max_trx_id, 如果成立就在m_ids事务集合中对比,不存在的代表数据已经提交,可以访问


rc(读已提交):在每一次执行快照读的时候生成ReadView
rr(可重复读):在第一次执行快照读的时候生成readview,后面每次执行快照读都会复用

 

posted @ 2022-07-13 20:30  -韩  阅读(20)  评论(0编辑  收藏  举报