mysql 细节解剖

一般来说,mysql使用同步+长连接+连接池的方式进行通信交互(但mysql也有异步和短连接)

默认存储引擎InnoDB

支持事务,支持行级锁和表级锁,支持读写不冲突

 

执行一条Select sql语句,执行流程

 mysql预读取,局部性原理

因为mysql InnoDB数据存储于磁盘,从磁盘读取到内存,最小读取单位是页Page,页在操作系统4K(4K对齐),但在innoDB设置为16K。我们操作数据库数据,其实是先操作内存里的数据页,再更新数据到本地磁盘。但不可能mysql内存每次都只是一页一页地读取和操作,所以innodb有内存缓存机制--BufferPool

BufferPool

bufferPool是innodb很重要的缓存机制,假设中途数据库奔溃了,那如何恢复处理?它也有持久化机制:redo log

redo log:属于InnoDB的机制,可以用于奔溃数据备份、控制事务(配合undo log使用?)

binlog:属于mysql系统级别的机制,它会记录DDL(create表 drop等)、DML(增删改)操作语句。默认关闭bin log功能(额外占用IO和磁盘空间)ps:mysql主从复制,也是通过使用binlog的特性实现的。

              1.用于数据恢复,他是全量备份(DDL、DML都记录)

              2.主从同步(slave 读取 master binlog)

Update语句执行流程

mysql索引结构由来

mysql索引数据结构为B+树,演变过程由二叉平衡树(过于高瘦)——> B树(趋于矮胖)——>B+树,B+树相较b树好处比较明显是:

1.innodb主键索引把每条完整数据都存放于叶子节点(innodb是放数据,myisam放的是数据地址指针),这非叶子节点所占用空间更小,提高IO每次读页的吞吐数,减少IO次数(二级索引【非主键索引】叶子节点存储的是二级索引和主键索引的键值,所以使用二级索引进行查询时,会查到叶子里的主键索引键值,再“回表”走一遍主键索引最终查到主键索引下的数据)

2.叶子节点的数据有指针顺序互相链接,这样当查询语句是范围大小查询的时候,只需要查一个边界值所在叶子位置,然后直接从有序的叶子节点找到数据区间。

题外:偶然也可以看到索引可以选择hash数据结构,但一般不建议。hash虽然查找很快,都是O(1),但由于hash碰撞以及hash结构建立所以需要计算hash值,导致数据顺序打乱。

mysql数据文件简要

show variables like 'datadir';  查看数据库数据文件存放路径

可以看到  *.ibd  *.myi  *.myd文件,其中myi、myd代表myisam引擎的索引、数据文件。idb是innodb的数据文件,注意innodb只有数据文件,因为索引的叶子节点是放数据的,所以都在同一个文件。

因此,Innodb 是索引的顺序决定数据存放的顺序,而决定物理数据存放顺序的索引,被称作聚集索引(innodb也就是主键索引)。

假如表不存在主键,也没有唯一或其他索引呢?这时候会用一个隐藏的列_rowid作为聚集索引

事务篇

事务的ACID特性,这里就不多说了

autocommit

很多人都知道,默认情况来说,在命令行输入一条update语句,这也包含了事务。但明明没有开启事务,那是因为mysql默认autocommit为ON。show global variables like 'autocommit';(顺便说show global variables like 'tx_isolation';可查看事务隔离默认级别)

事务其实本质上,就是我们的sql操作会先写进一个不可见的生成在内存空间的临时表,临时表会跟真实的表作比较,看是否通过校验,通过则提交。我们手动提交事务,其实就是控制了临时表做比较和提交这个过程。

事务并发三大问题

事务的四种隔离级别

Oracle只有RC和Serialiable隔离级别 。

选用种类:

互联网项目请用:读已提交(Read Commited)这个隔离级别!

innoDB锁的基本类型

其实锁,锁住的是索引(不存在主键和任何索引的表呢?其实不存在没有索引的表,假设没主键,会有个隐藏列_rowid作为索引的),假如select * where XX for update查询条件中不走索引(查全表),会导致锁全表,尽量避免这个情况。

select for update是行锁,但他真实效果不是锁定查询出来的行,而是锁定查询条件里索引对应的行

begin;
select * from t_stu where s_class = '213' and s_name = '李四g' for update;

//前提:s_name是二级索引,s_class只是一般字段
//因为没有相应的s_class记录,所以查询结果为空,但实际上会单独锁定s_name = '李四g'这行数据

当然,代码块的说法并不准确,for update的查询条件假设是范围区间的话,会有另一种基准锁行(间隙锁,区间锁算法,有兴趣再去mysql细节解剖第三节视频看)。

发布了21 篇原创文章 · 获赞 9 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/a5552157/article/details/104336527