1、数据库的三范式是什么?
数据库的三范式是数据库设计中的三个基本原则,它们用于确保数据库的结构合理、数据冗余最小化,并提高数据的一致性。这三个范式分别是:
-
第一范式(1NF):确保每个列都是不可分割的基本数据项,即表中的所有字段都应该只包含原子性的值,没有重复的组或数组。这可以确保数据表的每一行都是唯一的。
-
第二范式(2NF):在第一范式的基础上,要求表中的每一列都与主键直接相关,即表中不应存在仅与主键的一部分相关的非主属性。这可以避免部分依赖,即非主键列只依赖于主键的一部分。
-
第三范式(3NF):在第二范式的基础上,要求非主键列之间不能相互依赖,即非主键列必须直接依赖于主键,不能通过其他非主键列间接依赖。这可以避免传递依赖,即一个非主键列依赖于另一个非主键列。
遵循这些范式可以提高数据库的规范化程度,减少数据冗余,降低数据异常,提高数据的一致性和完整性。然而,过度规范化可能会导致查询性能下降,因此在实际应用中需要根据具体情况做出权衡
2、一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?
表类型如果是MyISAM,那ID就是8
表类型如果是InnoDB,那ID就是6
3、如何获取当前数据库版本?
要获取当前MySQL数据库的版本,你可以使用以下SQL查询:
SELECT VERSION();
这个查询会返回当前MySQL服务器的版本号。
如果你想要更详细的版本信息,包括版本号、编译版本、编译选项等,可以使用
SHOW VARIABLES LIKE 'version';
这将返回一个包含version
关键字的行,显示MySQL服务器的详细版本信息。
在命令行界面(CLI)中,你也可以通过以下命令获取版本信息:
mysql --version
或者,如果你已经连接到了MySQL服务器,可以使用以下命令:
SELECT @@GLOBAL.version;
这将返回全局变量version
的值,它包含了MySQL服务器的版本信息。
4、说一下 ACID 是什么?
ACID是数据库管理系统(DBMS)中用于确保事务处理的可靠性和数据完整性的四个关键属性的缩写。这四个属性分别是:
-
原子性(Atomicity):
- 事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间某个点。
- 如果事务中的某个操作失败,整个事务将被回滚,就像从未执行过一样。
-
一致性(Consistency):
- 事务必须保证数据库从一个一致的状态转移到另一个一致的状态。
- 在事务开始之前和事务结束之后,所有的数据都必须符合数据库的完整性约束和业务规则。
-
隔离性(Isolation):
- 并发执行的事务之间不会互相影响。
- 每个事务都像是在独立运行,即使多个事务并发执行,它们也应该是隔离的,以避免数据冲突。
-
持久性(Durability):
- 一旦事务被提交,它对数据库的改变就是永久性的,即使系统发生故障也不会丢失。
- 事务提交后,其结果必须被永久保存,并且在任何情况下都不会被撤销。
ACID属性是数据库事务处理的核心,它们确保了数据库操作的可靠性和数据的完整性。在设计和实现数据库系统时,开发者需要确保这些属性得到满足,以保证系统的稳定性和用户的信任。
5、char 和 varchar 的区别是什么?
CHAR
和 VARCHAR
都是MySQL数据库中用于存储字符串数据的两种不同的数据类型,它们之间有几个关键的区别:
-
固定长度与可变长度:
CHAR
是固定长度的数据类型,意味着无论存储的字符串实际长度如何,它都会占用定义时指定的固定长度的空间。VARCHAR
是可变长度的数据类型,它根据存储的字符串的实际长度动态分配空间,并且在字符串后面存储长度信息。
-
存储空间:
- 由于
CHAR
是固定长度,它在存储较短的字符串时可能会浪费更多的空间。 VARCHAR
由于是可变的,它在存储较短的字符串时可以节省空间,因为它只占用必要的长度加上一个额外的长度字节。
- 由于
-
性能:
CHAR
因为其固定长度的特性,处理起来通常比VARCHAR
更快,尤其是在索引操作中,因为其长度固定,易于优化。VARCHAR
由于需要存储额外的长度信息,并且在插入和更新时可能需要重新计算长度,因此在某些情况下可能会比CHAR
慢。
-
默认值:
- 如果没有指定值,
CHAR
类型的列会被填充空格以达到其固定长度。 VARCHAR
类型的列如果没有指定值,则默认为空字符串。
- 如果没有指定值,
-
最大长度:
- 在MySQL中,
CHAR
和VARCHAR
都可以定义最大长度,但VARCHAR
的最大长度可以更长(最大长度为 65,535 字节)。
- 在MySQL中,
-
使用场景:
- 当你知道存储的字符串长度不会变化,或者长度变化不大时,使用
CHAR
可能更合适。 - 当字符串长度可能会有较大变化,或者你想要节省空间时,使用
VARCHAR
更合适。
- 当你知道存储的字符串长度不会变化,或者长度变化不大时,使用
选择 CHAR
还是 VARCHAR
取决于具体的应用场景和性能需求。通常情况下,如果字符串长度变化不大,为了性能考虑,推荐使用 CHAR
;如果字符串长度变化较大,为了节省空间,推荐使用 VARCHAR
。
6、float 和 double 的区别是什么?
- float 最多可以存储 8 位的十进制数,并在内存中占 4 字节。
- double 最可可以存储 16 位的十进制数,并在内存中占 8 字节。
7、mysql 的内连接、左连接、右连接有什么区别?
MySQL中的内连接(INNER JOIN)、左连接(LEFT JOIN)、右连接(RIGHT JOIN)是不同类型的连接操作,用于根据两个表之间的关联条件合并行。它们的主要区别如下:
-
内连接(INNER JOIN):
- 内连接只返回两个表中连接条件相匹配的行。
- 如果某个表中的行在另一个表中没有匹配的行,那么这些行将不会被包含在结果集中。
-
左连接(LEFT JOIN):
- 左连接返回左表(即指定的第一个表)的所有行,即使右表(第二个表)中没有匹配的行。
- 如果右表中没有匹配的行,结果集中右表的部分将为 NULL。
-
右连接(RIGHT JOIN):
- 右连接返回右表的所有行,即使左表中没有匹配的行。
- 如果左表中没有匹配的行,结果集中左表的部分将为 NULL。
这些连接操作通常在 SELECT
语句中使用,通过 ON
子句来指定连接条件。例如:
-- 内连接
SELECT *
FROM table1
INNER JOIN table2
ON table1.column_name = table2.column_name;-- 左连接
SELECT *
FROM table1
LEFT JOIN table2
ON table1.column_name = table2.column_name;-- 右连接
SELECT *
FROM table1
RIGHT JOIN table2
ON table1.column_name = table2.column_name;
注意:在MySQL中,RIGHT JOIN
并不常用,因为可以通过 LEFT JOIN ... ORDER BY
的方式来实现相同的结果。此外,RIGHT JOIN
在某些数据库系统中可能不被支持或有不同的行为。
在实际应用中,选择哪种类型的连接取决于你希望从查询中获取的数据。如果你需要保留所有左侧表的记录,即使右侧表中没有匹配的记录,那么使用 LEFT JOIN
是合适的。反之,如果你需要保留所有右侧表的记录,即使左侧表中没有匹配的记录,那么使用 RIGHT JOIN
是合适的。如果你只对两个表中都有匹配的记录感兴趣,那么使用 INNER JOIN
是合适的。
8、mysql 索引是怎么实现的?
索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。
目前主流的数据库引擎的索引都是 B+ 树实现的,B+ 树的搜索效率,可以到达二分法的性能,找到数据区域之后就找到了完整的数据结构了,所有索引的性能也是更好的。
9、怎么验证 mysql 的索引是否满足需求?
explain select * from table where column=''
使用 explain 查看 SQL 是如何执行查询语句的,从而分析你的索引是否满足需求。
10、说一下数据库的事务隔离?
MySQL数据库支持多种事务隔离级别,这些隔离级别用于解决并发事务中的一些问题,如脏读、不可重复读和幻读。MySQL的事务隔离级别包括:
-
读未提交(Read Uncommitted):
- 在这个隔离级别,事务可以读取到其他未提交事务的更改。这意味着一个事务可以读到另一个事务未提交的数据,可能会导致脏读。
-
读已提交(Read Committed):
- 事务只能读取到其他事务已经提交的更改。这个级别可以避免脏读,但仍然可能遇到不可重复读的问题,即在同一事务中,多次读取同一数据集合时可能会得到不同的结果。
-
可重复读(Repeatable Read):
- 这是MySQL的默认事务隔离级别。在这个级别,事务在整个过程中可以重复读取到相同的数据。它解决了不可重复读的问题,但仍然可能遇到幻读,即一个事务在读取某个范围内的记录时,另一个事务插入了新的记录,导致第一个事务再次读取该范围时结果不一致。
-
串行化(Serializable):
- 这是最高的隔离级别,它通过锁定涉及的所有数据来避免脏读、不可重复读和幻读。在这个级别,事务会依次顺序执行,从而提供了最严格的隔离。这可以避免并发问题,但可能导致性能显著下降。
MySQL通过InnoDB
存储引擎支持事务处理,并且可以通过设置transaction_isolation
系统变量来改变事务隔离级别。可以通过以下命令查看当前的事务隔离级别:
SHOW VARIABLES LIKE 'transaction_isolation';
或者,要查看特定会话的隔离级别:
SELECT @@transaction_isolation;
要设置事务隔离级别,可以使用以下命令:
SET SESSION TRANSACTION ISOLATION LEVEL [隔离级别];
其中[隔离级别]
可以是READ UNCOMMITTED
、READ COMMITTED
、REPEATABLE READ
或SERIALIZABLE
之一。
选择合适的事务隔离级别是一个平衡性能和数据一致性的决策。较低的隔离级别可能会提高并发性能,但同时增加了数据不一致的风险。较高的隔离级别可以提供更强的数据一致性保证,但可能会降低并发性能。
11、说一下 mysql 的行锁和表锁?
MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。
- 表级锁:开销小,加锁快,不会出现死锁。
锁力度大,发生锁冲突的概率高,并发量最低。 - 行级锁:开销大,加锁慢,会出现死锁。
锁力度小,发生锁冲突的概率小,并发度最高。
12、mysql 问题排查都有哪些手段?
- 使用 show processlist 命令查看当前所有连接信息。
- 使用 explain 命令查询 SQL 语句执行计划。
- 开启慢查询日志,查看慢查询的 SQL。
13、如何做 mysql 的性能优化?
MySQL性能优化是一个涉及多个方面的复杂过程,以下是一些常见的优化策略:
-
优化查询:
- 重写查询语句,减少不必要的列和表的访问。
- 使用合适的WHERE子句来减少返回的数据量。
- 避免使用SELECT *,尽量指定需要的列。
-
使用索引:
- 为经常作为查询条件的列创建索引。
- 考虑使用复合索引,特别是当多个列一起用于查询条件时。
- 定期检查索引的效率,并删除不必要的索引。
-
优化数据表结构:
- 使用合适的数据类型,避免冗余。
- 考虑使用分区表来处理大型表。
- 避免使用过多的JOIN操作,特别是在大数据集上。
-
调整MySQL配置:
- 根据服务器的硬件配置调整
my.cnf
或my.ini
中的参数,如innodb_buffer_pool_size
、max_connections
等。 - 启用查询缓存(如果适用)。
- 根据服务器的硬件配置调整
-
使用合适的存储引擎:
- 根据应用需求选择合适的存储引擎,如
InnoDB
、MyISAM
等。 InnoDB
支持事务处理和行级锁定,通常更适合需要高并发和数据一致性的应用。
- 根据应用需求选择合适的存储引擎,如
-
监控和分析:
- 使用
SHOW PROCESSLIST
查看当前运行的进程。 - 使用
EXPLAIN
分析查询的执行计划。 - 监控慢查询日志,找出并优化慢查询。
- 使用
-
硬件升级:
- 升级服务器的CPU、内存或磁盘,以提高性能。
- 使用更快的硬盘,如SSD,来减少I/O等待时间。
-
优化服务器操作系统:
- 调整操作系统的网络和文件系统设置。
- 确保操作系统的内核版本和驱动程序是最新的。
-
使用缓存机制:
- 实现应用层的缓存,减少对数据库的直接访问。
- 使用MySQL内置的缓存,如表缓存和查询缓存。
-
数据库维护:
- 定期进行数据库维护,如优化表(
OPTIMIZE TABLE
)。 - 清理无用的数据,避免表膨胀。
- 定期进行数据库维护,如优化表(
-
并发控制:
- 优化事务的大小和持续时间,减少锁的竞争。
- 使用合适的隔离级别,平衡性能和数据一致性。
-
读写分离:
- 在多用户环境中,实现读写分离,将查询和更新操作分散到不同的服务器。
-
使用性能分析工具:
- 使用如MySQL Enterprise Monitor、Percona Toolkit等工具进行性能分析和调优。
性能优化是一个持续的过程,需要根据实际的应用场景和工作负载来不断调整和优化。在进行性能优化时,建议先对当前系统的性能进行基准测试,然后根据测试结果和监控数据来制定优化策略。
14、什么是数据库分区?
根据一定逻辑规则,将一个表拆成多个更小更容易管理的部分。
其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。
查看是否支持分区命令:
- 5.6以下的版本:show variables like '%partition%';
- 5.6以上的版本:show plugins; 当看到有partition并且status是active时表示支持。
15、为什么要分区?
- 分区可以在一个表中存储比单个磁盘或文件系统分区上的数据更多的数据,因为我们可以将分区表存储在不同物理磁盘上
- 对已过期或者不需要保存的数据,可以通过删除与这些数据有关的分区来快速删除数据,他的效率远比delete高;
- 优化查询,在where子句中包含分区条件时,可以只扫描必要的一个或者多个分区来提高查询效率;例如:SELECT * FROM t PARTITION(p0,p1)WHERE c <5 仅选择与WHERE条件匹配的分区p0和p1中的那些行。在这种情况下,MySQL不检查表t的任何其他分区;
- 凭借在多个磁盘上传播数据,实现更高的查询吞吐量。
注:一个表最多只能有1024个分区,同一个分区表的所有分区必须使用相同的存储引擎
16、怎样分区?
- RANGE分区:基于一个给定连续区间范围,把数据分配到不同的分区;
- LIST分区:类似RANGE分区,区别在LIST分区是基于枚举出的值列表分区,RANGE是基于给定连续区间范围分区;
- HASH分区:基于用户定义的表达式返回值来选择分区,该表达式对要插入到表的行中列值操作;
- KEY分区:类似HASH,但是HASH允许使用用户自定义表达式,而KEY分区不允许,它需要使用MySQL服务器提供的HASH函数,同时HASH分区只支持整数分区,而KEY分区支持除BLOB和TEXT类型外其他列