MySQL 从入门到删库跑路,保姆级教程!

[复制链接]
发表于 前天 17:36 | 显示全部楼层 |阅读模式
你是小阿巴,刚入行的步调员。

这天,你接到一个私活:帮学校做个门生管理体系,要能管理门生信息、记载结果、统计数据。
你一听,这不简单吗?用 Java 写个步调,把数据存到 Map 里就搞定了。
  1. public class StudentManagementSystem {<br>   // 使用 Map 存储学生信息,key 为学号,value 为学生信息字符串<br>   private Map<Integer, String> studentMap = new HashMap<>();<br>   // 添加学生<br>   public void addStudent(int studentNo, String name, double score, int classId) {<br>       String studentInfo = name + "," + score + "," + classId;<br>       studentMap.put(studentNo, studentInfo);<br>  }<br>   // 查询学生<br>   public String getStudent(int studentNo) {<br>       return studentMap.get(studentNo);<br>  }<br>   // 查询所有学生<br>   public void listAllStudents() {<br>       for (Map.Entry<Integer, String> entry : studentMap.entrySet()) {<br>           System.out.println("学号:" + entry.getKey() +<br>                   ",信息:" + entry.getValue());<br>      }<br>  }<br>}
复制代码
 
结果一周后,甲方指着你的鼻子骂道:狗阿巴,我录入的 500 个门生信息怎么全没了?!
你一查,原来昨晚服务器重启了,导致内存里的数据全部丢失!
你汗出如浆了:看来我得把数据生存到硬盘上……
于是你连夜改代码,把数据存到了文本文件里,这下数据就不会丢失了。

但接下来,甲方提出了各种差别的查询数据需求,每个需求你都得写一堆代码逻辑,让你越来越头大。

于是你找到号称 “后端之狗” 的鱼皮告急:有没有更好的办法管理数据啊?
鱼皮笑了笑:固然要用数据库啦!
你一脸懵:数据库?那是啥?
 
 
第一阶段:认识数据库

鱼皮:数据库就像一个超等 Excel 表格,可以存储管理海量数据、快速机动地查询和筛选数据、在多个服务器间共享数据、而且可以或许精确控制数据的读写权限。

你名顿开:啊,以是我应该用数据库来管理门生信息。🤡
鱼皮:没错,绝大多数项目标数据都存在数据库里,因此数据库是后端步调员的必备技能。
数据库紧张分 2 大类:
1)关系型数据库,比如 MySQL、Oracle、PostgreSQL,得当存储相互之间有关联的数据,比如门生和班级、订单和商品。

2)非关系型数据库,比如 Redis(紧张用于缓存和高速读写)、MongoDB(文档型数据库),它们在数据布局和使用场景上更机动。

 
你:这么多数据库,我该学哪个呢?
鱼皮:发起新手从 MySQL 开始,由于它是主流的、轻易入门的、开源的关系型数据库。
你:那还等什么,MySQL,启动!
鱼皮:别急,在学之前,得先相识几个数据库的根本概念。
1)数据库管理体系(DBMS):顾名思义就是用来管理数据库的体系,比如 MySQL。它把数据存储在硬盘上,断电也不会丢失。
2)数据库:一个 MySQL 体系可以管理多个数据库,比如每个项目一个库(门生系同一个库、订单系同一个库),互不干扰。
3)表:一个数据库可以有多张数据表,用来存储某一类数据。
4)记载:表由一行行记载构成,每一行就是一条数据
5)字段:每一列对应一个字段,具著名称和范例。比如姓名字段是文本范例、年龄字段是数字范例。

6)关联
这是关系型数据库的焦点,表和表之间是有接洽的,紧张有 3 种关系。
1 对 1:比如门生表和门生档案表,一个门生对应一份档案

1 对多:比如班级表和门生表,一个班级有多个门生

多对多:比如门生表和课程表,一个门生可以选多门课,一门课也可以被多个门生选

这些表和表之间的关联形成了完备的业务体系。
你想了想:对哦,也就是说我可以根据门生关联查询到所属的班级和选修的课程。
那怎么使用数据库呢?
鱼皮:这就要用到 SQL 了。
SQL 是专门用来使用数据库的 布局化查询语言(Structured Query Language)。
你可以用 SQL 实现各种查询,比如:
1)查询全部门生:SELECT * FROM student;
2)只查询属于某个班级的门生:SELECT * FROM student WHERE class_id = 1;

