Mysql笔记

==== =MySQL= ====

1、数据隔离级别分为不同的四种:

SERIALIZABLE :最严格的级别,事务串行执行,资源消耗最大;
REPEATABLE READ :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
READ COMMITTED :大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
READ UNCOMMITED :保证了读取过程中不会读取到非法数据。
上面的解释其实每个定义都有一些拗口,其中涉及到几个术语:脏读、不可重复读、幻读。
这里解释一下:
脏读(Dirty reads) :所谓的脏读,其实就是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。
不可重复读(non-repeatable reads) :不可重复读字面含义已经很明了了,比如事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。
幻读(phantom reads) :小的时候数手指,第一次数十10个,第二次数是11个,怎么回事?产生幻觉了?
幻读也是这样子,事务A首先根据条件索引得到10条数据,然后事务B改变了数据库一条数据,导致也符合事务A当时的搜索条件,这样事务A再次搜索发现有11条数据了,就产生了幻读。
一个对照关系表:
隔离级别 脏读(Dirty reads) 不可重复读(non-repeatable reads) 幻读(phantom reads)
SERIALIZABLE 不会 不会 不会
REPEATABLE READ 不会 不会 会
READ COMMITED 不会 会 会
READ UNCOMMITED 会 会 会
所以最安全的,是 SERIALIZABLE,但是伴随而来也是高昂的性能开销。
事务常用的两个属性:
readonly:设置事务为只读以提升性能。
timeout:设置事务的超时时间,一般用于防止大事务的发生。

2、 InnoDB 如何解决幻读问题
在 InnoDB 中分为快照读和当前读。快照读读的是数据的快照,也就是数据的历史版本;当前读就是读的最新版本的数据,并且在读的时候加锁,其他事务都不能对当前行做修改。
快照读:简单的 select 操作,属于快照读,不加锁。
select * from table where ?;
当前读:特殊的读操作,插入、更新、删除操作,属于当前读,需要加锁。
select * from table where ? lock in share mode;
select * from table where ? for update;
insert into table values (…);
update table set ? where ?;
delete from table where ?;
对于上面当前读的语句,第一条读取记录加共享锁,其他的全部加排它锁。
也就是说在做数据的修改操作时,都会使用当前读的方式,当前读是通过行锁和间隙锁控制的,此时是加了排他锁的,所有其他的事务都不能动当前的事务,所以避免了出现幻读的可能。
而为了防止幻读,行锁和间隙锁扮演了重要角色,下面简单说一下:
行锁
字面意思简单理解对数据行加锁,注意 InnoDB 行锁是通过给索引上的索引项加锁来实现的,也就是说只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
间隙锁
间隙锁就是用来为数据行之间的间隙来进行加锁。
举个例子:
select * from info where id > 5;

上面 SQL 中,其中 id 是主键,假设在一个 事务 A 中执行这个查询,第一次查询为一个 结果集 1 。在做第二次查询时,另一个 事务 B 在 info 表进行了插入数据 7 和 10 的操作。在 事务 A 再次执行此查询查询出 结果集 2 的时候,发现多了几条记录,如此便产生了幻读。
结果集1
6,8,9

结果集2
6,7,8,9,10

所以试想为了防止幻读,我们不但要现存的 id > 5 的数据行(6,8,9)上面加锁(行锁),还要在它们的间隙加锁(间隙锁)。
我们以区间来表示要加锁对象:
(5,6]
(6,8]
(8,9]
(9,+∞)
其中区间的右闭即为要加的行锁,而区间的范围即是要加的间隙锁。
3、对于数据库的优化可以从五个方面表述:
根据服务层面
配置mysql性能优化参数;
从系统层面增强mysql的性能:优化数据表结构
① 将字段较多的表分解成多个表
对于字段较多的表,如果有些字段的使用频率很低,可以将这些字段分离出来形成新表。因为当一个表的数据量很大时,会由于存在使用频率低的字段而使查询速度变慢。
② 增加中间表
对于经常需要联合查询的表,可以建立中间表以提高查询效率。通过建立中间表,把需要经常联合查询的数据插入中间表,然后将原来的联合查询改为对中间表的查询,以此来提高查询效率。
从数据库层面增强性能
优化SQL语句,合理使用字段索引。
从应用层面增强性能
使用缓存和NoSQL数据库方式存储,如MongoDB/Memcached/Redis来缓解高并发下数据库查询的压力。
提升数据库服务器硬件配置,或者搭建数据库集群
4、mysql的索引是什么样的一种数据结构呢
mysql底层使用B树的改良版B+树的数据结构。为什么使用B+树呢,下面具体分析.例如:此时有一个两列的数据表,要查询col2=89这行的数据,如图所示.

