原创声明
本文作者:黄小斜
转载请务必在文章开头注明出处和作者。
本文思维导图
数据库和关系型数据库
作为一个程序员,不了解数据库怎么能行,那么数据库到底是个啥呢,作为一个Java工程师,平时和数据库打交道着实不少,所谓的CRUD其实就是对数据库进行增删改查的操作。
根据百度百科的介绍,数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、有共享的、统一管理的数据集合。数据库是以一定方式储存在一起、能与多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合,可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据进行新增、查询、更新、删除等操作。
是不是没听懂,好吧,简单来说,像MySQL这样的数据库,就是用于存储结构化数据的,比如一个学生的信息数据,一个商品的数据,或者是一个学生购买商品的消费数据。
联想到平时我们经常使用的Excel,其实和数据库挺像的,数据库其实就是一个表格,里面有很多的数据类型,比如字符串,比如数字,再比如长文本等等。
而这类数据库也叫关系型数据库,典型代表就是MySQL。
再看看百度百科的介绍,关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。用户通过查询来检索数据库中的数据,而查询是一个用于限定数据库中某些区域的执行代码。关系模型可以简单理解为二维表格模型,而一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织。
除了关系型数据库之外,近些年来还有很多nosql(not only sql)数据库在兴起,比如MongoDB,以及图数据库、列式数据库等等,这些数据库对于新手程序员来说用的并不多,所以本文我们只讨论关于关系型数据库的内容。
关系型数据库是我们程序员平时用的最多,也最简单易上手的数据库类型,所以,学习数据库一般也从MySQL这类关系型数据库入手,一来它简单好学,二来它是免费的。
我的数据库学习历程
我第一次听说“数据库”这个词还是在大学的时候,那时候正值大家找工作,有一个同学和我们分享自己的求职经验,据他所说,每个公司都会考察你的数据库知识,学好了数据库,面试什么公司都不怕。
当时我还觉得挺玄乎的,不过我们学校确实没来什么大公司,我对此半信半疑,至于到底是不是这样,后来也就没再追究了。
第二次接触数据库,是在学习Java的时候,记得当初自己跟着一个小教程,下载安装了MySQL,然后从网上下载了demo代码,用当时先进的开发工具eclipse跑通了别人家的代码,其实就是增删改查。
只不过当时对这些东西也没啥概念,后来又下载了一个db的可视化工具,可以更方便地了解自己的数据库里到底都有啥。
再到后来,我开始慢慢接触项目实战,使用数据库的时间也越来越长,自以为对于数据库的理解还算可以,直到我真正地接触了数据库相关的面试题,才让我发现自己对于数据库的理解是多么的肤浅。
那个时候,我只懂写一些简单的crud,甚至连内外连接、group by和count等一些简单的sql用法都不了解,除此之外,我对于数据库的一些原理性内容几乎也是一窍不通的,比如数据库的索引、事务、锁机制,我统统不知道,更别谈如何回答相关的面试题了。
于是,我开始意识到学习数据库原理是多么重要的一件事情,我开始看数据库方面的书籍,从最基础的数据库教材,再到MySQL的原理性内容,再到mybatis这类orm框架的实现,我都逐渐地开始学习和了解,直到我能够对大部分的数据库面试题都较好地掌握。
而现在,我在一个每天要处理海量数据的公司里工作,对于数据方面的学习已经不仅仅停留在数据库了,我还要接触数据仓库、分布式数据库以及各种大数据的应用场景,学习数据知识的道路看来短时间内是走不完了。
学习数据库,先从SQL入手
说到MySQL,就不得不谈谈SQL了,sql,按照百科的说法是这样的
结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。
对于不同的数据库,sql的写法可能有一些差异,但是大致都是相同的,就拿MySQL来说,平时我们用到最多的就是select、update、delete和insert了,这类操作统称为数据操纵语言DML(Data Manipulation Language),用户通过它可以实现对数据库的基本操作。
当然还有操作数据库和表的一些ddl,数据库模式定义语言DDL(Data Definition Language),是用于描述数据库中要存储的现实世界实体的语言。 简单来说,ddl其实就是用来执行建表,删表,更改表结构等操作的
以前我的sql写的并不多,毕竟简单的增删改查并不需要多复杂的sql技巧,最多就是做一下表连接。
再到后来,我开始做一些项目,接触了ORM的一些框架,比如hibernate和mybatis,这些框架甚至可以让你完全不写sql,只要调用一些增删改查的API即可,这让我很长一段时间都忽略了SQL的重要性。
其实学习sql最复杂的地方并不是一些高级用法,而是在于实际场景中的应用和优化。两条sql,可能因为简单的差异就会有很大的性能差距,差异点可能是,比如有没有走到索引,是否是全表扫描,又或者走到了哪个索引,而这样的性能分析只有在实际的场景里才有意义。
当然了,对于新手来说,学习sql的语法是放在第一位的,然后才能逐渐过渡到会使用,会优化,会分析。
关于数据库的那些面试题
想要真正学好数据库,搞定面试题中的相关问题,那你就必须要搞懂数据库的基本原理。
如果你不相信,那我随便举几个面试题常见的题型,比如”数据库事务的ACID是什么意思”、“数据库中有哪些锁”、“数据库的索引用的是什么数据结构”
上面几道题算是简易版的,在平常的面试中也经常能够看到,就算你只是背一背答案,可能也多少能答对一些,那么如果再进一步,考察一下数据库的原理性知识,恐怕就没这么简单了。
举个栗子“数据库事务的ACID是如何实现的”,“数据库中有哪些锁,分别是如何实现的,如何使用”、“数据库中的索引是如何实现的,何时命中索引,何时不能,为什么“
是不是感觉难度一下子就上来了。毕竟深入到原理性的东西,懂的人就越来越少了。除此之外,还有很多进阶的面试题,更多时候会结合实际场景来考察。
比如考察你对MySQL存储引擎innodb的理解,对于sql优化的理解 ,以及对于分布式场景下数据库能力的应用,比如分布式锁,分布式事务,以及分库分表的一些问题。
知道了面试题大概都考啥之后,接下来我们要做的就是找到症结所在,然后一一击破
数据库基本原理
学习数据库,你需要先打好基础,数据库原理是计算机科班的一门必修课,非科班的我选择的是自学,我当时也是拿着那本大学教材《数据库系统概论》来自学的。
教材这种东西,肯定还是偏理论的一点,我们要了解的内容主要包含几个方面
1、数据库模型有哪些:包括层次模型、网状模型和关系模型,我们所用的关系型数据库就是基于关系模型实现的。
2、关系数据库的基础和sql:了解关系数据库的基本概念,了解sql的基本使用方法,至少CRUD和一些常见用法要搞懂
3、数据库的安全性和完整性,这两部分内容其实理论的东西比较枯燥,实际上对应到实际场景中,安全性就是要保护数据的安全,包括权限控制和数据备份,而完整性则是通过一些约定和规范来限制数据库的存储内容,比如我们可以用主键、唯一键、非空等要求来限制字段的取值。
4、关系数据理论 这部分内容很有意思,也比较复杂,讲到了数据库的范式理论,从一范式到四范式,各有各的用法和要求,某互联网公司“第四范式”就是用这个概念来命名的。
5、事务和锁 最后一部分内容,就是数据库的两个重要组成部分,事务和锁,事务可以保证一组数据库操作的ACID特性,非常适用于需要数据一致性的场景,而数据库的锁不但是实现事务的基础,还可以灵活地适用于不同的数据库应用场景,我们还可以通过sql语句来完成加锁和释放,对于并发场景尤其管用。
MySQL的实现原理
学习完了数据库基础之后,接下来就该学习MySQL了,毕竟很多时候我们的数据库应用就是MySQL。
其实MySQL里的很多知识点和我们上面提到的数据库基础大同小异,而回到MySQL的实现层,我们就得来看看MySQL的存储引擎了。
MySQL的存储引擎分为innodb和myisam,相信大家对于这两个引擎区别的面试题看了也不少,比如innodb支持事务,支持行级锁,而myisam不支持。
由于现在innodb基本上是主流,所以我们讨论MySQL的时候基本上就是在讨论innodb。对于MySQL的实现原理,我认为大概有这么一些内容需要我们去学习。
首先,我们了解MySQL里有哪些数据类型,一般的用法如何,然后,尝试用MySQL去跑一些sql语句,建库建表,加索引加主键,总之,这些实践能帮助你更好地学习上述内容。
想要更好地了解MySQL的原理,我们就必须要了解MySQL的整体架构,一般来说,MySQL从上到下可以分为这么几层
客户端
也就是我们经常用的可视化工具,比如Navicat for MySQL
服务端
就是我们安装的MySQL程序,其实打开它它就是一个MySQL的服务端进程
sql执行层
sql执行层主要负责解析执行sql,里面包含了很多复杂的组成部分,比如解释器,分析器,优化器等等,执行层会生成一个sql的执行计划,这个计划也经常是我们分析sql性能的一个重要参考内容
存储引擎层
存储引擎层是innodb了,比如数据要如组织和存放,索引要如何建立和管理等等,加锁怎么加,事务如何实现,都是这一层要考虑的内容。
文件系统层
存储引擎的下一层就是文件系统了,数据库的数据如何和文件系统进行交互,就是这一层要做的事情了。
索引
不得不说,索引绝对是数据库中最经常考察,考点也最多的内容了。
比如给你一条sql,那么它能否命中索引,能命中哪些索引,如果想要命中某个索引,你应该如何修改,这种问题面试时是不是经常看到,变来变去这么多题型,其实面试官就是想考察你对于索引的理解。
还有就是,索引的数据结构,一样是非常热门的考点之一,索引其实是基于B+树来实现的,不知道b+树是啥,请回去看数据结构。
简单来说,它是一种多路搜索树,致力于更短的时间来完成数据检索,因为它的高度比二叉树要低,而比起普通的b树,它的非叶节点只起索引作用,而叶子节点是顺序串联的,所以非常适合做搜索树。
如果你理解了这一点,那么面对此类面试题就可以更加从容一些,面试官其实就是想知道你对b+树的了解到了什么样的程度而已。
事务和锁
除了索引之外,数据库中最复杂的内容可能就是事务和锁了。
就拿事务的ACID特性来说,你需要了解每个大写字母背后的实现原理,比如原子性是如何实现的,一致性是如何保证的,背后的原理是什么。
我们平时常用的事务可能就是spring里的事务模板,在事务里执行的同库数据库操作,要么都成功,要么都失败,这就是原子性。
两个事务之间互不影响,这就是隔离性,当然了,这里又涉及到了事务隔离级别。
事务隔离级别包括读未提交,读已提交,可重复读和序列化,每个事务隔离级别都适用于某种数据库读写场景,很多时候,我们都需要搞懂隔离级别背后的原理,才能更好地适用它。
MySQL里默认使用可重复读的隔离级别,这个级别基本上可以保证我们的事务按照预期执行,在MySQL中,这个事务隔离级别甚至可以解决幻读的问题。
在MySQL的事务背后,其实有一个隐藏的boss,那就是数据库的锁,很多事务的隔离级别都是通过锁来实现的,比如可重复读只要加行锁就可以实现了,而幻读则需要加上间隙锁next-key lock来实现。
行级锁和表级锁是MySQL中的两种锁,表级锁顾名思义,会直接锁表,一次只有一个事务能够访问,而行级锁其实锁的也并非是一行,在MySQL中,这个锁加在索引上,而这个索引对应的数据往往不止一行,所以这个行级锁只是理论意义上的"行级锁"
说了这么多,要理解MySQL的事务和锁,还是要多看看相关的书籍和文章,理解其内部的实现原理,知其然也要知其所以然。
下面又到了我们熟悉的资源推荐环节
推荐资源
书籍
数据库
0 《数据库系统概论》
数据库原理应该是教材吧,这本书作为数据库入门来说还是可以的,毕竟不是专门做DB的,看大厚书用处不大,这本书把数据库的基本概念都讲完了。
1 sql必知必会
这本书主要是讲解sql语句怎么写,毕竟数据库最重要的一点就是要熟练地使用sql语句,当然这本书也可以当做工具书来使用。
2 深入浅出MySQL
这本书适合作为MySQL的学习书籍,当你有了一定的MySQL使用经验后,可以看看它,该书从数据库的基础、开发、优化、管理维护和架构5个方面对MySQL进行了详细的介绍,讲的不算特别深,但是足够我们使用了。这本书我也只看了一部分。
3 MySQL技术内幕:innodb存储引擎
看完上面那本书以后,对MySQL算是比较熟悉了,不过对于面试中常考的innodb引擎,还是推荐一下这本书把,专门讲解了innodb存储引擎的相关内容。我还没有细看,但是内容足够你学好innodb了。
4 高性能Mysql
这本书可以说是很厚了,更适合DBA拜读,讲的太详细了,打扰了。
微信公众号【程序员黄小斜】
致力于让自学编程这件事变得更简单,授人以鱼也要授人以渔。作者自学编程转行互联网,目前是阿里巴巴Java工程师,专注于分享程序员前沿技术干货和编程学习心得,期待你的关注,和我们一起进步!
文中所提到的电子书都可以免费领取,在我的公众号后台回复“计算机网络”即可领取对应的下载地址。