3)分组统计每个班级中全部门生的匀称结果:SELECT class_id, AVG(score) FROM student GROUP BY class_id;

4)还可以同时查询门生表和班级表,并把结果关联在一起:SELECT s.name, c.class_name FROM student s JOIN class c ON s.class_id = c.id;

别的,差别的数据库管理体系(比如 MySQL、Oracle、SQL Server)有本身的 “方言”,使用这些数据库的 SQL 会有一点点小差别。

你:天呐,相当于我要多学一门语言,而且还要学方言!
鱼皮:别担心,SQL 的焦点语法都是通用的。

而且你现在只必要知道 SQL 是用来使用数据库的就够了,
偶尔间再到我开辟的 免费 SQL 学习网站 边练边学,而且后续我还会出视频专门讲 SQL 哦。

 
你:关注了关注了~
鱼皮:那接下来咱们就开始实战学习吧,先把 MySQL 装上而且使用一波。
 
第二阶段:实战应用

根本使用

机敏如你,直接打开 官网 下载了 MySQL 数据库,而且乐成安装运行。

 
但是怎么使用 MySQL 呢?
鱼皮:可以使用官方提供的 下令行工具,先输入下令,输入默认设置的用户名和暗码,就能连上数据库并举利用用了。

你:root 是什么?
鱼皮:root 是数据库的超等管理员账号,拥有全部权限。
不外下令行看着不直观,我发起你装个 MySQL 可视化工具(比如 Navicat、DataGrip),能像使用 Excel 一样管理数据库,数据一清二楚。

你:哇,确实方便多了!
鱼皮:接下来我带你现实使用一遍,用数据库来管理门生信息。
1)起首毗连数据库
点击左上角创建毗连,选择数据库的种别,然后输入数据库设置信息,点击确认,就毗连乐成了。

 
2)然厥后创建一个数据库
右键点击数据库毗连,选择 “新建数据库”,定名为 school,点击确认,就创建乐成了。
对应的 SQL 语句是 CREATE DATABASE school;

 
3)接下来我们要创建表
鱼皮:想一想,假如要筹划一个存储门生信息的表,必要哪些字段?
你:学号、姓名、结果、班级。
鱼皮:没错,每个字段还要指定范例。

  • 学号用 int 整数范例
  • 姓名用 varchar 文本范例
  • 结果用 decimal 小数范例(保存 2 位小数)
  • 班级用 int 整数范例(体现班级编号)

除了范例,创建表时还要设置一些 束缚,比如:

  • 主键:每条数据的唯一标识,一样寻常发起每个表单独加一列 id 字段,作为主键
  • 非空:某些字段不能为空,比如姓名不能为空
  • 唯一:值不能重复,比如每个学号都是唯一的
  • 外键:创建表之间的关联关系,比如门生表的 class_id 可以设为外键,关联到班级表的 id,包管数据的完备性。但现实开辟中外键存在性能标题,用的没那么多。

筹划好表布局之后,点击生存,数据表就创建乐成了。
对应的 SQL 语句雷同如许:
  1. CREATE TABLE student (<br>  id INT PRIMARY KEY AUTO_INCREMENT,  # 主键,自动递增<br>  student_no INT UNIQUE NOT NULL,     # 学号,唯一且非空<br>  name VARCHAR(50) NOT NULL,          # 姓名,非空<br>  score DECIMAL(5,2),                 # 成绩,最多 5 位数字,2 位小数<br>  class_id INT                        # 班级编号<br>);
复制代码
 
4)然后我们就可以使用数据表了。紧张有 4 类焦点使用 —— 增编削查。
先插入几条门生数据:
  1. INSERT INTO student (student_no, name, score, class_id) <br>VALUES (2024001, '小阿巴', 95.5, 1);
复制代码
然后查询全部门生数据:
  1. SELECT * FROM student;
复制代码

修改某条数据,把你的结果改成满分:
  1. UPDATE student SET score = 100 WHERE student_no = 2024001;<br>​<br>SELECT * FROM student;
复制代码
末了删除某条数据:
  1. DELETE FROM student WHERE student_no = 2024001;<br>​<br>SELECT * FROM student;
复制代码

鱼皮:注意,删撤除的数据就再也找不返来了!
因此现实项目中发起使用 逻辑删除,就是加个 is_deleted 字段来标志数据是否失效,而不是真的删除数据,如许纵然误删也能规复。

 
客户端使用

