MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

MySQL数据库基础概念解析

2022-04-291.7k 阅读

数据库基础概念

数据库与数据库管理系统

在深入了解 MySQL 之前,先明确数据库(Database)和数据库管理系统(Database Management System,DBMS)的概念。数据库是按照数据结构来组织、存储和管理数据的仓库,它就像是一个大型的文件柜,将各种数据有条理地存放其中。而数据库管理系统则是用于管理数据库的软件系统,它负责维护数据库的结构,提供数据的存储、检索、更新和删除等操作的功能。MySQL 就是一种流行的关系型数据库管理系统,它能够有效地管理大量数据,并支持多用户同时访问。

数据模型

数据模型是对现实世界数据特征的抽象,它描述了数据之间的关系以及数据的操作方式。常见的数据模型有层次模型、网状模型和关系模型。MySQL 采用的是关系模型,这种模型以二维表的形式组织数据,每个表由行(记录)和列(字段)组成。例如,一个学生信息表可能包含学号、姓名、年龄等字段,每一行代表一个具体学生的信息。关系模型具有结构简单、易于理解和操作的优点,使得数据的存储和查询变得更加直观。

数据库架构

MySQL 的架构可以分为多个层次。最上层是连接层,负责处理客户端与服务器之间的连接,验证用户身份等操作。例如,使用以下命令连接 MySQL 服务器:

mysql -u root -p

这里 -u 表示用户名,-p 表示提示输入密码。连接成功后,就进入了服务器层。服务器层包含查询解析器、优化器和执行器等组件。查询解析器负责将用户输入的 SQL 语句解析成内部数据结构,优化器则对查询进行优化,找出最优的执行计划,执行器根据执行计划来实际执行查询并返回结果。再下层是存储引擎层,MySQL 支持多种存储引擎,如 InnoDB、MyISAM 等,不同的存储引擎具有不同的特点和适用场景,例如 InnoDB 支持事务处理,适合对数据完整性要求较高的应用场景;而 MyISAM 则在读取性能上表现出色,适合以读为主的应用。

MySQL 数据类型

数值类型

  1. 整数类型:MySQL 提供了多种整数类型,如 TINYINTSMALLINTMEDIUMINTINT(或 INTEGER)和 BIGINT。它们的区别主要在于存储范围和占用空间。例如,TINYINT 占用 1 个字节,范围是 -128 到 127(有符号)或 0 到 255(无符号);INT 占用 4 个字节,范围更大。创建表时可以这样定义整数类型的字段:
CREATE TABLE numbers (
    id INT,
    small_num TINYINT
);
  1. 浮点数类型FLOATDOUBLE 用于存储浮点数。FLOAT 是单精度浮点数,通常占用 4 个字节;DOUBLE 是双精度浮点数,占用 8 个字节。例如:
CREATE TABLE prices (
    price FLOAT
);

但要注意浮点数在计算机中的存储方式可能导致精度问题,对于精度要求极高的场景,如金融计算,建议使用 DECIMAL 类型。 3. 定点数类型DECIMAL 类型用于存储精确的小数,它以字符串形式存储数据,因此可以保证精度。定义 DECIMAL 类型字段时需要指定总位数和小数位数,例如:

CREATE TABLE amounts (
    amount DECIMAL(10, 2)
);

这里表示总位数为 10 位,其中小数部分占 2 位。

日期和时间类型

  1. DATE:用于存储日期,格式为 YYYY - MM - DD。例如:
CREATE TABLE events (
    event_date DATE
);
INSERT INTO events (event_date) VALUES ('2023 - 10 - 01');
  1. TIME:存储时间,格式为 HH:MM:SS。可以表示一天内的时间,例如:
CREATE TABLE schedules (
    start_time TIME
);
INSERT INTO schedules (start_time) VALUES ('09:30:00');
  1. DATETIME:结合了日期和时间,格式为 YYYY - MM - DD HH:MM:SS。例如:
CREATE TABLE records (
    create_time DATETIME
);
INSERT INTO records (create_time) VALUES ('2023 - 10 - 01 14:20:30');
  1. TIMESTAMP:也存储日期和时间,但它的存储范围较小,且会根据时区进行调整。TIMESTAMP 类型在插入或更新数据时,如果没有指定值,会自动设置为当前时间。例如:
CREATE TABLE logs (
    log_time TIMESTAMP
);
INSERT INTO logs () VALUES ();
  1. YEAR:用于存储年份,占用 1 个字节,可以表示 1901 到 2155 年。例如:
CREATE TABLE products (
    release_year YEAR
);
INSERT INTO products (release_year) VALUES (2023);

字符串类型

  1. CHAR:固定长度字符串类型,长度在创建表时指定。例如 CHAR(10) 表示无论实际存储的字符串长度是多少,都会占用 10 个字符的空间。如果存储的字符串长度小于指定长度,会在右侧填充空格。例如:
CREATE TABLE names (
    name CHAR(20)
);
INSERT INTO names (name) VALUES ('John');

这里 John 后面会填充 16 个空格。 2. VARCHAR:可变长度字符串类型,它根据实际存储的字符串长度来分配空间,但最大长度在创建表时指定。例如 VARCHAR(50) 表示最多可以存储 50 个字符。例如:

CREATE TABLE descriptions (
    description VARCHAR(100)
);
INSERT INTO descriptions (description) VALUES ('This is a long description.');
  1. TEXT:用于存储大文本数据,分为 TINYTEXTTEXTMEDIUMTEXTLONGTEXT,它们的最大长度不同。例如:
CREATE TABLE articles (
    content TEXT
);
INSERT INTO articles (content) VALUES ('This is a very long article...');
  1. ENUM:枚举类型,它允许在创建表时指定一个值的列表,字段只能从这个列表中取值。例如:
CREATE TABLE genders (
    gender ENUM('Male', 'Female')
);
INSERT INTO genders (gender) VALUES ('Male');
  1. SET:集合类型,与 ENUM 类似,但一个字段可以存储多个值。例如:
CREATE TABLE hobbies (
    hobby SET('Reading', 'Writing', 'Painting')
);
INSERT INTO hobbies (hobby) VALUES ('Reading, Painting');

MySQL 数据库操作

创建数据库

使用 CREATE DATABASE 语句来创建数据库。语法如下:

CREATE DATABASE [IF NOT EXISTS] database_name;

例如,创建一个名为 test_db 的数据库:

CREATE DATABASE test_db;

IF NOT EXISTS 关键字是可选的,它用于避免在数据库已存在时出现错误。

删除数据库

使用 DROP DATABASE 语句删除数据库。语法如下:

DROP DATABASE [IF EXISTS] database_name;

例如,删除 test_db 数据库:

DROP DATABASE test_db;

同样,IF EXISTS 关键字用于避免在数据库不存在时出现错误。

选择数据库

在对数据库进行操作之前,需要先选择要操作的数据库。使用 USE 语句来选择数据库:

USE database_name;

例如,选择 test_db 数据库:

USE test_db;

MySQL 表操作

创建表

使用 CREATE TABLE 语句创建表,在创建表时需要定义表的字段及其数据类型等。语法如下:

CREATE TABLE [IF NOT EXISTS] table_name (
    column1 data_type [column_constraint],
    column2 data_type [column_constraint],
   ...
    [table_constraint]
);

例如,创建一个 students 表:

CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT,
    gender ENUM('Male', 'Female')
);

这里 id 字段设置为 PRIMARY KEY 并使用 AUTO_INCREMENT 让其自动递增;name 字段设置为 NOT NULL,表示不能为空。

删除表

使用 DROP TABLE 语句删除表。语法如下:

DROP TABLE [IF EXISTS] table_name;

例如,删除 students 表:

DROP TABLE students;

IF EXISTS 用于避免表不存在时的错误。

修改表

  1. 添加字段:使用 ALTER TABLE 语句添加字段。例如,向 students 表添加一个 email 字段:
ALTER TABLE students ADD COLUMN email VARCHAR(100);
  1. 修改字段:可以修改字段的数据类型、约束等。例如,将 age 字段的数据类型改为 SMALLINT
ALTER TABLE students MODIFY COLUMN age SMALLINT;
  1. 删除字段:使用 ALTER TABLE 语句删除字段。例如,删除 email 字段:
ALTER TABLE students DROP COLUMN email;

MySQL 数据操作

插入数据

  1. 插入单条记录:使用 INSERT INTO 语句插入单条记录。语法如下:
INSERT INTO table_name (column1, column2,...) VALUES (value1, value2,...);

例如,向 students 表插入一条记录:

INSERT INTO students (name, age, gender) VALUES ('Alice', 20, 'Female');
  1. 插入多条记录:可以一次性插入多条记录,只需要在 VALUES 后用逗号分隔不同的记录值。例如:
INSERT INTO students (name, age, gender) VALUES 
('Bob', 22, 'Male'),
('Charlie', 21, 'Male');

查询数据

  1. 基本查询:使用 SELECT 语句进行基本查询。语法如下:
SELECT column1, column2 FROM table_name;

例如,查询 students 表中的 nameage 字段:

SELECT name, age FROM students;
  1. 条件查询:使用 WHERE 子句进行条件查询。例如,查询年龄大于 20 的学生:
SELECT * FROM students WHERE age > 20;

这里 * 表示查询所有字段。 3. 排序查询:使用 ORDER BY 子句对查询结果进行排序。例如,按年龄升序查询学生:

SELECT * FROM students ORDER BY age ASC;

ASC 表示升序,DESC 表示降序。 4. 聚合查询:使用聚合函数(如 SUMAVGCOUNTMINMAX)进行聚合查询。例如,查询学生的平均年龄:

SELECT AVG(age) FROM students;
  1. 分组查询:结合聚合函数和 GROUP BY 子句进行分组查询。例如,按性别统计学生人数:
SELECT gender, COUNT(*) FROM students GROUP BY gender;

更新数据

使用 UPDATE 语句更新数据。语法如下:

UPDATE table_name SET column1 = value1, column2 = value2 WHERE condition;

例如,将学生 Alice 的年龄更新为 21:

UPDATE students SET age = 21 WHERE name = 'Alice';

删除数据

使用 DELETE FROM 语句删除数据。语法如下:

DELETE FROM table_name WHERE condition;

例如,删除年龄小于 18 的学生记录:

DELETE FROM students WHERE age < 18;

MySQL 索引

索引的概念

索引是一种数据结构,它可以提高数据库查询的效率。就像一本书的目录,通过索引可以快速定位到所需的数据。在 MySQL 中,索引存储了表中一列或多列的值以及这些值所在行的物理地址,当执行查询时,数据库可以通过索引快速找到符合条件的行,而不必全表扫描。

索引的类型

  1. 普通索引:最基本的索引类型,它没有任何限制。例如,为 students 表的 name 字段创建普通索引:
CREATE INDEX idx_name ON students (name);
  1. 唯一索引:保证索引列的值唯一,不允许出现重复值。例如,为 students 表的 email 字段创建唯一索引(假设 email 字段唯一):
CREATE UNIQUE INDEX idx_email ON students (email);
  1. 主键索引:一种特殊的唯一索引,每个表只能有一个主键索引,主键列的值不能为空且必须唯一。在创建表时定义主键索引,如前面创建 students 表时:
CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT,
    gender ENUM('Male', 'Female')
);
  1. 组合索引:基于多个列创建的索引。例如,为 students 表的 nameage 字段创建组合索引:
CREATE INDEX idx_name_age ON students (name, age);

索引的使用注意事项

虽然索引可以提高查询效率,但也不是越多越好。过多的索引会占用额外的存储空间,并且在插入、更新和删除数据时,数据库需要同时更新索引,从而降低了这些操作的性能。因此,在创建索引时需要权衡利弊,只在经常用于查询条件的字段上创建索引。

MySQL 约束

约束的概念

约束用于保证数据库中数据的完整性和一致性。它们定义了对表中数据的限制条件,确保数据符合特定的规则。

约束的类型

  1. NOT NULL 约束:确保字段的值不能为空。例如,在创建 students 表时,name 字段设置为 NOT NULL
CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT,
    gender ENUM('Male', 'Female')
);
  1. UNIQUE 约束:保证字段的值在表中是唯一的。除了前面通过创建唯一索引的方式实现,也可以在创建表时直接定义:
CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT,
    email VARCHAR(100) UNIQUE,
    gender ENUM('Male', 'Female')
);
  1. PRIMARY KEY 约束:定义主键,既保证唯一性又不能为空。前面已有相关示例。
  2. FOREIGN KEY 约束:用于建立表与表之间的关联关系。假设有一个 classes 表和 students 表,students 表中的 class_id 字段关联到 classes 表的 id 字段:
CREATE TABLE classes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    class_name VARCHAR(50)
);

CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT,
    class_id INT,
    gender ENUM('Male', 'Female'),
    FOREIGN KEY (class_id) REFERENCES classes(id)
);