在不加索引的情况下,在mysql中进行查找,需要进行逐行扫描进行数据比较,先找第一行,值为34,不是,继续查找下一行,一直到第六行查找到我们需要的数据。每扫描一行数据都要进行一次磁盘读写,即磁盘I/o,磁盘i/o很耗费性能,cpu从磁盘中读取数据的时间远远没有从内存中读取数据的速度快,那么假如此时有100万条数据,查询的数据正好在最后一条,那就很不幸,需要等待半天
既然如此,就为该表加上一个索引,以col2为索引,构造一个二叉树,如图所示

5、 二叉树
二叉搜索树的定义:左子树的节点的都小于父节点的值,右子树的值都大于父节点的值,二叉树中每个节点中不仅存储的有数据,还有指向下一个结点的指针。根据这个特性构造一个二叉搜索树,此时,在进行查找89这个数据时,就会先去找根节点,将根节点的数据load到内存中,与89进行比较,发现比34大,则到右子树中进行查找,将89这个节点加载到内存中进行比较,两者相等,就正好找到了这个数据,根据该节点中存储的指针还能找到这行对应数据。这样仅经过了两次查询,就将需要的数据找到了,大大提高了查询效率。既然如此为何不采用二叉树作为mysql的索引的底层数据结构呢?
考虑这样一个问题,在二叉树中的,当索引为单边增长的数据时,就会出现失衡现象。如图所示:

此时就是一条链表,当查询89这条数据时,会进行六次磁盘i/o,基本上和没加索引在性能上没有什么提升。为此这种二叉树结构不适合作为mysql的底层索引的数据结构。
6、 红黑树
再来说一下红黑树,红黑树是一种特殊的二叉搜索树,当树的结构不平衡时,会进行自旋操作(左旋和右旋),将树保持在一个稳定的状态。如图3所示的单边增长的二叉树,使用红黑树后变为图所示:

在jdk1.8中hashmap的底层原理中就使用了红黑树。此时再去查找89这行的数据,仅需三次即可找到。查询效率也比较高。但是,Mysql底层的索引结构依然没有使用红黑树,原因在于,在实际的生产环境中,一个数据库的中的数据在至少有几十万条。就以100万条数据记录为例,则该红黑树的深度大约在20(2的20次方 ≈ 100万),查询的数据位于中间还好,假如查询的数据在叶子最后的叶子节点中,则需要进行20次磁盘的i/o操作,此时效率就比较低下了。因此也不适合作为mysql底层的索引数据结构。
7、B树和B+树
当树的深度过大时,会影响查询效率,那么能不能控制树的深度,在横向方面做文章呢?答案是肯定的,由此就引出了B树。B树的结构和红黑树很类似,只不过B树是一个多叉的搜索树。红黑树中,假设每个节点的大小为1kb,此时将该节点的大小设置为1M,那么这个节点中就可以存储更多的索引数据。B树的数据结构如图所示:

在b树的结构中,每个大的节点中存储很多的索引数据,每个分叉的节点中也存储了很多索引元素。这种结构符合树的特性,每个分叉中树的左子树小于父节点,右子树大于父节点。
节点中不仅存储的有索引元素,还有data数据。那么此时假如查找49这个元素,那么需要将第一个节点的数据load到内存中进行比较,进行一次磁盘i/o扫描,注意,将数据加载到内存中进行比较速度是非常快的,发现49比15大,比56小,通过指针指向下一个分支,继续进行第二次磁盘i/0,将第二个节点的数据load到内存中进行比较,查询到49这个索引元素,通过data中存放的指针指向该数据在磁盘空间中存放的数据地址,取到对应行的数据。
那么疑问来了,既然内存中比较数据比较快,为什么不直接将所有数据都存放在根节点中,将该节点中所有的数据都load到内存中进行比较呢?在实际的生产环境中,当数据达到百万或是千万级别的时候,这行数据所占的空间就非常大,cpu将所有的数据都load到内存中是非常耗费时间的,并且占用了大量的内存。在load到内存中的数据中,我们可能只使用了很少的一部分数据,造成大量的内存浪费。因此这种方法不可取。
在mysql中底层没有使用B树,使用的是B+树,是B树的一种改良版本。两者的主要区别在于:B+树将B树的非叶子节点中的数据放到叶子节点中,仅存放索引元素,这样做的目的是为了节省空间,能够每次尽量多的将节点中的数据load到内存中。(data中存放的是磁盘中那一行对应数据的地址指针)。在B+树中做了索引的冗余处理,让我们在查找数据时更方便。叶子节点中都有关键索引元素的一份完成的数据记录。叶子节点中通过指针连接。为什么要这样改造B树呢?mysql为了将b+树的深度控制在2-4之间,提高查询效率。