你非常高兴:用可视化工具真方便啊,但是我怎么用代码使用数据库呢?
鱼皮:主流编程语言都有使用数据库的 SDK,比如使用 Java 的 JDBC,必要先加载对应数据库的驱动、然后获取毗连、编写 SQL 语句并实验、末了网络结果并关闭毗连。

你挠了挠头:我就查询 1 次数据库,都要写这么多代码么?而且我根本不会写 SQL 语句啊!
鱼皮笑道:没关系,现实开辟中我们会使用 ORM 对象关系映射框架,可以把数据库的表映射成 Java 对象,像使用对象一样使用数据库。

比如 Java 的 MyBatis 框架,可以让你用更轻便的方式实验 SQL:
  1. // MyBatis 方式:只需要写 SQL,框架自动处理连接和结果映射<br>Student student = studentMapper.selectByStudentNo(2024001);<br>System.out.println(student.getName());
复制代码
尚有它的加强版 MyBatis Plus 和 MyBatis Flex,提供了更多开箱即用的功能,连 SQL 都不消写!直接调用现成的方法,几行代码就能实现增编削查,告别 SQL Boy!

你感叹道:这才是人写的代码啊!优雅,真是优雅~
鱼皮提示道:但是,框架不是全能的,有些复杂查询的 SQL 还要本身手写,不外现在有 AI 了,写个 SQL 还不是手拿把掐的?
你:明确了,我这就用框架重写门生管理体系。
 
第三阶段:数据库特性

索引

一个月后,你重写的门生管理体系正式上线,不但得到了甲方的好评,而且很快火遍了天下高校。
你心田暗爽:数据库也不外云云嘛~

但你没想到,随着门生数据量的暴涨和表布局的扩展,你的数据库查询速率也越来越慢,光是查询某个班级的门生竟然都要等好几秒!
你有些惊讶:我这 SQL 也不复杂啊,怎么查询这么慢?
鱼皮:加个索引试试?
你:索引?那是啥?
鱼皮:索引就是数据库的目次。你现在查数据,数据库得一行一行全表扫描,数据量越大速率越慢。加了索引后,数据库可以通过索引快速定位到数据,就像通过书的目次快速翻到某一页。

你名顿开:对啊,老师常常按班级查询门生,不妨给班级字段添加索引。
  1. CREATE INDEX idx_class_id ON student(class_id);
复制代码
添加索引后,你再次测试查询,竟然只要几十毫秒!
你冲动得跳了起来:索引太香了,我要给全部字段都加索引~
鱼皮摆摆手:别,索引可不是越多越好!
你愣住了:为啥?
鱼皮:索引固然能加速查询,但也有代价。

  • 一方面会增长写入数据(增编削)的开销。由于每次写入数据,索引也要更新。
  • 别的,索引本身也是数据,要占用更多的存储空间。

以是,要在常常用来查询、而且数据区分度高的字段上公道添加索引。比如班级 ID、学号这种字段得当加索引,但性别字段(只有男女两个值)就不得当。

 
事件

又过了几天,甲方又提新需求了。
甲方:小阿巴,有老师反馈标题判错了,必要批量把全部门生的结果都加 5 分。
你信心满满:简单,不就是个批量更新使用么?
你写了一段代码,循环更新全部门生的结果。

没想到,越自负 Bug 越多,功能刚刚上线,就收到了投诉:怎么有些门生的结果改了,有些没改?
你检察了下日记,发现前面门生的结果更新乐成了,但由于网络颠簸,导致反面的门生都没更新。

你急坏了:咋办,如许就不公平了啊!
鱼皮看了看你的代码:这是典范的数据同等性标题,你必要用 事件 来办理。
你:啥是事件?
鱼皮:事件就是把多个使用捆绑在一起,要么全部乐成,要么全部失败。

就像你给别人投币,你扣除硬币和对方增长硬币必须同时乐成,不能让硬币凭空消散对吧?
你:对对对,那批量改结果也是,要么全部门生都加 5 分,要么都不加。
鱼皮:没错,数据库事件有 4 个特性,简称 ACID:

  • 原子性(Atomicity):要么全做,要么全不做。
  • 同等性(Consistency):数据从一个精确状态到另一个精确状态。比如转账时,A 扣钱和 B 加钱的总和稳定。
  • 隔离性(Isolation):多个事件互不干扰。
  • 长期性(Durability):事件完成后,数据永世生存。

