mysql01

 1、概述

Mysql可分为Server层和存储引擎层。server层包括连接器、查询缓存、分析器、执行器等,涵盖mysql的大多数核心服务功能,以及所有的内置函数(如日期、时间、数字和加密函数),所有跨存储引擎的功能都在这一层,比如存储过程、触发器、视图等

而存储引擎负责数据的存储和提取,其架构模式是插件式的,支持InnoDB、MyIsam、Memory等多个存储引擎,现在最常用的存储引擎是InnoDB,他从Mysql5.5.5版本开始成为了默认存储引擎。

连接器,进行数据库连接

查询缓存:拿到语句,会从缓存里看,是否执行过这条语句,之前执行过的语句及其结果可能会以key-value对的形式,(如果有表更新的话,跟这个表有关的查询缓存会失效,清空)

分析器:对sql语句进行解析,将字符串T识别表名T,字符串ID识别成列ID,将select识别为查询语句

 2、sql更新语句执行

重要的日志模块:binlog

Mysql整体来看,一块是server层,主要做的是MySQL功能层面的事情,还有一块是引擎层,负责存储相关的具体事宜。,redo log是InnoDB 引擎特有的日志,而server层也有自己的日志,称为binlog(归档日志)

why两份日志

因为最开始MySQL里并没有InnoDB引擎,mysql自带的引擎是MyISAM,但MyISAM没有crash-safe能力,binlog日志只能用于归档,而InnoDB是另一个公司以插件形式引入mysql,既然只依靠binlog是没有crash-safe能力的,所以InnoDB使用另外一套日志系统,也就是redo-log来实现crash-safe能力。

 两阶段提交:为了两份日志之间的逻辑一致

3、事务

SQL隔离级别:读未提交、读提交、可重复读和串行化

读未提交:一个事务还没提交时,他做的变更就能被别的事务看到

读提交:一个事务提交之后,他做的变更才会被其他事务看到

可重复读:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的诗句是一直的。

串行化:对于同一个记录,写会加写锁,读会加读锁,当出现读写冲突时,后访问的事务必须等前一个事务执行完成,才能继续执行

每条记录在更新的是否都会同时记录一条回滚操作,同一条记录在系统中可以存在多个版本,这就是数据库的多版本并发控制(MVCC)

回滚日志什么时候删除?系统会判断当没有事务需要用到这些回滚日志的时候,回滚日志会被删除。

什么时候不需要了?当系统要么有比这个回滚日志更早的read-view的时候

为什么尽量不使用长书屋?长事务意味着系统里面会存在很老的事务视图,在这个事务提交之前,回滚记录都要保留,这会导致大量占用存储空间,除此之外,长事务还占用锁资源,可能会拖垮库

4.索引

(1)哈希作用:提高数据查询效率

(2)常见索引模型:哈希表、有序数组、搜索树

(3)哈希表:键-值(key-value)

                        冲突处理方法:链表

                        使用场景:只有等值查询的场景

(4)有序数组:按顺序存储,查找用二分法就可以快速查询,时间复杂度O(log(N))

                        查询效率高,更新效率低

                        适用场景:静态存储引擎

(5)二叉搜索树:每个节点的左儿子小于父节点,父节点又小于右儿子

                                查询时间复杂度O(log(N)),更新时间复杂度O(log(N))

      InnoDB中的索引模型:B+tree

索引类型:主键索引、非主键索引

主键索引的叶子节点是整行的数据(聚簇索引),非主键索引的叶子节点内容是主键的值 (二级索引)

两者区别:主键索引只要搜索这个B+tree即可拿到数据,普通索引先搜索索引拿到主键值,再到主键索引数搜索一次(回表)

一个数据页满了,按照B+tree算法,新增加一个数据页,叫做页分裂,会导致性能下降,空间利用率降低大概50%,当相邻的两个数据页利用率很低的时候做数据页合并,合并的过程是分裂过程的逆过程

数据库底层存储的核心是基于这些数据模型的,每碰到一个新数据库,我们需要先关注他 数据模型,这样才能从理论上分析出这个数据库的适用场景

 回到主键索引树搜索的过程,称为回表

如何通过索引优化,避免回表过程?

1)覆盖索引

