说一说MySQL一条SQL语句的执行过程?

典型回答 如一条简单的查询语句:<font style="color:rgba(25, 26, 31, 0.9);">select * from users where age='18' and name='Hollis';</font> 执行过程如下图: 结合上面的说明,我们分析下这个语句的执行流程: ①使用连接器,通过客户端/服务器通信协议与 MySQL 建立连接。并查询是否有权限 ②Mysql8.0之前检查是否开启缓存,开启了 Query Cache 且命中完全相同的 SQL 语句,则将查询结果直接返回给客户端; ③由解析器(分析器)进行语法分析和语义分析,并生成解析树。如查询是select、表名users、条件是age=‘18’ and name=‘Hollis’,预处理器则会根据 MySQL 规则进一步检查解析树是否合法。比如检查要查询的数据表或数据列是否存在等。 ...

March 22, 2026 · 1 min · santu

阿里的数据库能抗秒杀的原理

典型回答 其实,在阿里电商的秒杀等(据我了解,淘宝、天猫、猫超、大麦等都是这么干的)场景中,主要还是基于MySQL数据库在做扣减的,主要是因为这样做最可靠了(避免了redis扣减方案中的数据不一致、少卖等问题)。 但是我们都知道,数据库是抗不了热点行的并发更新的,于是阿里内部就对MySQL做了patch。 这个方案其实云上数据库RDS也支持了,所以我就可以讲了。(没开放的技术确实不敢讲,怕被请喝茶。。。) 这个技术叫做Inventory Hint,其实就是一个补丁。(官方介绍:https://help.aliyun.com/zh/rds/apsaradb-rds-for-mysql/inventory-hint ) PS:这里主要是介绍通过Inventory Hint来提升热点更新的并发,但是并不意味着内容只用这个方案来抗热点并发,但是这个是基础,先把这个讲清楚。后续其他的方案,我也会挑一些能讲的介绍。 使用方法 他的用法很简单,只需要在正常的update语句中增加上特殊的hint语句就行了,如: 1 2 3 UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1)*/ T SET c = c - 1 WHERE id = 1; 这里面的COMMIT_ON_SUCCESS、ROLLBACK_ON_FAIL和TARGET_AFFECT_ROW都是一些Hint语法: COMMIT_ON_SUCCESS:当前语句执行成功就提交事务上下文。 ROLLBACK_ON_FAIL:当前语句执行失败就回滚事务上下文。 TARGET_AFFECT_ROW(NUMBER):如果当前语句影响行数是指定的就成功,否则语句失败。 hint:MySQL 中的 “Hint” 是一种特殊的语法,允许开发者向数据库引擎提供如何执行特定查询的额外信息或建议。这些提示不改变查询的结果,但可以影响查询的执行路径,比如如何选择索引、是否使用缓存等。使用 Hint 的目的是为了优化查询性能。 ...

March 22, 2026 · 1 min · santu

InnoDB和MyISAM有什么区别?

典型回答 InnoDB和MyISAM是MySQL中比较常用的两个执行引擎,MySQL 在 5.5 之前版本默认存储引擎是 MyISAM,5.5 之后版本默认存储引擎是 InnoDB,MyISAM适合查询以及插入为主的应用,InnoDB适合频繁修改以及涉及到安全性较高的应用。 如果应用需要高度的数据完整性和事务支持,那么InnoDB是更好的选择。所以频繁修改及数据安全性的情况适合。 如果应用主要是读取操作,或者需要高效的全文搜索功能,那么MyISAM可能更适合。所以查询频繁的适合。 他们主要有以下区别: 一、InnoDB支持事务,MyISAM不支持 二、InnoDB 是聚集索引,MyISAM 是非聚集索引。MyISAM是采用了一种索引和数据分离的存储方式,Innodb的聚簇索引中索引和数据在一起。 三、InnoDB支持外键,MyISAM不支持 四、InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。 五、InnoDB不支持FULLTEXT类型的索引(5.6之前不支持全文索引) 六、InnoDB中不保存表的行数,但是MyISAM只要简单的读出保存好的行数即可 七、对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立联合索引 **** InnoDB MyISAM 事务 支持 不支持 外键 支持 不支持 聚簇索引 支持 不支持 锁级别 支持行级锁、表级锁 表级锁 行数保存 不支持 支持 默认版本 5.5 之后 5.5 之前 全文索引 5.6以后支持 支持 ...

March 22, 2026 · 1 min · santu

有了关系型数据库,为什么还需要NOSQL?

典型回答 NOSQL数据库无需提前设计表结构,数据可以根据需要自由地存储和组织,而且相对于关系型数据库,NOSQL高效灵活,非常适合那些复杂、高变化、高并发量的场景中。 扩展知识 什么是关系型数据库,什么是非关系型数据库? 关系型数据库,是指采用了关系模型来组织数据的数据库(关系模型可以简单理解为二维表格模型),其以行和列的形式存储数据,以便于用户管理。 关系型数据库中有表的概念,表中包含了行和列,多张(或1张)表可以组成数据库。 关系型数据库具有以下几个特点: 1、传统的关系型数据库中的数据以行和列的方式进行存储。 2、关系型数据库采用结构化查询语言(即SQL)来对数据库进行查询 3、关系型数据库强调ACID规则(原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)) 4、关系型数据库十分强调数据的一致性,并为此降低读写性能付出了巨大的代价 5、关系型数据的数据通常存储在硬盘中 我们常见的MySQL、Oracle等都是关系型数据库。但是因为关系型数据库强调强一致性、以及基于硬盘存储,所以存在着一定的性能问题,相比之下,非关系型数据库在这方面就会相对有些优势。 NoSQL表示非关系型数据库,主要指那些非关系型的、分布式的,且一般不保证ACID的数据存储系统,主要代表如Redis、MongoDB等。 非关系型数据库的存储方式是基于键值来存储的,对于值的类型也有不同的支持,所以没有固定的要求和限制。 关系型数据库和非关系型数据库主要有哪些区别? 1、关系型数据库以表的形式进行存储数据,而非关系型数据库以Key-value的形式存储数据。 2、关系型数据库需要保证事务的ACID,而非关系型数据库中的事务一般无法回滚。(也有部分数据库可以回滚,如MongoDB在集群模式下) 3、关系型数据库可以通过一张表中的任意字段进行查询,非关系型数据库需要通过key进行查询 4、一般来说,关系型数据库是基于硬盘存储,非关系型数据库基于内存存储。 (Mongodb基于磁盘存储) ...