你:那怎么使用事件呢?
鱼皮:假如直接用原始的 JDBC,必要手动控制事件,比力贫困。
但假如在 Spring 框架中,只必要加一个 @Transactional 注解就搞定了:

Spring 会自动帮你管理事件。假如中心任何一步堕落,抛出了指定的非常,整个事件会自动回滚,将数据规复到原来的状态,包管要么全部门生都加分乐成,要么都不加。

你:原来这么简单啊,我这就用事件重写代码!
 
其他

鱼皮:MySQL 尚有一些其他特性,比如视图可以用来简化复杂查询、存储过程可以批量实验 SQL、触发器可以自动触发使用。
1)视图:视图是一个假造表,把复杂查询封装起来重复使用。比如你常常要统计每个班级的匀称结果,每次都写一长串 SQL 太贫困,可以创建一个视图,以后直接查视图就行。
2)存储过程:可以批量实验 SQL。比如天天定时同步数据,写个存储过程,定时调用就行。
3)触发器:可以自动触发使用。比如每次添加用户,自动天生一条使用日记,不消手动写代码。

你感叹道:原来数据库尚有这么多功能,我学不完了啊……
鱼皮笑了:别担心,这些在现实开辟中用得不多,先简单相识就好。
 
第四阶段:生产情况实践

几年后,你已经成为小著名气的 “门生管理体系大家”,还建立了本身的工作室。
没事儿就对着新来的练习生阿坤吹牛皮:你阿巴哥我啊,醒目数据库,索引、事件耍的贼溜儿~

然而某天上午,学校的运维同砚打来电话:阿巴阿巴,体系出标题了,全部使用都不停 转圈、超时! 好像是数据库卡死了!

你大惊:什么?!我都加索引了,还能卡死?

emmm…… 对了,我想到了!
赶紧重启数据库,重启办理全部标题!嘿嘿嘿哈哈哈哈~

结果重启没多久,数据库又卡死了!
你彻底懵了:呜呜呜,怎么办啊!
这时,你身旁的阿坤忽然鸡叫起来:我来!

 
为什么体系会瓦解?

阿坤:我们先看看为什么体系会瓦解?
开启 MySQL 的慢查询日记功能,有两种方式。
1)通过 SQL 下令(临时开启)
  1. # 开启慢查询日志日志功能<br>SET GLOBAL slow_query_log = 1;<br>​<br># 设置慢查询阈值(超过几秒算是慢查询)<br>SET GLOBAL long_query_time = 5;<br>​<br># 修改日志日志文件位置(可选)<br>SET GLOBAL slow_query_log_file = '/path/to/slow.log';
复制代码
2)修改设置文件(永世收效)
  1. # 在 [mysqld] 部分设置参数<br>slow_query_log = 1<br>long_query_time = 5<br>slow_query_log_file = /path/to/slow.log
复制代码
 
你看,有些 SQL 语句实验了几十秒!

使用 Explain 下令分析下这些查询,原来没有精确使用索引,导致了全表扫描,把数据库拖垮了。

这些慢查询就是罪魁罪魁,它们会 长时间霸占数据库毗连和 CPU 资源。当大量用户同时实验慢查询,数据库毗连池很快被耗尽,新的哀求由于无法获取毗连、全部壅闭,导致数据库 “卡死”。

你内疚地低下头:我知道了,生产情况肯定要开启慢查询日记,及时发现慢 SQL 并优化。
 
数据丢失了怎么办?

屋漏偏逢连夜雨,你很快又收到了投诉,说是有的门生数据丢失了!
你非常迷惑:MySQL 不是有日记(Redo Log 和 Binlog)来包管数据长期性吗?怎么会丢数据呢?

颠末排查,原来是服务器的硬盘被一个门生不鉴戒踹坏了!
你难熬得像持矢了一样:真是人在家中坐,Bug 天上来。

唉,我怎么把数据找返来啊?
阿坤:别怕,幸好鱼皮哥之前设置了备份。一方面定期做 全量备份,比如使用 mysqldump 工具天天破晓备份一次并发送到其他服务器上;再共同 增量备份,使用 Binlog(二进制日记)记载每次的数据修改使用,如许纵然数据库崩了,也能规复到近来的状态。

 
怎么包管体系不会再崩?