select ID from T where k between 3 and 5,此时只需要查ID值,而ID值已经在k索引树上了,因此可以直接提供查询结果,不需要回表,也就是说,在这个查询里面,索引k已经覆盖了我么的查询需求,称为覆盖索引。

覆盖索引可以减少树的搜索次数,显著提升查询性能

2)最左前缀原则

3)索引下推

mysql5.6引入的索引下推优化,可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数

5、锁

数据库锁设计的初衷是处理并发问题。

根据加锁的范围,mysql里面的锁大致可以分为全局锁、表级锁和行锁三类。

全局锁,对整个数据库实例加锁。命令是Flush tables with read lock(FTWRL),当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞;数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构)和更新类事务的提交语句。

全局锁的典型使用场景是,做全表逻辑备份,对于全部是InnoDB引擎的库,可以使用single-transaction参数,对应用会更友好

表锁一般在数据库引擎不支持行锁的时候才会用到

表级锁,语法是lock tables ... read/write,可以用unlock tables主动释放锁,也可以在客户端断开的时候自动释放

另一类表级锁是MDL(metadata lock),MDL不需要显式使用,在访问一个表的时候会被自动加上,MDL的作用是保证读写的正确性

MDL,当对一个表做增删改查时,加MDL读锁,当要对表做结构变更操作时,加MDL写锁

        读锁之间不互斥,可以多个线程同时对一张表增删改查

        读写锁之间、写锁之间是互斥的,用来保证变更结构操作的安全性。

6、行锁

行锁是针对数据表中行记录的锁

在InnoDB事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放,这是两阶段锁协议

死锁:当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁

解决两种策略:

一种策略是,直接进入等待,直到超时,这个超时时间可以通过参数innodb_lock_wait_timeout来设置

另一种策略,发起死锁检测,发现死锁后,主动回滚死锁链条中的某个事物,让其他事务得以继续执行,将参数innodb_deadlock_detect设置为on,表示开启这个逻辑

How解决由这种热点行更新导致的性能问题

Re:一种思路 如果能确保这个业务一定不会出现死锁,可以临时把死锁检测关掉。

        另一种思路:控制并发量。做在数据库服务端,

7、事务到底是隔离还是不隔离?

begin/start transaction命令并不是一个事务的起点,在执行到他们之后的第一个操作InnoDB表的语句,事务才真正启动,如果你想要马上启动一个事务,可以使用start transaction with consistent snapshot这个命令

第一种启动方式,一致性视图是在执行第一个快照读语句时创建的

第二种启动方式,一致性视图是在执行 start transaction with consistent snapshot创建的

视图的概念

        view,用查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果,创建输入的语法是create view,,而他的查询方法与表一样

        另一个是InnoDB在实现MVCC时用到的一致性读视图,即consistent read view ,用于支持RC(read committed 读提交)和RR(Repeatable Read 可重复读)隔离级别的实现

视图的作用是事务执行期间来定义“我能看到什么数据”

快照在MVCC如何工作?

InnoDB里面每个事务有一个唯一的事务id,叫transaction id,他是在事务开始时向InnoDB的事务系统申请的,是按申请顺序严格递增的

而每行数据也都是有多个版本的,每次事务更新数据的时候,都会生成一个新的数据版本,并把transaction id赋值给这个数据版本的事务id,记为row trx_id,同时,旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它

因此,数据表的一行记录,其实可能有多个版本(row),每个版本有自己的row_trx_id

可重复读的核心是一致性读(consistent read),而事务更新数据的时候,只能用当前读,如果当前的记录的行锁被其他事务占用的话,就需要进入锁等待。

读提交和可重复读区别:

        在可重复读隔离级别下,只需要在事务开始的时候创建一致性视图,之后事务里的其他查询都共用这个一致性视图

        在读提交隔离级别下,每一个语句执行前都会重新算出一个新的视图。

 InnoDB的行数据有多个版本,每个版本都有自己的row_trx_id,每个事务或语句有自己的一致性视图,普通查询语句是一致性读,一致性读会根据row_trx_id和一致性视图确定数据版本的可见性。

        对于可重复读,查询只承认在事务启动前就已经提交完成的数据

        对于读提交,查询值承认在语句启动前已经提交完成的数据

而当前读,总是读取已经提交完成的最新版本

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值