2020总结❤
年末了,也比较忙了,也多想陪陪家人了。闲下来的时候拍了一些照片
夕阳
美食
火
2020年终总结2020是一个极为不平凡的一年,开年的事情对我来说影响很大,复工延迟,隔离,种种事情,总是一件接着一件;刚过完春节去了趟北京,然后又急匆匆的赶回家,这件事情记忆很深的,回来的一路上坐的绿皮车,熬了一夜,真的很难受,经过了很多城市,也想起了很多往事,也明白了许多道理,有些道理就是在生活中,没经历过就是不会懂,就是这种感觉。绿皮车上就几个人,都拖着很多行李,我买的是晚上的票,非常冷,因为疫情的缘故,整个车上几乎没人说话,特别冷清,一瞬间感觉特别孤独,人在这种环境就最有可能胡思乱想,大概想了学业,工作,感情,未来,每次一想到这些东西就有点后怕,感觉自己就跟抑郁了一样。
即使这样,还是再次北漂。不过这次比较幸运,到了北京没几天就找到了一份工作,在但是环境中,自认为还是份不错的工作,工作也比较顺利,学到了很多东西,交识了许多朋友。
后来,回来升学,在几个同学的帮助下也考的还算不错吧,因为本身就没多少时间。
入学后,生活上也还算很适应,可也不少,每天泡在图书馆,还算充实,期末考前复习 ...
MySQL索引概览
提起优化SQL,你可能会把它理解为优化索引。简单来说这也不算错,索引在SQL优化中占了很大的比重。索引用的好,可以将SQL查询的效率提升10倍甚至更多。但索引是万能的吗?既然索引可以提升效率,只要创建索引不久好了吗?实际上,在有些情况下,创建索引反而会降低效率。
索引是万能的吗?首先我们需要了解什么是索引(Index)。数据库中的索引,就好比是一本书的目录,它可以帮我们快速进行特定值的定位于查找,从而加快查询的效率。
索引就是帮助数据库管理系统高效获取数据的数据结构。
如果我们不使用索引,就必须从第1条记录开始扫描,直到把所有的数据表都扫描完,才能找到想要的数据。既然如此,如果我们想要快速查找数据,就只需要创建更多的索引就好了呢?
其实索引不是万能的,在有些情况下使用索引反而会让效率变低。
索引的价值是帮我们从海量数据中找到想要的数据,如果数据量少,那么是否使用索引对结果影响并不大。
在数据表中的数据行数比较少的情况下,比如不到1000行,是不需要创建索引的。另外,当数据重复度大,比如高于10%的时候,也不需要对这个字段使用索引。我们之前讲过,如果是性别这个字段,就不需要对他创建索引。 ...
MySQL存储过程
存储过程,它是SQL的另一个重要应用,和视图一样,都是对SQL代码进行封装,可以反复利用。它和视图有着同样的优点,清晰、安全,还可以减少网络传输量。不过它和视图不同,视图是虚拟表,通常不对底层数据表直接操作,而存储过程是程序化的 SQL,可以直接操作底层数据表,相比于面向集合的操作方式,能够实现一些更复杂的数据处理。存储过程可以说是由 SQL 语句和流控制语句构成的语句集合,它和我们之前学到的函数一样,可以接收输入参数,也可以返回输出参数给调用者,返回计算结果。
什么是存储过程,如何创建一个存储过程存储过程的英文是Stored Procedure。它的思想很简单,就是SQL语句的封装。一旦存储过程被创建出来,使用它就像使用函数一样简单,我们直接通过调用存储过程名即可。
如何定义一个存储过程:
1234CREATE PROCEDURE 存储过程名称([参数列表])BEGIN 需要执行的语句END
在这里,我们使用CREATE PROCEDURE 创建一个存储过程,后面是存储过程的名称,以及过程所带的参数,可以包括输入参数和输出参数。最后由BEGIN和END来定义我们所要执行的语句块 ...
TCP可靠传输原理
如何实现一个靠谱的协议TCP协议为了保证顺序性,每个包都有一个ID。在建立连接的时候,会商定其实的ID是什么,然后按照哪个ID一个个发送。为了保证不丢包,对于发送的包都要应答,但是应答也不是一个一个来,而是会答应某个之前的ID,表示都收到了,这种模式称为 累计确认 或者 累计应答。
为了记录所有发送的包和接收的包,TCP也需要发送端和接收端分别都有缓存来保存这些记录。发送端的缓存里是按照包的ID一个个排列的,根据处理的情况分成四个部分。
第一部分:发送了并且已经确认的。
第二部分:发送了并且尚未确认的。
第三部分:没有发送,但是已经等待发送的。
第四部分:没有发送,并且暂时还不会发送的。
在TCP里,接收端会给发送端报一个窗口的大小,叫Advertised window。这个窗口的大小应该等于上面的第二部分加上第三部分,就是已经交代了没做完的加上马上要交代的。超过这个窗口的,接收端做不过来,就不能发送了。
于是,发送端需要保持下面的数据结构。
LastByteAcked:第一部分和第二部分的分界线
LastByteSent:第二部分和第三部分分界线
LastByteAcked+Ad ...
使用性能分析工具分析SQL
数据库服务器的优化步骤当我们遇到数据库调优问题的时候,该如何思考了?
整个流程划分成了观察(Show status) 和行动(Action)两个部分。字母S的部分代表观察(会使用相应的分析工具),字母A代表的部分是行动(对应分析可以采取的行动)。
我们可以通过观察了解数据库整体的运行状态,通过性能分析工具可以让我们了解执行慢的SQL都有哪些,查看具体的SQL执行计划,甚至SQL执行中的每一步的成本代价,这样才能定位问题所在,找到了问题,在采取相应的行动。
首先在S1部分,我们需要观察服务器的状态是否存在周期性的波动。如果存在周期性波动,有可能是周期性节点的原因,比如双十一、促销活动。这样的话,我们可以通过A1这一步骤解决,也就是加缓存,或者更改缓存失效策略。
如果缓存策略没有解决,或者不是周期性波动的原因,我么就需要进一步分析查询延迟和卡顿的原因。接下来进入S2这一步,我们需要开启慢查询。慢查询可以帮我们定位执行慢的SQL语句。我们可以通过设置long_query_time参数定义 “慢”的阈值,如果SQL执行时间超过了long_query_time,则会认为是慢查询。当收集上来这些 ...
MySQLMVCC
MVCC是什么,解决了什么MVCC的英文全称是Multiveion Concurrency Contol,中文翻译过来就是多版本并发控制技术。从名字中也能看出来,MVCC是通过数据行的多个版本管理来实现数据库的并发控制,简单来说它的思想就是保存数据的历史版本。这样我们就可以通过比较版本号决定数据是否显示出来,读取数据的时候不需要加锁也可以保证事务的隔离效果。
通过MVCC可以解决以下几个问题:
读写之间阻塞的问题,通过MVCC可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升事务并处理能力。
降低了死锁的概率。这是因为MVCC采用了乐观锁的方式,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。
解决一致性读的问题。一致性读也被称为快照读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。
什么是快照读,什么是当前读快照读读取的是快照数据。不加锁的简单的SELECT都属于快照读,比如这样:
1SELECT * FROM player WHERE ...
当前读就是读取最新数据,而不是历史版本 ...
MySQL基础架构
大体来说,MySQL可以分为Server层和存储引擎层两部分。
Server 层包括连接器、查询缓存、分析器、执行器等,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
而存储引擎负责数据的存储和提取。其架构模式是插件式的,支持InnoDB、MyISAM、Memory等多个存储引擎。现在最常用的存储引擎是InnoDB,它从MySQL 5.5.5 版本开始成为了默认存储引擎。
也就是说,你执行create table建表的时候,如果不指定引擎类型,默认使用的就是InnoDB。不过,你也可以通过指定存储引擎的类型来选择别的引擎,比如在create table 语句中使用 engine=memory,来指定使用内存引擎创建表。不同存储引擎的表数据存取方式不同,支持的功能也不同,在后面的文章中,我们会讨论到引擎的选择。
从图中不难看出,不同的存储引擎共用一个Server层,也就是从连接器到执行器的部分。
连接器第一步,你会先来接到这个数据库上,这时候接待你的就是连接器。连接器负责跟客户 ...
MySQL锁
索引和锁是数据库中的两个核心知识点,不论在工作中,还是在面试中,我们都经常会跟它们打交道。之前已经从不同维度对索引进行了了解,比如B+树,Hash索引、页结构、缓冲池和索引原则等,了解它们的工作原理可以加深对索引的了解。事务的隔离级别的实现都是通过锁来完成的,思考以下为什么我们需要给数据加锁呢?
实际上加锁是为了保证数据的一致性,这个思想在程序开发领域中同样很重要。在程序开发中也会存在多线程同步的问题。当多个线程并发访问某个数据的时候,尤其是针对一些敏感的数据(比如订单、金额等),我们就需要 保证这个数据在任何时候最多只有一个线程在进行访问,保证数据的完整性和一致性。
按照锁的粒度进行划分锁用来对数据进行锁定,我们可以从锁定对象的力度大小来对锁进行划分,分别为行锁、页锁 和表锁。
顾名思义,行锁就是按照行的力度对数据进行锁定。锁定力度小,发生冲突概率低,可以实现的并发度高,但是对于锁的开销比较大,加锁会比较慢,容易出现死锁情况。
页锁就是在页的力度上进行锁定,锁定的数据资源比行要多,因为一个页中可以有多个行记录。当我们使用页锁的时候,会出现数据浪费的想象,但这样的浪费最多也就是一个 ...
MySQL视图
视图,也就是虚拟表,本身是不具有数据的,它是SQL中的一个重要概念。从下面这张图,能看到,虚拟表的创建连接了一个或多个数据表,不同的查询应用都可以建立在虚拟表之上。
视图一方面可以帮我们使用表的一部分而不是所有的表,另一方面也可以针对不同的用户制定不同的查询试图。比如,针对一个公司的销售人员,我们只想给他看部分数据,而某些特殊的数据,比如采购的价格,则不会提供给他。
刚才讲的只是视图的一个使用场景,实际上视图还有很多作用。
如何创建,更新和删除视图视图作为一张虚拟表,帮我们封装了底层与数据表的接口。它相当于是一张表或多张表的数据结果集。视图的这一特点,可以帮我们简化复杂的SQL查询,比如在编写视图后,我们就可以直接重用它,而不需要考虑视图中包含的基础查询的细节。同样,我们也可以根据需要更改数据格式,返回于底层数据表格式不同的数据。
通常情况下,小型项目的数据库可以不使用视图,但是在大型项目中,以及数据表比较 复杂的情况下,视图的价值就凸显出来了,它可以帮助我们把经常查询的结果集放到虚拟表中,提升使用效率。理解和使用起来就都非常方便了。
创建视图:CREATE VIEW创建视图的语 ...
MySQL事务隔离级别
事务并发处理可能存在的异常都有哪些?在了解数据库隔离级别之前,需要了解设定事务的隔离级别都要解决哪些可能存在的问题,也就是事务并发处理时会存在哪些异常情况。实际上,SQL-92标准中已经对3种异常情况进行了定义,这些异常情况级别分别为脏读(Dirty Read)、不可重复度(Nnrepeatable)和 幻读(Phantom Read)。
脏读、不可重复读和幻读都代表了什么,比如有个英雄表heros_temp,如下所示:
这张英雄表,我们会记录很多英雄的姓名,假设我们不对事务进行隔离操作,那么数据库在进行事务的并发处理时会出现怎样的情况?
第一天,小张访问数据库,正在进行事务操作,往里面写入一个新的英雄 “吕布”:
12SQL> BEGINSQL> INSERT INTO heros_temp values(4,'吕布')
当小张还有提交该事务的时候,小李又对数据表进行了访问,他想看下这张英雄表里都有哪些英雄:
1SQL> SELECT * FROM heros_temp;
这时,小李看到的结果如下:
你有没有发现什么异常?这个时候小张还没 ...