March 22, 2026 · 1 min · santu

char和varchar的区别?

典型回答 char和varchar都是用于在数据库中存储字符串的数据类型。它们之间的主要区别在于存储空间的使用方式: char是一种定长的数据类型,它的长度固定且在存储时会自动在结尾添加空格来将字符串填满指定的长度。char的长度范围是0-255, varchar是一种可变长度的数据类型,它只会存储实际的字符串内容,不会填充空格。因此,在存储短字符串时,varchar可以节省空间。varchar的长度范围是0-65535(MySQL 5.0.3之后的版本)。 如果使用char(100),则插入记录后就分配了100个字符,后续修改不会造成页分裂的问题,而varchar(100)由于没有提前分配存储空间,因为表中数据刚开始插入时,可变长度字段值都是根据实际长度存储下来的,且行与行之间数据也是紧密连续存放在文件地址中的。那么现在值变长了,原来的位置无法扩展出新的空间出来,所以无法覆盖存放到原来的位置上。此时MySQL就会使用页分裂的方法扩展字段变长的空间。 ✅什么是InnoDB的页分裂和页合并 varchar的优点是变长的字符串类型,兼容性更好;但是同时也会带来一些问题,如使用varchar可能会产生内存碎片、varchar会额外需要1到2个字节存储长度信息、以及update语句可能会导致页分裂等。 例如,存储产品描述(可变长度)、存储用户地址(可变长度)、存储用户名称(可变长度),这些都适合用varchar。 char的优点是定长的字符串类型,减少内存碎片,并且无需额外的磁盘空间去存储长度信息。但是他的缺点是会丢失列末尾的空格信息 ✅MySQL为什么会有存储碎片?有什么危害? char会在长度不足时,在后面补充空格,所以当我要在一个长度为10的char中,分别存一个"hollis "和"hollis"时,他存储的都是"hollis ",所以会丢失原来存储的空格信息。 例如,存储身份证号(固定长度)、存储订单号(固定长度)、存储国家编码(固定长度),这些都适合用char。