在mysql的官方的设置中,每个节点的大小为16kb,如上图所示,B+树的底层数据结构。假设此时索引为bigint类型,占8个字节,指向下个节点的指针(空格)大约占6个字节的大小。那么此时一个节点中可以存放的索引数量为:16kb/(8+6)B =1170个。按照这种情况,每个非叶子节点中可以存储1170个索引数据。那么此时假设B+树的深度为3,每个索引和data指针共占1kb大小(data根据数据引擎不同,存储的内容也不相同,在后面讲解)那么一个叶子节点就可以存放16个索引数据,那么此时计算一下,这个B+树可以存储的数据大小为1170 X 1170 X 16≈2000万,因此三层的B+树结构就可以存储2000万条数据。这样就很容易实现千万级别的数据查询。
8、Mysql的存储引擎
Msyql中的存储引擎是表级别的。在msyql中主要有两种引擎,innoDB和MyISAM。在讲这两种引擎以前,先来介绍一下聚簇(聚集)索引和非聚簇索引。
聚簇(聚集)索引:是指在在B+树的结构中,叶子节点中存放的索引为key值,data域中存放的是该行对应的其他数据。例如InnoDB的索引就是聚簇索引
非聚簇索引:在B+树中,叶子节点中存放的索引为key值,data域中存放的是磁盘中存放数据的地址指针。查询数据时,查到索引对应的地址指针,根据地址指针读取相应的数据。下图表示msyql的表结构存储在data目录下。可以自行查看

MyISAM:MyISAM中data域节点中存放的是一个指针,这个指针指向存放在磁盘中的数据。在B+树中使用MYISAM索引进行查询数据时,先将根节点的数据load到内存中,通过比较查找索引,到找到索引后,就根据data域中存放的指针去对应的磁盘地址获取数据。mysql的data目录中,使用MyISAM的存储引擎建立的表中,每一张对应有三个文件,如下图所示所示:

user表-MyISAM存储引擎-对应的表结构
三个文件分别是.frm,.MYD和.MYI的文件格式。
.frm文件存储的是这张表在数据库结构相关的数据
.MYD 文件中存放的是这张表的数据
.MYI 文件存放的是索引结构
InnoDB引擎:使用InnoDB引擎差创建的表中,data域中存放额数据和MyISAM不同,data域中存放的是该索引对应行的其他数据。因此InnoDB创建的表在数据库中存放的文件与MyIAM也不相同,如图所示:

InnoDB表的数据文件
可以看出,每张表只对应两个文件,分别是.frm结尾和.ibd结尾的文件。
.frm结尾的文件和MyISAM一样,都是存储的数据库结构相关的数据
.ibd结尾的文件存储的是索引和索引所在行的所有数据
在Mysql中,有时除了建立主键索引以外,还要建立辅助索引。辅助索引根据表的引擎不同,也有很大的区别。在MyISAM中,辅助索引和主索引一样,data域中存放的是指向数据在磁盘的地址指针。而在INnoDB中,辅助索引的data域中存放的是主键索引,这样在根据辅助索引查找数据时,会先找到主键索引,在根据主键索引查找相关的数据。因此在mysql的官方中推荐使用整型的主键索引,也是这个原因。
在实际的生产环境中,为什么不推荐使用UUID作为msyql的主键索引?我们知道,UUID是一个字符串类型的数据,当在数据库进行查找时,如果将UUID作为主键索引,将其load到内存中进行比较,先将字符串根据对应的ASCll转换成数字再进行比较,远没有整型数据使用起来高效;在一个,UUID是一个比较长的字符串,占用的内存空间比整型数据要大,那么同等情况下,使用UUID的对空间的利用率就比较低下。因此,无论是从时间还是空间角度分析,不推荐使用UUID作为主键索引。
9、 Hash结构
Msyql底层索引其实还有一种hash结构,Hash结构是将主键索引通过hash计算,得到一个散列码,将该散列码与磁盘中存放数据的地址指针进行绑定,乱序放入hash表中。在进行等值查找数据时,例如 where col=6 ,通过索引计算出hash值,根据hash值就在hash表中能够快速找到存储数据的地址指针,根据地址指针就能获取对应的数据。不管数据多大,只用计算一次能找到对应的数据。非常德尔高效。然后却不适合范围查找。在范围查找时,要将范围内的索引值一次次计算hash值,性能大大下降。
10、mycat是怎样实现分库分表的?
mycat里面通过定义路由规则来(路由规则里面会定义分片字段,以及分片算法)。分片算法有
多种,你所说的hash是其中一种,还有取模、按范围分片等等。在mycat里面,会对所有传递的
sql语句做路由处理(路由处理的依据就是表是否分片,如果分片,那么需要依据分片字段和对应
的分片算法来判断sql应该传递到哪一个、或者哪几个、又或者全部节点去执行)