你松了一口吻:那怎么包管数据库不会再宕机呢?
阿坤:可以搭建 MySQL 高可用集群,典范的是 一主多从 架构。
主库(Master)专门负责写使用(增编削),并通过 Binlog 记载每一次数据变动使用。
从库(Slave) 拉取主库的 Binlog 到本地文件中,然后回放数据变动使用,实现数据同步。我们可以使用从库来负担绝大部门的读使用,这叫 读写分离,能大大提升并发本领。

当主库出现故障时,使用 MHA 等工具,自动将一个从库提升为新的主库,并调解其他从库的指向,实现故障的自动切换。

 
数据量大了怎么办?

你非常惊讶:之前完全没听说过这些啊……
阿坤用看流离狗的眼神看了你一眼:阿巴哥哥,假如数据量特殊大,一个库存不下怎么办?
你默不作声:阿巴阿巴……
阿坤笑了:固然是 分库分表 啦!比如
1)水平拆分:把同一张表的数据分散到多个表或多个库中。比如根据门生 ID 的尾号,奇数的存到表 1,偶数的存到表 2。

2)垂直拆分:按业务功能来拆分库,比如把门生根本信息、结果信息、选课信息分别存到差别的库中。

你彻底服了:妙啊,如许就能存储海量数据了!
 
其他实践

这时鱼皮走过来拍了拍阿坤的肩膀:小伙子年轻有为啊!
小阿巴,MySQL 生产情况实践的知识点尚有很多。比如:
1)权限管理:不要全部人都用 root 账号,风险太大,要给差别的人分配差别的权限。
2)云数据库服务:提供了现成的 MySQL 集群架构、监控监控体系、自动备份、数据迁徙等,比本身运维省心多了。

3)调优本领:硬件优化、数据库设置优化、库表筹划优化、SQL 优化、毗连池优化等等。
4)常见标题:尚有死锁排查、大表的在线变动、数据迁徙、主从延长处置惩罚等等,遇到了再去办理。
你羞愧地抬不起头:我以为本身已经把握了数据库,原来只是学了个皮毛……

 
第五阶段:深入底层原理

于是,你自动找到阿坤:我想深入学习 MySQL,不能只停顿在会用的层面,叨教怎么学习底层原理啊?
阿坤有些惊讶:咦?你不 背八股文 的么?刷刷题就好了呀!
你震惊了:现在的练习生,竟然可骇如斯!

 
鱼皮:阿坤你别逗他了,着实我们可以带着标题学习。比如 MySQL 是怎样实现高效查询的
你想了想:加索引?
鱼皮:对,但这只是使用层面。底层实现有很多技能,比如高效的存储引擎(InnoDB)、精良的索引布局(B+ 树)、缓冲池机制、查询优化器等等。

比如我考考你,下面两个 SQL 语句哪个实验更快?
  1. # SQL 1: 使用 OR<br>SELECT * FROM student WHERE class_id = 1 OR class_id = 2;<br>​<br># SQL 2: 使用 IN<br>SELECT * FROM student WHERE class_id IN (1, 2);
复制代码
你:额…… 第 2 个?由于它更简短。
鱼皮:哼哼,答案是 险些一样快!由于 MySQL 的查询优化器非常智能,它会分析语句、将它们处置惩罚成雷同的逻辑布局,再去实验。
这就是 MySQL 能高效查询的缘故起因之一,带着这些标题去阅读相干文章,大概直接像阿坤说的刷一刷 MySQL 口试题,就能快速学会很多焦点知识点。

假如想体系学习,可以看看《MySQL 是怎样运行的》、《高性能 MySQL》这几本书。

要记取,学习底层原理不但是为了应付口试,而是为了更好地使用 MySQL,遇到标题时可以或许快速定位息争决。
你:好的,我这就去学!
 
末端

多少年后,你已经成为了大厂的数据库专家。不但能纯熟筹划库表、优化性能,搭个 MySQL 集群也是手拿把掐的。
!

你也像鱼皮当时一样,耐烦地给新人分享学习数据库的履历:数据库是实战型技能,肯定要多动手实践。

再次遇到鱼皮是在一条惨淡的小巷,此时的他年过 35,灰头土脸。你什么都没说,只是给他点了个赞,不打搅,是你的温柔。

更详细的 MySQL 数据库学习门路,可以在编程导航免费阅读哦。
 
更多编程学习资源


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表