大佬教程收集整理的这篇文章主要介绍了2万字☀️MySQL数据库面试36题(看完吊打面试官),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
重点部分用🚩标注
常用的存储引擎有以下:
@H_103_132@myISAM | Innodb | |
---|---|---|
存储结构 | 每张表被存放在三个文件:frm 表格定义、@H_939_145@mYD(MYData)数据文件、@H_939_145@mYI(MYIndeX)-索引文件 | 所有的表都保存在同一个数据文件中.ibd frm 表格定义、(也可能是多个文件c;或者是独立的表空间文件)c;InnoDB表的大小只受限于操作系统文件的大小c;一般为2GB |
存储空间 | @H_1_142@myISAM可被压缩c;存储空间较小InnoDB的表需要更多的内存和存储c;它会在主@H_450_113@内存中建立其专用的@H_450_113@缓冲池用于高速缓冲@H_450_113@数据和索引 | |
可移植性、备份及恢复 | 由于MyISAM的数据是以@H_450_113@文件的形式存储c;所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作 | 免费的方案可以是拷贝数据文件、@H_450_113@备份 binlogc;或者用 mysqldumpc;在数据量达到几十G的时候就相对痛苦了 |
文件格式 | 数据和索引是分别存储的c;数据.MYD c;索引.MYI | 数据和索引是集中存储的c;.ibd |
记录存储顺序 | 按记录插入顺序保存 | 按主键大小有序插入 |
外键 | 不支持 | 支持 |
事务 | 不支持 | 支持 |
锁支持(锁是避免资源争用的一个机制c;R_270_11845@ySQL锁对用户几乎是透明的) | 表级锁定 | 行级锁定、表级锁定c;锁定力度小并发能力高 |
SELECT | @H_1_142@myISAM更优||
INSERT、updatE、deletE | InnoDB更优 | |
SELEct count(*) | @H_1_142@myisam更快c;因为myisam@H_450_113@内部维护了一个计数器c;可以直接调取。||
索引的实现方式 | B+树索引c;R_270_11845@yisam 是堆表 | B+树索引c;Innodb 是索引组织表 |
哈希索引 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
总结
索引是@H_450_113@一种数据结构。数据库索引c;是对某一列或多个列的值进行@H_450_113@预排序的数据结构。通过使用索引c;可以让数据库系统不必扫描整个表c;而是直接定位到符合条件的记录c;这样就大大加快了查询速度。
更通俗的说c;索引就相当于@H_450_113@目录。为了方便查找书中的内容c;通过对内容@R_801_10399@形成目录。索引是一个文件c;它是要占据物理空间的。
索引用来快速地寻找那些具有特定值的记录。如果没有索引c;一般来说执行查询时遍历整张表。
索引的原理很简单c;就是把无序的数据变成有序的查询
优点:
缺点:
索引算法有 @H_450_113@BTree算法和Hash算法
熟悉数据结构的同学都知道c;@H_450_113@B+树、平衡二叉树、红黑树都是经典的数据结构。在B+树中c;所有的记录节点都是按照键值大小的顺序放在叶子节点上c;如下图。
B+树的索引又可以分为主索引和辅助索引。其中主索引为聚簇索引c;辅助索引为非聚簇索引。聚簇索引是以主键作为B+ 树索引的键值所构成的B+树索引c;聚簇索引的叶子节点存储着完整的数据记录;非聚簇索引是以非主键的列作为B+树索引的键值所构成的B+树索引c;非聚簇索引的叶子节点存储着主键值。所以使用非聚簇索引进行查询时c;会先找到主键值c;然后到根据聚簇索引找到主键对应的数据域。上图中叶子节点存储的是数据记录c;为聚簇索引的结构图c;非聚簇索引的结构图如下:
哈希索引是基于哈希表实现的c;对于每一行数据c;存储引擎会对索引列通过哈希算法进行哈希计算得到哈希码c;并且哈希算法要尽量保证不同的列值计算出的哈希码值是不同的c;将哈希码的值作为哈希表的key值c;将指向数据行的指针作为哈希表的value值。这样查找一个数据的时间复杂度就是o(1)c;一般多用于精确查找。
hash索引底层就是@H_450_113@hash表c;进行查找时c;调用一次hash函数就可以获取到相应的键值c;之后进行回表查询获得实际数据。
B+树底层实现是@H_450_113@多路平衡查找树。对于每一次的查询都是从根节点出发c;查找到叶子节点方可以获得所查键值c;然后根据查询判断是否需要回表查询数据。
因为两者数据结构上的差异导致它们的使用场景也不同c;哈希索引一般多用于@H_450_113@精确的等值查找c;B+索引则多用于除了精确的等值查找外的其他查找。在大多数情况下c;会选择使用B+树索引。
B树和B+树最主要的区别主要有两点:
B+树的@H_450_113@内部节点@H_450_113@只有键没有值c;@H_450_113@叶子节点存放所有的键和值。
B+树的@H_450_113@叶子节点是通过相连在一起的c;方便顺序检索。
两者的结构图如下。
那在什么情况适合使用B树呢c;因为B树的内部节点也可以存储值c;所以可以把一些频繁访问的值放在距离根节点比较近的地方c;这样就可以提高查询效率。综上所述c;B+树的性能更加适合作为数据库的索引。
索引虽好c;但也不是无限制的使用c;最好符合一下几个原则
1) @H_450_113@最左前缀匹配原则c;组合索引非常重要的原则c;R_270_11845@ysql会一直向右匹配直到遇到范围查询(>、<、@R_675_7000@n、likE)就停止匹配c;比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引c;d是用不到索引的c;如果建立(a,b,d,C)的索引则都可以用到c;a,b,d的顺序可以任意调整。(下面有详细说明)
2)较频繁作为查询条件的字段才去创建索引
3)更@H_450_113@新频繁字段不适合创建索引
4)若是@H_450_113@不能有效区分数据的列不适合做索引列(如性别c;男女未知c;最多也就三种c;区分度实在太低)
5)@H_450_113@尽量的扩展索引c;不要新建索引。比如表中已经有a的索引c;现在要加(a,b)的索引c;那么只需要修改原来的索引即可。
6)定义有外键的数据列一定要@R_801_10399@。
7)对于那些查询中很少涉及的列c;重复值比较多的列不要@R_801_10399@。
8)对于定义为text、image和bit的数据类型的列不要@R_801_10399@。
最左匹配原则:从最左边为起点开始连续匹配c;遇到@H_450_113@范围查询(<、>、@R_675_7000@n、like)会停止匹配。
例如@R_801_10399@(a,b,C)c;大家可以猜测以下几种情况是否用到了索引。
第一种
SELEct * from table_name where a = 1 and b = 2 and c = 3
SELEct * from table_name where b = 2 and a = 1 and c = 3
上面两次查询过程中所有值都用到了索引c;where后面字段调换不会影响查询结果c;因为MySQL中的优化器会自动优化查询顺序。
第二种
SELEct * from table_name where a = 1
SELEct * from table_name where a = 1 and b = 2
SELEct * from table_name where a = 1 and b = 2 and c = 3
答案是三个查询语句都用到了索引c;因为三个语句都是从最左开始匹配的。
第三种
SELEct * from table_name where b = 1
SELEct * from table_name where b = 1 and c = 2
答案是这两个查询语句都没有用到索引c;因为不是从最左边开始匹配的
第四种
SELEct * from table_name where a = 1 and c = 2
第五种
SELEct * from table_name where a = 1 and b < 3 and c < 1
第六种
SELEct * from table_name where a like 'ab%';
SELEct * from table_name where a like '%ab'
SELEct * from table_name where a like '%ab%'
聚簇索引和非聚簇索引最主要的区别是@H_450_113@数据和索引是否分开存储。
在InnoDB存储引擎中c;默认的索引为B+树索引c;利用主键创建的索引为主索引c;也是聚簇索引c;在主索引之上创建的索引为辅助索引c;也是非聚簇索引。为什么说辅助索引是在主索引之上创建的呢c;因为辅助索引中的叶子节点存储的是主键。
在MyISAM存储引擎中c;默认的索引也是B+树索引c;但主索引和辅助索引都是非聚簇索引c;也就是说索引结构的叶子节点存储的都是一个指向数据行的地址。并且使用辅助索引检索无需访问主键的索引。
可以从非常经典的两张图看看它们的区别(图片来源于网络):
第一范式(1NF):字段不可分; 第二范式(2NF):有主键c;非主键字段依赖主键; 第三范式(3NF):非主键字段不能相互依赖。
1NF:原子性。 字段不可再分,否则就不是关系数据库;; 2NF:唯一性 。一个表只说明一个事物; 3NF:每列都与主键有直接关系c;不存在传递依赖。
在上面介绍了几种不符合最左匹配原则的情况会导致索引失效c;除此之外c;以下这几种情况也会导致索引失效。
SELEct * FROM table_name where a = 1 or b = 3
SELEct * FROM table_name where a + 1 = 2
SELEct * FROM table_name where a = '1'
会使用到索引c;如果写成SELEct * FROM table_name where a = 1
则会导致索引失效。SELEct * FROM table_name where abs(a) = 1
SELEct * FROM table_name where a != 1
SELEct * FROM table_name where a is null
数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列c;这些操作要么全部执行,要么全部不执行c;是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
不可重复度和幻读看起来比较像c;它们主要的区别是:
在幻读中c;发现数据不一致主要是数据增多或者减少了。
数据库的隔离级别分别可以解决数据库的脏读、不可重复读、幻读等问题。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
未提交读 | 允许 | 允许 | 允许 |
提交读 | 不允许 | 允许 | 允许 |
可重复读 | 不允许 | 不允许 | 允许 |
串行化 | 不允许 | 不允许 | 不允许 |
事务的隔离机制主要是依靠锁机制和MVCC(多版本并发控制)实现的c;
@H_450_113@提交读和可重复读可以通过MVCC实现c;串行化可以通过锁机制实现。
在了解MVCC时应该先了解当前读和快照读。
可以看到MVCC的作用就是在@H_450_113@不加锁的情况下【快照读】c;解决数据库@H_450_113@读写冲突问题c;并且解决@H_450_113@脏读、幻读、不可重复读等问题c;但是不能解决丢失修改问题。
@H_623_5@mVCC的实现原理:版本号
系统版本号:是一个自增的IDc;@H_450_113@每开启一个事务c;系统版本号都会递增。
事务版本号:事务版本号就是@H_450_113@事务开始时的系统版本号c;可以通过事务版本号的大小判断事务的时间顺序。
@H_450_113@行记录隐藏的列
DB_ROW_ID
:所需空间6bytec;隐含的自增的@H_450_113@行IDc;用来生成聚簇索引c;如果数据表没有指定聚簇索引c;InnoDB会利用这个隐藏ID创建聚簇索引。
DB_TRX_ID
:所需空间6bytec;最近修改的@H_450_113@事务IDc;记录创建这条记录或最后一次修改这条记录的事务ID。
undo日志
@H_623_5@mVCC做使用到的快照会存储在Undo日志中c;该日志通过回滚指针将一个一个数据行的所有快照连接起来。它们大致长这样。从上面的分析可以看出c;事务对同一记录的修改c;记录的各个会在Undo日志中连接成一个线性表c;@H_450_113@在表头的就是最新的旧纪录。
SELECT
作为查询的结果要满足两个条件:
INSERT
将当前系统版本号作为数据行@H_450_113@快照的创建版本号。
将当前系统版本号作为数据行@H_450_113@快照的删除版本号。
保存当前系统版本号为更新前的数据行快照创建行版本号c;并保存当前系统版本号为更新后的数据行快照的删除版本号c;@H_450_113@其实就是c;先删除再插入即为更新。
总结一下c;R_270_11845@VCC的作用就是在避免加锁的情况下@H_450_113@最大限度解决读写并发冲突的问题c;它可以实现@H_450_113@提交读和可重复度两个隔离级。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
未提交读 | 允许 | 允许 | 允许 |
提交读 | 不允许 | 允许 | 允许 |
可重复读 | 不允许 | 不允许 | 允许 |
串行化 | 不允许 | 不允许 | 不允许 |
在MySQL数据库中有如下六种触发器:
数据查询语言DQL(Data Query Language)
SELECT
数据操纵语言DML(Data Manipulation Language)
INSERTc;updatEc;delet
主要为以上操作 即对数据进行操作的c;对应上面所说的查询操作 DQL与DML共同构建了多数初级程序员常用的增删改查操作。而查询是较为特殊的一种 被划分到DQL中。
超键:在关系中能@H_450_113@唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键c;多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。
主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。
外键:@H_450_113@在一个表中存在的另一个表的主键称此表的外键。
full join 一定需要 on 条件的匹配c;一条匹配全部输出
cross join 是笛卡尔积c;没有匹配都能输出
详情见 : https://hiszm.blog.csdn.net/article/details/119736109
type 表示 MySQL 决定如何查找表中的行c;从@H_450_113@最差到最优有如下几种取值:
流程描述:
@H_874_1472@
NOT NULL
: 用于控制字段的内容一定不能为空(NULL)。UNIQUE
: 控件字段内容不能重复c;一个表允许有多个 Unique 约束。PRIMary KEY
: 也是用于控件字段内容不能重复c;但它在一个表只允许出现一个。FOREIGN KEY
: 用于预防破坏表之间连接的动作c;也能防止非法数据插入外键列c;因为它必须是它指向的那个表中的值之一。checK
: 用于控制字段的值范围。三者都表示删除c;但是三者有一些差别:
delete | Truncate | Drop | |
---|---|---|---|
类型 | 属于DML | 属于DDL | 属于DDL |
回滚 | 可回滚 | 不可回滚 | 不可回滚 |
删除内容 | @H_450_113@表结构还在c;删除表的全部或者一@H_450_113@部分数据行 | @H_450_113@表结构还在c;删除表中的@H_450_113@所有数据 | 从数据库中删除表c;@H_450_113@所有的数据行c;索引和权限也会被删除 |
删除速度 | 删除速度慢c;需要@H_450_113@逐行删除 | 删除速度快 | 删除速度最快 |
总结
在不再需要一张表的时候c;用drop;
在保留表而删除所有数据的时候用truncate。
当数据库有并发事务的时候c;保证数据访问顺序的机制称为锁机制。
隔离级别 | 实现方式 |
---|---|
未提交读 | 总是读取最新的数据c;无需加锁 |
提交读 | 读取数据时加共享锁c;读取数据后释放共享锁 |
可重复读 | 读取数据时加共享锁c;事务结束后释放共享锁 |
串行化 | 锁定整个范围的键c;一直持有锁直到事务结束 |
按照锁的@H_450_113@粒度可以将MySQL锁分为三种:
资源开销 | 加锁速度 | 是否会出现死锁 | 锁的粒度 | 并发度 | |
---|---|---|---|---|---|
表级锁 | 小 | 快 | 不会 | 大 | 低 |
行级锁 | 大 | 慢 | 会 | 小 | 高 |
页面锁 | 一般 | 一般 | 不会 | 一般 | 一般 |
从锁的@H_450_113@类别上区别可以分为共享锁和排他锁
乐观锁:系统假设数据的更新在大多数时候是不会产生冲突的c;所以数据库@H_450_113@只在更新操作提交的时候对数据检测冲突c;如果存在冲突c;则数据更新失败。
乐观锁实现方式:一般通过@H_450_113@版本号和CAS算法实现。
悲观锁:假定会发生并发冲突c;屏蔽一切可能违反数据完整性的操作。通俗讲就是每次去拿数据的时候都认为别人会修改c;所以每次在拿数据的时候都会@H_450_113@上锁。
悲观锁的实现方式:通过数据库的@H_450_113@锁机制实现c;对查询语句添加for updata。
SELEct * from table where id=1 for update
CASc;即 Compare And Swap(比较与交换)c;是一种无锁算法c;基于硬件原语实现c;能够在不使用锁的情况下实现多线程之间的变量同步。jdk中的java.util.concurrent.atomic包中的原子类就是通过CAS来实现了乐观锁。
@H_450_113@CAS算法过程(🚩)
算法涉及到三个操作数:
CAS算法解析:
CAS具体执行时c;当且仅当预期值A符合内存地址V中存储的值时c;就用新值U替换掉旧值c;并写入到内存地址V中。否则不做更新。
CAS算法的运行原理如下如所示:
@H_450_113@CAS会有如下三个方面的问题:
1.ABA问题c;一个线程将内存值从A改为Bc;另一个线程又从B改回到A。
2.循环时间长开销大:CAS算法需要不断地自旋来读取最新的内存值c;长时间读取不到就会造成不必要的CPU开销。
3.只能保证一个共享变量的原子操作(jdk的AtomicReference来保证应用对象之间的原子性c;可以把多个变量放在一个对象里来进行CAS操作c;解决了这一问题)。
ABA问题图解:
ABA问题解决方案:在变量前面添加版本号c;每次变量更新的时候都将版本号加1c;比如juc的原子包中的AtomicStampedReference类。
死锁是@H_450_113@指两个或者两个以上进程在执行过程中c;由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。
@H_450_113@在MySQL中c;R_270_11845@yISAM是一次获得所需的全部锁c;要么全部满足c;要么等待c;所以不会出现死锁。
如何避免MySQL发生死锁或锁冲突:
drop | delete | truncate | |
---|---|---|---|
速度 | 快 | 逐行删除c;慢 | 较快 |
类型 | DDL | DML | DDL |
回滚 | 不可回滚 | 可回滚 | 不可回滚 |
删除内容 | 删除整个表c;数据行、索引都会被删除 | 表结构还在c;删除表的一部分或全部数据 | 表结构还在c;删除表的全部数据 |
一般来讲c;删除整个表c;使用dropc;删除表的部分数据使用deletec;保留表结构删除表的全部数据使用truncate。
union和union all的作用都是将两个结果集合并到一起。
慢查询一般用于记录执行时间超过某个临界值的sql语句的日志。
@H_450_113@相关参数:
slow_query_log
:是否开启慢日志查询c;1表示开启c;0表示关闭。slow_query_log_file
:MySQL数据库慢查询日志存储路径。long_query_time
:慢查询阈值c;当sql语句查询时间大于阈值c;会被记录在日志上。log_queries_not_using_indexes
:未使用索引的查询会被记录到慢查询日志中。log_output
:日志存储方式。“FILE”表示将日志存入文件。“TABLE”表示将日志存入数据库。@H_450_113@方法:
配置项:
slow_query_log
可以使用
show variables like ‘slov_query_log’
查看是否开启c;果状态值为
OFF
c;可以使用set GLOBAL slow_query_log = on
来开启c;它会在
datadir
下产生一个xxx-slow.log
的文件。
配置项:
long_query_time
查看:
show VARIABLES like 'long_query_time'
c;单位秒设置:
set long_query_time=0.5
实操时应该从长时间设置到短的时间c;即将最慢的SQL优化掉
一旦SQL超过了我们设置的临界时间就会被记录到xxx-slow.log
中
慢查询的优化首先要搞明白慢的原因是什么?是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大?
所以优化也是针对这三个方向来的c;
LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。
LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。
如果给定两个参数c;
第一个参数指定第一个返回记录行的偏移量c;
第二个参数指定返回记录行的最大数目。
初始记录行的偏移量是 0(而不是 1)
@H_939_145@mysql> SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15 mysql> SELECT * FROM table LIMIT 5; //检索前 5 个记录行 //换句话说c;LIMIT n 等价于 LIMIT 0,n。
使用自增ID的好处:
使用自增ID的缺点:
UUID
:(Universally Unique Identifier)通用唯一标识码c;UUID是基于当前时间、计数器和硬件标识等数据计算生成的。
使用UUID的优点:
使用UUID的缺点:
最后说下结论c;一般情况MySQL推荐使用自增ID。因为在MySQL的InnoDB存储引擎中c;主键索引是一种聚簇索引c;主键索引的B+树的叶子节点按照顺序存储了主键值及数据c;如果主键索引是自增IDc;只需要按顺序往后排列即可c;如果是UUIDc;ID是随机生成的c;在数据插入时会造成大量的数据移动c;产生大量的内存碎片c;造成插入性能的下降。
从减少数据访问方面考虑:
从返回更少的数据方面考虑:
从减少服务器CPU开销方面考虑:
从增加资源方面考虑:
from -> on -> join -> where -> group by -> having -> SELEct -> disTinct -> order by
主从复制主要有三个线程:binlog线程c;I/O线程c;SQL线程。
主从复制的作用:
读写分离主要依赖于主从复制c;主从复制为读写分离服务。
读写分离的优势:
@H_450_113@读写分离是依赖于主从复制c;而主从复制又是为读写分离服务的。
因为主从复制要求slave
不能写只能读
如果对
slave
执行写操作c;那么show slave status
将会呈现Slave_SQL_Running=NO
c;此时你需要按照前面提到的手动同步一下slave
。
@H_450_113@方案一
使用@H_939_145@mysql-proxy代理
优点:直接实现读写分离和负载均衡c;不用修改代码c;Master和Slave用一样的帐号c;R_270_11845@ysql官方不建议实际生产中使用
@H_450_113@方案二
使用AbstractRoutIngDatasource
+aop
+Annotation
在dao
层决定数据源。 如果采用了@H_939_145@mybatisc; 可以将读写分离放在ORM
层c;比如@H_939_145@mybatis可以通过@H_939_145@mybatis plugin拦截sql语句c;所有的insert/update/delete
都访问@H_939_145@master库c;所有的SELEct
都访问salve库c;这样对于dao层都是透明。plugin
实现时可以通过注解或者分析语句是读写方法来选定主从库。不过这样依然有一个问题c; 也就是不支持事务c; 所以我们还需要重写一下DatasourcetransactionManager
c; 将read-only
的事务扔进读库c; 其余的有读有写的扔进写库。
@H_450_113@方案三
使用AbstractRoutIngDatasource
+aop
+Annotation
在service
层决定数据源c;可以支持事务.
缺点:类内部方法通过this.xx()
方式相互调用时c;aop
不会进行拦截c;需进行特殊处理。
@H_450_113@目的
我们都知道在
sql
中有一类函数叫做聚合函数,例如sum()
、avg()
、@H_939_145@max()等等, 这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚 集前的行数的。但是有时我们想要既显示聚集前的数据,又要显示聚集后的数据,
这时我们便引入了窗口函数。
开窗函数可以为每组返回多个值c;因为开窗函数所执行聚合计算的行集组是窗口。
@H_450_113@应用
GROUP BY
TOP N
@H_450_113@格式
over(partition by col1 order by col2 rows @R_675_7000@n col3)
开窗函数=分析函数+Over();
row_number() over(partition by … order by …)
rank() over(partition by … order by …)
dense_rank() over(partition by … order by …)
count() over(partition by … order by …)
@H_593_2588@max() over(partition by … order by …)
@H_593_2588@min() over(partition by … order by …)
sum() over(partition by … order by …)
avg() over(partition by … order by …)
first_value() over(partition by … order by …)
last_value() over(partition by … order by …)
lag() over(partition by … order by …)
lead() over(partition by … order by …)
开窗函数详细见:https://hiszm.blog.csdn.net/article/details/119824742
引用
https://hiszm.cn
https://hiszm.blog.csdn.net/article/details/119540143
https://mp.weixin.qq.com/s/REzOiTTNKstR1JHlu3thzQ
https://blog.csdn.net/jankin6/category_11191625.html
https://mp.weixin.qq.com/s_biz=MzU3MzgwNTU2Mg==&mid=2247487449&idx=1&sn=2cc97bf6669416267c25a7a46192b706&scene=21#wechat_redirect
以上是大佬教程为你收集整理的2万字☀️MySQL数据库面试36题(看完吊打面试官)全部内容,希望文章能够帮你解决2万字☀️MySQL数据库面试36题(看完吊打面试官)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。