March 22, 2026 · 1 min · santu

MySQL 5.x和8.0有什么区别?

典型回答 性能:MySQL 8.0 的速度要比 MySQL 5.7 快 2 倍。MySQL 8.0 在以下方面带来了更好的性能:读/写工作负载、IO 密集型工作负载、以及高竞争(“hot spot"热点竞争问题)工作负载。 NoSQL:MySQL 从 5.7 版本开始提供 NoSQL 存储功能,目前在 8.0 版本中这部分功能也得到了更大的改进。该项功能消除了对独立的 NoSQL 文档数据库的需求,而 MySQL 文档存储也为 schema-less 模式的 JSON 文档提供了多文档事务支持和完整的 ACID 合规性。 窗口函数(Window Functions):从 MySQL 8.0 开始,新增了一个叫窗口函数的概念,它可以用来实现若干新的查询方式。窗口函数与 SUM()、COUNT() 这种集合函数类似,但它不会将多行查询结果合并为一行,而是将结果放回多行当中。即窗口函数不需要 GROUP BY。 隐藏索引:在 MySQL 8.0 中,索引可以被“隐藏”和“显示”。当对索引进行隐藏时,它不会被查询优化器所使用。我们可以使用这个特性用于性能调试,例如我们先隐藏一个索引,然后观察其对数据库的影响。如果数据库性能有所下降,说明这个索引是有用的,然后将其“恢复显示”即可;如果数据库性能看不出变化,说明这个索引是多余的,可以考虑删掉。 取消查询缓存:MySQL 8.0 出于性能和可维护性方面的考虑取消了查询缓存,通过使用索引、更好的查询计划优化、以及缓存结果集而不是整个查询。这些方法更有效地提高了查询性能,同时避免了查询缓存可能引入的问题。 select for update支持no wait:如果另一个事务已经锁定了一些行,当前事务将等待直到那些锁被释放。加上 NOWAIT 关键字后,如果尝试锁定的行已经被其他事务锁定,数据库将立即抛出一个错误,而不是等待。 降序索引:MySQL 8.0 为索引提供按降序方式进行排序的支持,在这种索引中的值也会按降序的方式进行排序。 通用表表达式(Common Table Expressions CTE):在复杂的查询中使用嵌入式表时,使用 CTE 使得查询语句更清晰。 UTF-8 编码:从 MySQL 8 开始,使用 utf8mb4 作为 MySQL 的默认字符集。 JSON:MySQL 8 大幅改进了对 JSON 的支持,添加了基于路径查询参数从 JSON 字段中抽取数据的 JSON_EXTRACT() 函数,以及用于将数据分别组合到 JSON 数组和对象中的 JSON_ARRAYAGG() 和 JSON_OBJECTAGG() 聚合函数。 可靠性:InnoDB 现在支持表 DDL 的原子性,也就是 InnoDB 表上的 DDL 也可以实现事务完整性,要么失败回滚,要么成功提交,不至于出现 DDL 时部分成功的问题,此外还支持 crash-safe 特性,元数据存储在单个事务数据字典中。 高可用性(High Availability):InnoDB 集群为您的数据库提供集成的原生 HA 解决方案。 安全性:对 OpenSSL 的改进、新的默认身份验证、SQL 角色、密码强度、授权。 详见: https://dev.mysql.com/blog-archive/whats-new-in-mysql-8-0-generally-available/ ...

March 22, 2026 · 1 min · santu

为什么大厂不建议使用多表join?

典型回答 之所以不建议使用join查询,最主要的原因就是join的效率比较低。 MySQL是使用了嵌套循环(Nested-Loop Join)的方式来实现关联查询的,简单点说就是要通过两层循环,用第一张表做外循环,第二张表做内循环,外循环的每一条记录跟内循环中的记录作比较,符合条件的就输出。 而具体到算法实现上主要有simple nested loop,block nested loop和index nested loop这三种。而且这三种的效率都没有特别高。 MySQL是使用了嵌套循环(Nested-Loop Join)的方式来实现关联查询的,如果有2张表join的话,复杂度最高是O(n^2),3张表则是O(n^3)…随着表越多,表中的数据量越多,JOIN的效率会呈指数级下降。 PS:MySQL 8.0中新增了 hash join算法: ✅MySQL的Hash Join是什么? 扩展知识 join 在MySQL 中,可以使用 JOIN 在两个或多个表中进行联合查询,join有三种,分别是inner join、left join 和 right join。 INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。 取两个表的交集部分 LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。 取两个表的交集部分+左表中的数据 RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。 取两个表的交集部分+右表中的数据 在配合join一起使用的还有on关键字,用来指明关联查询的一些条件。 嵌套循环算法 MySQL是使用了嵌套循环(Nested-Loop Join)的方式来实现关联查询的,具体到算法上面主要有simple nested loop join,block nested loop join和index nested loop join这三种。 而这三种的效率都没有特别高。 simple nested loop,他的做法简单粗暴,就是全量扫描连接两张表进行数据的两两对比,所以他的复杂度可以认为是N*M N是驱动表的数量,M是被驱动表的数量 index nested loop,当Inner Loop的表用到字段有索引的话,可以用到索引进行查询数据,因为索引是B+树的,复杂度可以近似认为是N*logM。 block nested loop,其实是引入了一个Buffer,会提前把外循环的一部分结果提前放到JOIN BUFFER中,然后内循环的每一行都和整个buffer的数据作比较。虽然比较次数还是N*M,但是因为join buffer是基于内存的,所以效率高很多。 所以,虽然MySQL已经尽可能的在优化了,但是这几种算法复杂度都还是挺高的,这也是为什么不建议在数据库中多表JOIN的原因。随着表越多,表中的数据量越多,JOIN的效率会呈指数级下降。 ...

March 22, 2026 · 1 min · santu

什么是数据库范式,为什么要反范式?

典型回答 所谓数据库范式,其实就是数据库的设计上的一些规范;这些规范可以让数据库的设计更加简洁、清晰;同时也会更加好的可以保证一致性。 三个常用的范式: 第一范式(1NF)是说,数据库表中的属性的原子性的,要求属性具有原子性,不可再被拆分; 比如地址如果都细化拆分成省、市、区、街道、小区等等多个字段这就是符合第一范式的, 如果地址就是一个字段,那就不符合了。 第二范式(2NF)是说,数据库表中的每个实例或记录必须可以被唯一地区分,说白了就是要有主键,其他的字段都依赖于主键。 第三范式(3NF)是说,任何非主属性不依赖于其它非主属性,也就是说,非主键外的所有字段必须互不依赖 如果我们在做表结构设计的时候,完全遵守数据库三范式,确实可以避免一些写时异常,提升一些写入性能,但是同时也会丢失一些读取性能。 因为在遵守范式的数据库设计中,表中不能有任何冗余字段,这就使得查询的时候就会经常有多表关联查询,这无疑是比较耗时的。 于是就有了反范式化。所谓反范式化,是一种针对遵从设计范式的数据库的性能优化策略。 也就是说,反范式化不等于非范式化,反范式化一定发生在满足范式设计的基础之上。前者相当于先遵守所有规则,再进行局部调整。 比如我们可以在表中增加一些冗余字段,方便我们进行数据查询,而不再需要经常做多表join,但同时,这也会带来一个问题,那就是这些冗余字段之间的一致性如何保证,这个问题本来在遵守范式的设计中是不会有的,一旦做了反范式,那就需要开发者自行解决了。 反范式其实本质上是软件开发中一个比较典型的方案,那就是"用空间换时间",通过做一些数据冗余,来提升查询速度。 在互联网业务中,比较典型的就是数据量大,并发高,并且通常查询的频率要远高于写入的频率,所以适当的做一些反范式,通过做一些字段的冗余,可以提升查询性能,降低响应时长,从而提升并发度。

March 22, 2026 · 1 min · santu

什么是数据库事务机制?

典型回答 数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。 事务由事务开始与事务结束之间执行的全部数据库操作组成。 并非任意的对数据库的操作序列都是数据库事务。事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。 持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。 扩展知识 如何理解ACID 举例说明一下,用一个常用的“A账户向B账号汇钱”的例子来说明如何通过数据库事务保证数据的准确性和完整性。熟悉关系型数据库事务的都知道从帐号A到帐号B需要6个操作: 1、从A账号中把余额读出来(500)。 2、对A账号做减法操作(500-100)。 3、把结果写回A账号中(400)。 4、从B账号中把余额读出来(500)。 5、对B账号做加法操作(500+100)。 6、把结果写回B账号中(600)。 原子性 保证1-6所有过程要么都执行,要么都不执行。一旦在执行某一步骤的过程中发生问题,就需要执行回滚操作。 假如执行到第五步的时候,B账户突然不可用(比如被注销),那么之前的所有操作都应该回滚到执行事务之前的状态。 一致性 在转账之前,A和B的账户中共有500+500=1000元钱。在转账之后,A和B的账户中共有400+600=1000元。也就是说,数据的状态在执行该事务操作之后从一个状态改变到了另外一个状态。同时一致性还能保证账户余额不会变成负数等。 隔离性 在A向B转账的整个过程中,只要事务还没有提交(commit),查询A账户和B账户的时候,两个账户里面的钱的数量都不会有变化。 如果在A给B转账的同时,有另外一个事务执行了C给B转账的操作,那么当两个事务都结束的时候,B账户里面的钱应该是A转给B的钱加上C转给B的钱再加上自己原有的钱。 持久性 一旦转账成功(事务提交),两个账户的里面的钱就会真的发生变化(会把数据写入数据库做持久化保存)! 数据库事务存在的异常读现象 什么是脏读、幻读、不可重复读?

March 22, 2026 · 1 min · santu

什么是脏读、幻读、不可重复读?

典型回答 脏读:读到了其他事务还没有提交的数据。 不可重复读:对某数据进行读取过程中,有其他事务对数据进行了修改(UPDATE、DELETE),导致第二次读取的结果不同。 幻读:事务在做范围查询过程中,有另外一个事务对范围内新增了记录(INSERT),导致范围查询的结果条数不一致。 扩展知识 什么是脏读? 脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交(commit)到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。 什么是不可重复读? 不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。 一种更易理解的说法是:在一个事务内,多次读同一个数据。在这个事务还没有结束时,另一个事务也访问该同一数据。那么,在第一个事务的两次读数据之间。由于第二个事务的修改,那么第一个事务读到的数据可能不一样,这样就发生了在一个事务内两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复。 什么是幻读? 幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样.一般解决幻读的方法是增加范围锁RangeS,锁定检锁范围为只读,这样就避免了幻读。 幻读是不可重复读的一种特殊场景:当事务没有获取范围锁的情况下执行SELECT … WHERE操作可能会发生幻读。 一句话总结脏读、不可重复读、幻读 脏读:读到了其他事务还没有提交的数据。 不可重复读:对某数据进行读取过程中,有其他事务对数据进行了修改(UPDATE、DELETE),导致第二次读取的结果不同。 幻读:事务在做范围查询过程中,有另外一个事务对范围内新增或删除了记录(INSERT、DELETE),导致范围查询的结果条数不一致。 事务隔离级别 脏读、不可重复读和幻读这三种异常情况,是在 SQL-92 标准中定义的,同时 SQL-92 标准还定义了 4 种隔离级别来解决这些异常情况,从高到底依次为:顺序执行(Serializable)、可重复读(Repeatable reads)、提交读(Read committed)、未提交读(Read uncommitted)。 ...

March 22, 2026 · 1 min · santu

留言给博主