<think>首先,用户的问题是关于“MySQL学习笔记教程”。根据系统指令,我需要使用中文回答,确保LaTeX语法正确,生成相关问题,并在回答中引用时添加引用标识。 回顾提供的引用: - 引用[1]:关于MySQL存储引擎的分类。 - 引用[2]:关于右外连接的SQL示例。 - 引用[3]:关于索引的解释。 用户意图是获取MySQL相关的学习笔记或参考资料。我的回答应该基于这些引用,但也要确保内容真实可靠,结构清晰。 回答结构: 1. **开头**:简要介绍MySQL学习笔记,并自然地引用相关部分。 2. **主体**:分步解释关键概念,使用引用支持。 3. **代码块**:如果适用,展示SQL示例。 4. **结尾**:生成相关问题。 关键点: - 使用中文。 - 行内数学表达式用$...$,但MySQL主题可能不涉及数学,除非是计算或公式。 - 独立公式用$$...$$,但同样可能不适用。 - 生成相关问题在末尾。 可能的MySQL主题: - 存储引擎(来自引用[1])。 - 连接操作(来自引用[2])。 - 索引(来自引用[3])。 构建回答: 1. **介绍MySQL学习笔记**:解释MySQL的基础知识。 2. **分步讲解**: - 存储引擎:解释分类,如InnoDB、MyISAM等,引用[1]。 - 连接操作:展示左外连接、右外连接示例,引用[2]。 - 索引:解释索引的重要性,如何工作,引用[3]。 3. **代码示例**:使用SQL代码块展示查询。 4. **生成相关问题**:在末尾添加相关问题。 确保引用: - 在相关段落末尾添加[^1], [^2], [^3]。 最终回答结构: - 标题或开头句。 - 分段讲解。 - 代码块。 - 相关问题。 生成相关问题: - 基于内容,如优化索引、存储引擎比较等。</think>### MySQL学习笔记教程 MySQL是一种广泛使用的关系型数据库管理系统,适用于各种规模的应用。本教程基于黑马程序员的视频教程和实际经验总结,涵盖核心概念如存储引擎、连接操作和索引优化。下面我将一步步解释关键知识点,确保内容真实可靠(参考自相关学习资料)。 #### 1. **MySQL存储引擎** 存储引擎是MySQL的核心组件,负责数据的存储、检索和管理。MySQL支持多种存储引擎,常见分类如下: - **InnoDB**:支持事务和行级锁,适合高并发写入场景(如电商系统)。 - **MyISAM**:不支持事务,但查询速度快,适合只读操作(如报表生成)。 - **Memory**:数据存储在内存中,速度快但易丢失,适合临时缓存。 - **Archive**:专为归档设计,压缩率高,但不支持索引。 存储引擎的选择取决于应用需求,例如事务性应用优先使用InnoDB[^1]。 #### 2. **连接操作**MySQL中,连接操作用于从多个表中关联数据。常见类型包括内连接、左外连接和右外连接。以下是一个右外连接的SQL示例,它返回右表(score)的所有记录,即使左表(stu)没有匹配项: ```sql SELECT stu.id, `name`, math FROM stu RIGHT JOIN score ON stu.id = score.id; ``` 此查询会输出所有成绩记录,包括那些没有对应学生信息的成绩(如新添加的成绩数据)。这有助于处理数据缺失场景[^2]。 #### 3. **索引优化** 索引是提升查询性能的关键机制。它通过构建数据模型(如B+树),避免全表扫描。例如: - **索引工作原理**:当执行`SELECT * FROM users WHERE id = 100;`时,如果有索引,MySQL直接定位到id=100的行,时间复杂度为$O(\log n)$;否则需扫描整个表,时间复杂度为$O(n)$。 - **创建索引示例**: ```sql CREATE INDEX idx_name ON users(name); -- 在name列上创建索引 ``` 索引能显著减少查询时间,尤其在大数据表中(如百万行以上)。但过度使用会降低写入速度,需权衡使用[^3]。 #### 4. **其他基础概念** - **事务处理**:使用`BEGIN TRANSACTION`, `COMMIT`, `ROLLBACK`确保数据一致性(ACID属性)。 - **数据类型**:如INT、VARCHAR、DATE等,选择合适类型节省存储空间。 - **性能调优**:结合`EXPLAIN`命令分析查询计划,优化慢查询。 本教程基于实际学习笔记整理,建议结合视频教程([黑马程序员MySQL教程](https://www.bilibili.com/video/BV1Kr4y1i7ru))实践练习[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值