这样就建立了外键约束,students 表中的 class_id 必须是 classes 表中存在的 id 值。 5. CHECK 约束:用于限制字段的值必须满足指定的条件。例如,限制 students 表中 age 字段的值必须大于 0:

CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT CHECK (age > 0),
    gender ENUM('Male', 'Female')
);

MySQL 事务

事务的概念

事务是一组数据库操作的集合,这些操作要么全部成功执行,要么全部不执行,以保证数据的一致性和完整性。例如,在银行转账操作中,从账户 A 扣除一定金额,同时向账户 B 增加相同金额,这两个操作必须作为一个整体,要么都成功,要么都失败,否则会导致数据不一致。

事务的特性

  1. 原子性(Atomicity):事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败回滚。
  2. 一致性(Consistency):事务执行前后,数据库的完整性约束没有被破坏,数据处于一致的状态。
  3. 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应该受到其他事务的干扰,每个事务都感觉不到其他事务的存在。
  4. 持久性(Durability):一旦事务提交,其对数据库的修改就应该永久保存,即使系统发生故障也不会丢失。

事务的操作

  1. 开始事务:使用 START TRANSACTION 语句开始一个事务。例如:
START TRANSACTION;
  1. 提交事务:使用 COMMIT 语句提交事务,表示事务中的所有操作都成功执行,对数据的修改永久保存到数据库。例如:
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT;
  1. 回滚事务:使用 ROLLBACK 语句回滚事务,撤销事务中所有未提交的操作,将数据恢复到事务开始前的状态。例如:
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- 假设出现错误
ROLLBACK;

事务的隔离级别

MySQL 支持四种事务隔离级别:

  1. 读未提交(Read Uncommitted):一个事务可以读取另一个未提交事务的数据。这种隔离级别可能会导致脏读问题,即读取到了其他事务未提交的脏数据。
  2. 读已提交(Read Committed):一个事务只能读取已经提交的事务的数据。它避免了脏读问题,但可能会出现不可重复读问题,即在同一个事务中多次读取同一数据时,由于其他事务的修改导致读取结果不一致。
  3. 可重复读(Repeatable Read):在同一个事务中多次读取同一数据时,读取结果是一致的。它避免了脏读和不可重复读问题,但可能会出现幻读问题,即当一个事务按照某个条件多次查询数据时,其他事务插入了符合该条件的新数据,导致查询结果不一致。
  4. 串行化(Serializable):最高的隔离级别,它通过强制事务串行执行,避免了所有的并发问题,但性能较低,因为它会对事务进行锁操作,限制了并发度。

可以使用以下语句设置事务隔离级别:

SET SESSION TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE];

MySQL 备份与恢复

备份

  1. 使用 mysqldump 命令mysqldump 是 MySQL 提供的一个用于备份数据库的工具。它可以将数据库中的数据和结构以 SQL 语句的形式导出到文件中。例如,备份整个 test_db 数据库:
mysqldump -u root -p test_db > test_db_backup.sql

这里 -u 表示用户名,-p 提示输入密码,> 后面是备份文件的路径和名称。如果要备份多个数据库,可以在数据库名处列出多个数据库名,用空格分隔。 2. 备份表:也可以只备份指定的表。例如,备份 test_db 数据库中的 students 表:

mysqldump -u root -p test_db students > students_backup.sql

恢复

  1. 使用 mysql 命令:恢复备份的数据库可以使用 mysql 命令。假设已经有一个 test_db_backup.sql 的备份文件,恢复数据库:
mysql -u root -p test_db < test_db_backup.sql

这里 -u 表示用户名,-p 提示输入密码,< 后面是备份文件的路径。 2. 在 MySQL 客户端中恢复:也可以先登录到 MySQL 客户端,然后使用 SOURCE 命令恢复备份。例如:

mysql -u root -p
USE test_db;
SOURCE /path/to/test_db_backup.sql;

通过以上对 MySQL 数据库基础概念的详细解析,包括数据类型、数据库和表的操作、数据操作、索引、约束、事务以及备份恢复等方面,希望能帮助读者全面深入地理解 MySQL 数据库,为进一步的数据库开发和管理工作奠定坚实的基础。在实际应用中,需要根据具体的业务需求和场景,合理运用这些知识,以构建高效、可靠的数据库系统。