一、MySQL 简介
1.1 MySQL 的特点
- 开源免费:MySQL 提供了开源版本,适合各种规模的项目。
- 高性能:通过优化的存储引擎和查询优化器,提供高效的数据处理能力。
- 易用性:支持标准的 SQL 语法,拥有丰富的工具和社区支持。
- 可扩展性:支持大规模数据存储和高并发访问。
- 多存储引擎支持:支持多种存储引擎,如 InnoDB、MyISAM 等,满足不同需求。
- 跨平台:可在多种操作系统上运行,便于集成和部署。
二、数据库与表
2.1 数据库(Database)
数据库是数据的集合,用于组织和存储相关的数据。一个 MySQL 服务器可以包含多个数据库,每个数据库可以包含多个表。
创建数据库示例:
CREATE DATABASE my_database;
2.2 表(Table)
表是数据库中的基本存储结构,用于存储相关的数据。每个表由行(记录)和列(字段)组成,类似于电子表格。
创建表示例:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
三、数据类型
MySQL 支持多种数据类型,主要分为以下几类:
3.1 数值类型
- INT:整数类型,常用于主键。
- FLOAT、DOUBLE:浮点数类型,适用于存储精度要求不高的数值。
- DECIMAL:定点数类型,适用于需要精确计算的场景,如金融数据。
3.2 字符串类型
- VARCHAR:变长字符串,适用于存储可变长度的文本。
- CHAR:定长字符串,适用于存储固定长度的文本。
- TEXT:大文本类型,适用于存储大量文本数据。
3.3 日期和时间类型
- DATE:日期类型,格式为
YYYY-MM-DD。 - DATETIME:日期和时间类型,格式为
YYYY-MM-DD HH:MM:SS。 - TIMESTAMP:时间戳类型,用于记录数据的创建和更新时间。
3.4 布尔类型
- BOOLEAN 或 TINYINT(1):用于存储布尔值(TRUE/FALSE)。
五、主键与外键
5.1 主键(Primary Key)
主键是表中唯一标识每一条记录的字段或字段组合,通常用于引用和关联其他表的数据。
主键示例:
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
total DECIMAL(10,2),
order_date DATETIME
);
5.2 外键(Foreign Key)
外键用于建立表之间的关联,确保数据的完整性和一致性。外键约束可以防止无效的数据引用。
外键示例:
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
total DECIMAL(10,2),
order_date DATETIME,
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
外键约束解释:
- ON DELETE CASCADE:当主表中的记录被删除时,自动删除关联的子表记录。
- ON UPDATE CASCADE:当主表中的记录被更新时,自动更新关联的子表记录。
七、存储引擎
存储引擎决定了 MySQL 如何存储、索引和管理数据。不同的存储引擎有不同的特性和适用场景。
7.1 常见存储引擎
- InnoDB:
- 支持事务和外键,具有高可靠性和高性能。
- 默认存储引擎,适用于大多数应用场景。
- MyISAM:
- 不支持事务和外键,但具有较高的读性能。
- 适用于读多写少的应用,如日志存储。
- MEMORY:
- 将数据存储在内存中,具有极高的访问速度。
- 适用于临时数据存储和缓存。
- CSV:
- 以 CSV 格式存储数据,便于与其他应用程序交换数据。
- Archive:
- 适用于存储大量归档数据,支持高压缩比。
7.2 查看和更改存储引擎
查看表的存储引擎:
SHOW TABLE STATUS WHERE Name = 'users';
更改表的存储引擎:
ALTER TABLE users ENGINE=InnoDB;
7.3 InnoDB 特性
- 事务支持:支持 ACID 事务特性。
- 行级锁定:提高并发性能,减少锁竞争。
- 外键支持:确保数据的完整性和一致性。
- 崩溃恢复:通过日志和缓冲机制,实现数据的自动恢复。
十、用户管理与权限
10.1 用户管理
MySQL 通过用户和权限管理机制,控制不同用户对数据库的访问和操作权限。
创建用户示例:
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'secure_password';
10.2 权限管理
权限可以针对数据库、表、列或具体操作进行细粒度控制。
授予权限示例:
GRANT SELECT, INSERT, UPDATE ON my_database.* TO 'app_user'@'localhost';
撤销权限示例:
REVOKE INSERT ON my_database.* FROM 'app_user'@'localhost';
刷新权限:
FLUSH PRIVILEGES;
10.3 查看权限
查看当前用户权限:
SHOW GRANTS FOR 'app_user'@'localhost';
十四、安全性
14.1 认证与授权
通过用户管理和权限控制,确保只有授权的用户和应用能够访问数据库资源。
- 强密码策略:使用复杂且安全的密码。
- 最小权限原则:授予用户仅需的最低权限,避免过度授权。
14.2 数据加密
-
传输层加密(SSL/TLS):加密客户端与数据库服务器之间的通信,防止数据被窃听或篡改。
启用 SSL 示例:
[mysqld] ssl-ca=ca.pem ssl-cert=server-cert.pem ssl-key=server-key.pem -
存储层加密:加密存储在磁盘上的数据,保护静态数据的安全。可以使用 MySQL 内置的透明数据加密(TDE)或操作系统级别的加密。
14.3 审计与日志
- 审计日志:记录数据库的访问和操作行为,便于审计和追踪。
- 错误日志:记录数据库运行过程中出现的错误和警告,帮助排查问题。
- 慢查询日志:记录执行时间超过阈值的查询,辅助性能优化。
14.4 防火墙与网络安全
- 防火墙配置:限制数据库服务器的访问来源,避免未经授权的访问。
- 网络隔离:将数据库服务器放在受限的网络区域,隔离于外部互联网。
十五、事务与锁机制
15.1 锁的类型
- 行级锁(Row-Level Lock):锁定特定的行,允许高并发访问,不同事务可以同时锁定不同的行。
- 表级锁(Table-Level Lock):锁定整个表,适用于批量操作,但会降低并发性能。
- 意向锁(Intention Lock):用于标识事务希望在行级或表级锁上操作,避免锁冲突。
- 共享锁(Shared Lock):允许多个事务读取同一资源,但不允许写入。
- 排他锁(Exclusive Lock):允许一个事务读取和写入资源,其他事务无法访问。
15.2 锁的实现机制
- InnoDB 存储引擎:支持多版本并发控制(MVCC),通过行级锁和锁升级机制,实现高并发和数据一致性。
- 死锁检测与解决:InnoDB 会自动检测死锁,并回滚其中一个事务以解除死锁。
15.3 事务隔离级别
事务隔离级别决定了事务之间的可见性和并发控制,MySQL 支持以下隔离级别:
- READ UNCOMMITTED:最低隔离级别,允许脏读、不可重复读和幻读。
- READ COMMITTED:防止脏读,但仍允许不可重复读和幻读。
- REPEATABLE READ:防止脏读和不可重复读,InnoDB 默认隔离级别,仍允许幻读。
- SERIALIZABLE:最高隔离级别,完全串行化执行事务,防止脏读、不可重复读和幻读。
设置隔离级别示例:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
十六、备份与恢复高级策略
16.1 增量备份与差异备份
- 全量备份(Full Backup):备份整个数据库。
- 增量备份(Incremental Backup):备份自上次备份以来发生变化的数据。
- 差异备份(Differential Backup):备份自上次全量备份以来发生变化的数据。
16.2 Point-in-Time Recovery(PITR)
通过结合全量备份和二进制日志,实现特定时间点的数据恢复,适用于误操作或数据损坏后的恢复。
PITR 示例步骤:
-
恢复全量备份:
mysql -u root -p my_database < my_database_backup.sql -
应用二进制日志到指定时间点:
mysqlbinlog --stop-datetime="2024-04-27 12:00:00" mysql-bin.000001 | mysql -u root -p my_database
16.3 使用 Percona XtraBackup
Percona XtraBackup 是一个开源工具,用于执行非阻塞的物理备份,支持 InnoDB 和 XtraDB 存储引擎。
安装与使用示例:
# 安装 Percona XtraBackup(以 Ubuntu 为例)
sudo apt-get install percona-xtrabackup-80
# 执行备份
xtrabackup --backup --target-dir=/backups/my_backup
# 准备备份(应用日志)
xtrabackup --prepare --target-dir=/backups/my_backup
# 恢复备份
xtrabackup --copy-back --target-dir=/backups/my_backup
十七、数据库性能监控与调优
17.1 性能监控工具
- MySQL Performance Schema:内置的性能监控工具,提供详细的性能数据和统计信息。
- MySQL Enterprise Monitor:商业版监控工具,提供实时监控和报警功能。
- 第三方工具:如 Percona Monitoring and Management (PMM)、Nagios、Zabbix 等。
17.2 关键性能指标
- 查询响应时间:衡量查询的执行速度。
- 吞吐量:每秒处理的查询数量。
- 并发连接数:同时连接到数据库的客户端数量。
- 缓存命中率:衡量 InnoDB 缓冲池和查询缓存的效率。
- 锁等待和死锁:监控锁的使用情况,避免性能瓶颈。
17.3 调优策略
- 优化查询:
- 使用
EXPLAIN分析查询计划,优化索引使用。 - 避免全表扫描,尽量使用索引覆盖查询。
- 使用
- 调整服务器参数:
- innodb_buffer_pool_size:设置为物理内存的 60-80%,提高缓存能力。
- query_cache_size:适当设置查询缓存大小,提升查询性能(注意 MySQL 8.0 中已移除)。
- 水平和垂直扩展:
- 水平扩展:通过主从复制、分片等方式增加数据库实例,提升并发能力。
- 垂直扩展:升级服务器硬件,如增加内存、提升 CPU 性能。
- 分区与分表:
- 对大表进行分区(Partitioning),提高查询和管理效率。
- 根据业务需求进行分表,分散数据压力。
十八、常见问题与解决方案
18.1 数据库连接过多
原因:应用程序未正确关闭数据库连接,导致连接池耗尽。
解决方案:
- 使用连接池管理数据库连接,如 HikariCP、C3P0 等。
- 确保应用程序在完成数据库操作后正确关闭连接。
18.2 慢查询
原因:缺乏适当的索引、查询语句不优化、数据量过大等。
解决方案:
- 使用
EXPLAIN分析查询,优化索引和查询结构。 - 分析慢查询日志,定位并优化慢查询。
- 定期维护数据库,如删除无用数据、重建索引等。
18.3 死锁
原因:多个事务相互等待对方释放锁,导致系统无法继续执行。
解决方案:
- 优化事务顺序,避免循环依赖。
- 减少事务的持锁时间,尽量缩短事务的执行时间。
- 使用较低的隔离级别,如
READ COMMITTED,降低锁冲突的概率。
18.4 数据库崩溃
原因:硬件故障、操作系统崩溃、软件缺陷等。
解决方案:
- 定期备份数据,确保数据可恢复。
- 配置主从复制,提高数据库的冗余和容错能力。
- 使用 RAID 等存储技术,提升数据的可靠性。
18.5 数据库性能瓶颈
原因:资源不足(CPU、内存、磁盘)、查询效率低下、并发访问过多等。
解决方案:
- 升级服务器硬件,提升资源能力。
- 优化数据库配置参数,如调整缓冲池大小、连接数等。
- 优化查询和数据库结构,提升查询效率。
- 分布负载,使用主从复制或分片技术,提升并发处理能力。
十九、其他重要概念
19.1 正规化与反正规化
- 正规化(Normalization):设计数据库结构时,遵循规范化范式,减少数据冗余,提高数据一致性。
- 反正规化(Denormalization):在特定场景下,增加冗余数据或合并表结构,提升查询性能。
19.2 ACID 与 BASE 理论
- ACID:事务的四大特性(原子性、一致性、隔离性、持久性),确保数据库操作的可靠性。
- BASE:面向分布式系统的理论(基本可用、软状态、最终一致),适用于高可用性和可扩展性的系统。
19.3 分区(Partitioning)
分区是将一个大表分割成更小、更易管理的部分,每个分区可以独立存储和管理,提高查询和维护效率。
分区类型:
- 范围分区(Range Partitioning):基于列的范围值进行分区。
- 列表分区(List Partitioning):基于列的离散值进行分区。
- 哈希分区(Hash Partitioning):基于哈希函数进行分区,实现数据的均匀分布。
- 键分区(Key Partitioning):基于一个或多个列的值进行分区,类似于哈希分区。
创建分区表示例:
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
total DECIMAL(10,2),
order_date DATE
)
PARTITION BY RANGE (YEAR(order_date)) (
PARTITION p0 VALUES LESS THAN (1991),
PARTITION p1 VALUES LESS THAN (1992),
PARTITION p2 VALUES LESS THAN (1993),
PARTITION pMax VALUES LESS THAN MAXVALUE
);
19.4 索引覆盖(Covering Index)
当查询中的所有列都包含在索引中时,查询可以仅通过索引完成,无需回表查询数据页,提高查询性能。
示例:
CREATE INDEX idx_username_email ON users(username, email);
-- 查询使用覆盖索引
SELECT username, email FROM users WHERE username = 'john_doe';
19.5 索引选择性(Selectivity)
索引选择性是指索引列中不同值的比例,选择性越高,索引的效果越好。高选择性的列适合创建索引。
计算方法:
SELECT COUNT(DISTINCT column_name) / COUNT(*) AS selectivity FROM table_name;
二十、实际应用示例
以下是一个简单的 MySQL 在后端开发中的应用示例,展示如何创建数据库、表、执行 CRUD 操作以及使用事务。
20.1 创建数据库与表
-- 创建数据库
CREATE DATABASE ecommerce;
-- 使用数据库
USE ecommerce;
-- 创建用户表
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- 创建商品表
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
price DECIMAL(10,2) NOT NULL,
stock INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- 创建订单表
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
total DECIMAL(10,2),
order_date DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB;
-- 创建订单项表
CREATE TABLE order_items (
id INT AUTO_INCREMENT PRIMARY KEY,
order_id INT,
product_id INT,
quantity INT DEFAULT 1,
price DECIMAL(10,2),
FOREIGN KEY (order_id) REFERENCES orders(order_id)
ON DELETE CASCADE
ON UPDATE CASCADE,
FOREIGN KEY (product_id) REFERENCES products(id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB;
20.2 插入数据
-- 插入用户数据
INSERT INTO users (username, email, password) VALUES
('john_doe', 'john@example.com', 'hashed_password'),
('jane_smith', 'jane@example.com', 'hashed_password');
-- 插入商品数据
INSERT INTO products (name, description, price, stock) VALUES
('Laptop', 'High performance laptop', 1200.00, 50),
('Smartphone', 'Latest model smartphone', 800.00, 100);
20.3 查询数据
-- 查询所有用户
SELECT * FROM users;
-- 查询特定用户
SELECT * FROM users WHERE username = 'john_doe';
-- 查询库存大于 50 的商品
SELECT * FROM products WHERE stock > 50;
20.4 更新数据
-- 更新用户邮箱
UPDATE users SET email = 'john_new@example.com' WHERE username = 'john_doe';
-- 更新商品库存
UPDATE products SET stock = stock - 1 WHERE id = 1;
20.5 删除数据
-- 删除用户
DELETE FROM users WHERE username = 'jane_smith';
-- 删除商品
DELETE FROM products WHERE id = 2;
20.6 使用事务
START TRANSACTION;
-- 创建订单
INSERT INTO orders (user_id, total) VALUES (1, 1200.00);
SET @last_order_id = LAST_INSERT_ID();
-- 创建订单项
INSERT INTO order_items (order_id, product_id, quantity, price) VALUES
(@last_order_id, 1, 1, 1200.00);
-- 更新商品库存
UPDATE products SET stock = stock - 1 WHERE id = 1;
COMMIT;
20.7 事务回滚示例
START TRANSACTION;
-- 创建订单
INSERT INTO orders (user_id, total) VALUES (1, 1200.00);
SET @last_order_id = LAST_INSERT_ID();
-- 尝试创建订单项,假设产品 ID 999 不存在
INSERT INTO order_items (order_id, product_id, quantity, price) VALUES
(@last_order_id, 999, 1, 1200.00);
-- 如果上述操作失败,回滚事务
ROLLBACK;
4万+

被折叠的 条评论
为什么被折叠?



