MySQL:常用语法 / MySQL 核心知识技能梳理 / 数据库

一、数据库操作

1.1 创建与管理

-- 基本语法
CREATE DATABASE database_name;

-- 完整语法(指定字符集和排序规则)
-- 推荐使用 utf8mb4 以支持 emoji 和所有 Unicode 字符
CREATE DATABASE database_name
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci; -- 或 utf8mb4_general_ci (性能稍好,但排序精度稍低)

-- 如果不存在则创建(避免报错)
CREATE DATABASE IF NOT EXISTS database_name;

-- 查看所有数据库
SHOW DATABASES;

-- 选择/切换数据库
USE database_name;

-- 查看当前数据库
SELECT DATABASE();

-- 删除数据库
DROP DATABASE database_name;
DROP DATABASE IF EXISTS database_name;

1.2 修改数据库

-- 修改数据库字符集(注意:此操作不会转换已有表的字符集)
ALTER DATABASE database_name
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

二、表操作

2.1 数据类型(补充)

分类类型说明
整数TINYINTSMALLINTMEDIUMINTINTBIGINT可选 UNSIGNED(无符号),INT(11) 中的 11 仅为显示宽度,与存储大小无关
小数DECIMAL(M,D)FLOATDOUBLEDECIMAL 用于精确计算(如金额),M是总位数,D是小数位数
字符串CHAR(n)VARCHAR(n)TEXTLONGTEXTVARCHAR 变长,节省空间;TEXT 类型不能有默认值
日期时间DATETIMEDATETIMETIMESTAMPYEARTIMESTAMP 受时区影响,范围较小;DATETIME 范围大,不受时区影响
二进制BLOBLONGBLOBBINARYVARBINARY存储图片、文件等二进制数据
枚举ENUM('a','b','c')单选,内部存储为整数,最多 65535 个成员
集合SET('a','b','c')多选,最多 64 个成员
JSONJSONMySQL 5.7+ 支持,提供高效的 JSON 文档存储和查询
空间数据GEOMETRYPOINTLINESTRINGPOLYGON用于地理空间数据

2.2 创建表(增强)

-- 完整示例(包含更多约束和选项)
CREATE TABLE IF NOT EXISTS users (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  username VARCHAR(50) NOT NULL COMMENT '用户名',
  email VARCHAR(100) NOT NULL COMMENT '邮箱',
  age TINYINT UNSIGNED DEFAULT 0 COMMENT '年龄',
  status ENUM('active', 'inactive', 'banned') NOT NULL DEFAULT 'active' COMMENT '状态',
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  
  -- 约束
  PRIMARY KEY (id),
  UNIQUE KEY uk_username (username),
  UNIQUE KEY uk_email (email),
  INDEX idx_status_age (status, age), -- 复合索引
  
  -- 外键约束
  -- ON DELETE CASCADE: 主表删除时,从表关联行也删除
  -- ON DELETE SET NULL: 主表删除时,从表关联字段设为NULL
  -- ON UPDATE CASCADE: 主表主键更新时,从表关联字段也更新
  FOREIGN KEY (dept_id) REFERENCES departments(id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';

-- 分区表(适用于大数据量)
CREATE TABLE sales_log (
  id INT AUTO_INCREMENT,
  sale_date DATE NOT NULL,
  amount DECIMAL(10, 2),
  PRIMARY KEY (id, sale_date) -- 分区键必须是主键的一部分
)
PARTITION BY RANGE (YEAR(sale_date)) (
  PARTITION p2022 VALUES LESS THAN (2023),
  PARTITION p2023 VALUES LESS THAN (2024),
  PARTITION p2024 VALUES LESS THAN (2025)
);

-- 创建表时指定存储引擎和字符集
-- ENGINE=InnoDB (支持事务、行锁、外键)
-- ENGINE=MyISAM (不支持事务,表锁,全文索引,旧版本默认)
-- ENGINE=Memory (数据存于内存,速度快,重启后丢失)

2.3 修改表

-- 修改表名
ALTER TABLE old_name RENAME TO new_name;
RENAME TABLE old_name TO new_name;

-- 修改列(重命名+改类型+改约束)
ALTER TABLE table_name CHANGE old_col_name new_col_name new_datatype [NOT NULL] [DEFAULT 'value'];

-- 仅修改列的约束或默认值(比 CHANGE 更高效)
ALTER TABLE table_name MODIFY col_name datatype NOT NULL DEFAULT 'new_default';

-- 添加/删除外键
ALTER TABLE table_name ADD CONSTRAINT fk_name FOREIGN KEY (col) REFERENCES other_table(id);
ALTER TABLE table_name DROP FOREIGN KEY fk_name;

-- 表选项
ALTER TABLE table_name ROW_FORMAT=DYNAMIC; -- 优化行存储格式
ALTER TABLE table_name COMMENT = '新的表注释';

三、数据操作(CRUD)

3.1 插入数据 (INSERT) 

-- 批量插入并忽略错误
INSERT IGNORE INTO table_name (id, name) VALUES (1, 'a'), (2, 'b');

-- 批量插入并更新(UPSERT)
INSERT INTO table_name (id, name, count) VALUES (1, 'a', 10), (2, 'b', 20)
ON DUPLICATE KEY UPDATE count = VALUES(count) + count; -- VALUES() 函数引用待插入的值

-- 使用 SET 语法插入(更灵活)
INSERT INTO table_name SET id = 1, name = 'test';

3.2 查询数据 (SELECT) 

-- 强制使用指定索引(Index Hint)
SELECT * FROM users FORCE INDEX (idx_email) WHERE email = 'test@example.com';
SELECT * FROM users IGNORE INDEX (idx_status) WHERE status = 'active';

-- 查询锁定
SELECT * FROM orders WHERE status = 'pending' FOR UPDATE; -- 排他锁(写锁)
SELECT * FROM orders WHERE status = 'pending' LOCK IN SHARE MODE; -- 共享锁(读锁)

-- 分组后筛选 (HAVING vs WHERE)
-- WHERE 在分组前筛选行
-- HAVING 在分组后筛选组
SELECT department, AVG(salary) as avg_sal
FROM employees
WHERE hire_date > '2020-01-01'  -- 先筛选出2020年后入职的员工
GROUP BY department
HAVING AVG(salary) > 5000;      -- 再筛选出平均工资大于5000的部门

-- 流程控制函数
SELECT
  name,
  IF(score >= 60, '及格', '不及格') AS result,
  CASE
    WHEN score >= 90 THEN '优秀'
    WHEN score >= 80 THEN '良好'
    WHEN score >= 60 THEN '及格'
    ELSE '不及格'
  END AS grade
FROM exam_results;

3.3 连接查询 (JOIN) 

-- STRAIGHT_JOIN: 强制按 FROM 子句中表的顺序进行连接
SELECT * FROM table1 STRAIGHT_JOIN table2 ON table1.id = table2.id;

3.4 子查询

-- 关联子查询(效率较低,慎用)
SELECT * FROM users u WHERE (SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) > 10;
-- 优化为 JOIN
SELECT u.* FROM users u JOIN (SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id HAVING order_count > 10) o_count ON u.id = o_count.user_id;

3.5 窗口函数 (MySQL 8.0+)

-- 窗口函数框架: FUNCTION() OVER (PARTITION BY ... ORDER BY ... [frame_clause])
-- frame_clause: ROWS/RANGE BETWEEN start AND end
--   - UNBOUNDED PRECEDING: 分区开始
--   - N PRECEDING: 当前行前N行
--   - CURRENT ROW: 当前行
--   - N FOLLOWING: 当前行后N行
--   - UNBOUNDED FOLLOWING: 分区结束

-- 计算移动平均(最近3行)
SELECT
  date,
  amount,
  AVG(amount) OVER (ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3_days
FROM daily_sales;

-- 计算累计占比
SELECT
  category,
  amount,
  SUM(amount) OVER (PARTITION BY category ORDER BY date) AS cumulative_sum,
  amount / SUM(amount) OVER (PARTITION BY category) AS percentage_of_total
FROM sales;

四、索引与性能优化

4.1 索引类型

B-Tree 索引:默认索引类型,适用于全值匹配、范围查询、排序。

Hash 索引:仅 Memory 引擎显式支持,仅适用于精确匹配(=),速度快。

全文索引 (FULLTEXT):用于 CHARVARCHARTEXT 列的文本搜索。

CREATE FULLTEXT INDEX idx_content ON articles(title, body);
SELECT * FROM articles WHERE MATCH(title, body) AGAINST('MySQL 性能优化' IN NATURAL LANGUAGE MODE);

空间索引 (SPATIAL):用于地理空间数据类型。

降序索引 (Descending Index):MySQL 8.0+ 支持,优化 ORDER BY col DESC 查询。

CREATE INDEX idx_created_at_desc ON logs(created_at DESC);

隐藏索引 (Invisible Index):MySQL 8.0+ 支持,优化器会忽略此索引,用于测试删除索引的影响。

CREATE INDEX idx_name ON users(name) INVISIBLE;
ALTER TABLE users ALTER INDEX idx_name VISIBLE;

函数索引 (Function-Based Index):MySQL 8.0+ 支持,对表达式结果建索引。

CREATE INDEX idx_lower_email ON users((LOWER(email)));
SELECT * FROM users WHERE LOWER(email) = 'test@example.com';

4.2 性能优化建议

-- 1. 使用 EXPLAIN 分析查询计划
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
EXPLAIN FORMAT=JSON SELECT ...; -- 更详细的JSON格式输出
EXPLAIN ANALYZE SELECT ...; -- MySQL 8.0+ 实际执行查询并显示成本和时间

-- 2. 避免 SELECT *,只取需要的列
SELECT id, name FROM users;

-- 3. 避免在 WHERE 子句中对索引列使用函数或计算
-- 错误: WHERE YEAR(created_at) = 2023 (索引失效)
-- 正确: WHERE created_at >= '2023-01-01' AND created_at < '2024-01-01' (索引有效)

-- 4. 使用 EXISTS 代替 IN (对于大子查询)
-- WHERE id IN (SELECT user_id FROM orders)
-- 优化为:
-- WHERE EXISTS (SELECT 1 FROM orders WHERE user_id = users.id)

-- 5. 合理使用索引覆盖 (Covering Index)
-- 索引包含查询所需的所有列,无需回表
CREATE INDEX idx_covering ON orders (user_id, amount, status);
SELECT user_id, amount FROM orders WHERE user_id = 123; -- 只需扫描索引

-- 6. 分批处理大量数据更新/删除
-- DELETE FROM logs WHERE created_at < '2024-01-01' LIMIT 10000;
-- 在循环中执行,避免长事务和锁竞争

-- 7. 使用合适的 JOIN 算法
-- Block Nested-Loop (BNL) Join: 驱动表结果集存入 join buffer
-- MySQL 会自动选择,可通过 `optimizer_switch` 调整

-- 8. 优化 COUNT(*) 查询
-- InnoDB 中 COUNT(*) 需要全表扫描,可近似查询或使用缓存/触发器维护计数
SELECT COUNT(*) FROM users; -- 慢
SELECT TABLE_ROWS FROM information_schema.tables WHERE table_name = 'users'; -- 快但不精确

五、高级对象

5.1 视图 (VIEW)

-- 创建视图
CREATE VIEW active_users_view AS
SELECT id, username, email FROM users WHERE status = 'active';

-- 可更新视图(需满足一定条件,如不含聚合、DISTINCT、GROUP BY等)
CREATE VIEW user_email_view AS SELECT id, email FROM users;
UPDATE user_email_view SET email = 'new@example.com' WHERE id = 1; -- 会更新基表

-- 查看视图定义
SHOW CREATE VIEW view_name;

5.2 存储过程与函数

-- 存储过程:可以执行复杂的逻辑,无返回值(通过OUT参数返回)
DELIMITER //
CREATE PROCEDURE GetUserOrders(IN userId INT, OUT orderCount INT)
BEGIN
  SELECT COUNT(*) INTO orderCount FROM orders WHERE user_id = userId;
END //
DELIMITER ;

-- 函数:必须有返回值,不能修改数据库状态(除非是 DETERMINISTIC 或 NOT DETERMINISTIC)
DELIMITER //
CREATE FUNCTION CalculateDiscount(price DECIMAL(10,2), level INT)
RETURNS DECIMAL(10,2)
DETERMINISTIC -- 声明为确定性函数,可被优化
BEGIN
  DECLARE discount DECIMAL(10,2);
  IF level > 3 THEN
    SET discount = 0.2;
  ELSEIF level > 1 THEN
    SET discount = 0.1;
  ELSE
    SET discount = 0;
  END IF;
  RETURN price * (1 - discount);
END //
DELIMITER ;

5.3 触发器 (TRIGGER)

-- 创建触发器
-- NEW 和 OLD 是伪记录,分别代表新/旧行数据
CREATE TRIGGER before_user_update
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
  IF OLD.email != NEW.email THEN
    INSERT INTO user_audit_log (user_id, old_email, new_email, change_time)
    VALUES (OLD.id, OLD.email, NEW.email, NOW());
  END IF;
END;

-- 查看触发器
SHOW TRIGGERS;
SHOW TRIGGERS LIKE 'user%';

5.4 事件调度器 (Event Scheduler)

-- 开启事件调度器
SET GLOBAL event_scheduler = ON;

-- 创建定时任务(例如:每天凌晨1点归档日志)
CREATE EVENT archive_logs_daily
ON SCHEDULE EVERY 1 DAY
STARTS '2024-01-01 01:00:00'
DO
BEGIN
  INSERT INTO logs_archive SELECT * FROM logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
  DELETE FROM logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
END;

-- 查看事件
SHOW EVENTS;

-- 修改/删除事件
ALTER EVENT archive_logs_daily DISABLE; -- 禁用
DROP EVENT archive_logs_daily;

六、事务与锁

6.1 事务控制

-- 事务特性 (ACID)
-- Atomicity (原子性), Consistency (一致性), Isolation (隔离性), Durability (持久性)

-- 隔离级别
-- READ UNCOMMITTED (读未提交): 脏读
-- READ COMMITTED (读已提交): 不可重复读 (Oracle, SQL Server 默认)
-- REPEATABLE READ (可重复读): 幻读 (MySQL InnoDB 默认)
-- SERIALIZABLE (串行化): 性能最差,最安全

-- 设置事务隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 事务操作
START TRANSACTION; -- 或 BEGIN
-- ... SQL 语句 ...
COMMIT; -- 提交
-- ROLLBACK; -- 回滚

-- 保存点 (Savepoint)
SAVEPOINT sp1;
-- ... SQL 语句 ...
ROLLBACK TO SAVEPOINT sp1; -- 回滚到保存点
RELEASE SAVEPOINT sp1; -- 释放保存点

6.2 锁机制

表锁 (Table Lock):开销小,加锁快,无死锁,但并发度低。MyISAM 默认。

LOCK TABLES table_name READ; -- 共享锁
LOCK TABLES table_name WRITE; -- 排他锁
UNLOCK TABLES;

行锁 (Row Lock):开销大,加锁慢,会出现死锁,但并发度高。InnoDB 支持。

记录锁 (Record Lock):锁住单条索引记录。

间隙锁 (Gap Lock):锁住索引区间,防止幻读。

临键锁 (Next-Key Lock):记录锁 + 间隙锁。

行锁是在需要时自动加的,也可以手动控制:

SELECT * FROM table_name WHERE id = 1 FOR UPDATE; -- 排他行锁
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE; -- 共享行锁

死锁 (Deadlock):两个或多个事务相互等待对方释放锁。InnoDB 有死锁检测机制,会自动回滚代价较小的事务。

七、用户、权限与安全

-- 创建用户
CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'StrongPassword123!';
CREATE USER 'readonly_user'@'%' IDENTIFIED BY 'password';

-- 授予权限
-- 权限级别: *.* (所有库所有表), db_name.* (指定库所有表), db_name.table_name (指定表)
GRANT SELECT, INSERT ON my_app.* TO 'app_user'@'192.168.1.%';
GRANT SELECT ON my_app.products TO 'readonly_user'@'%';
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' WITH GRANT OPTION; -- 允许授权给他人

-- 撤销权限
REVOKE INSERT ON my_app.* FROM 'app_user'@'192.168.1.%';

-- 查看权限
SHOW GRANTS FOR 'app_user'@'192.168.1.%';
SHOW GRANTS FOR CURRENT_USER;

-- 刷新权限(修改授权表后需要)
FLUSH PRIVILEGES;

-- 删除用户
DROP USER 'app_user'@'192.168.1.%';

八、备份、恢复与复制

8.1 备份与恢复

# 逻辑备份 (mysqldump)
# 备份整个数据库
mysqldump -u root -p --single-transaction --routines --triggers --events my_app > my_app_backup.sql

# 备份指定表
mysqldump -u root -p my_app users orders > users_orders_backup.sql

# 恢复
mysql -u root -p my_app < my_app_backup.sql
# 或在 mysql 命令行中
SOURCE /path/to/my_app_backup.sql;

--single-transaction: 对于 InnoDB 表,可以在不锁表的情况下进行一致性备份。

--routines--triggers--events: 备份存储过程、触发器和事件。

8.2 二进制日志 (Binary Log)

记录所有对数据库的更改(DDL 和 DML),用于主从复制和数据恢复。

在 my.cnf 或 my.ini 中配置:

ini

[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW # ROW, STATEMENT, MIXED

查看二进制日志:

SHOW BINARY LOGS;
SHOW BINLOG EVENTS IN 'mysql-bin.000003';

使用 mysqlbinlog 工具恢复数据:

bash
mysqlbinlog /var/log/mysql/mysql-bin.000003 | mysql -u root -p

九、JSON 操作 (MySQL 5.7+)

-- 创建表
CREATE TABLE products (
  id INT PRIMARY KEY AUTO_INCREMENT,
  info JSON
);

-- 插入 JSON
INSERT INTO products (info) VALUES
('{"name": "Laptop", "price": 1200, "specs": {"ram": "16GB", "storage": "512GB SSD"}, "tags": ["electronics", "computer"]}'),
('{"name": "Mouse", "price": 25}');

-- 查询 JSON (-> 提取, ->> 提取并去引号)
SELECT
  info->'$.name' AS name_json,         -- "Laptop"
  info->>'$.name' AS name_string,      -- Laptop
  info->>'$.specs.ram' AS ram,         -- 16GB
  JSON_EXTRACT(info, '$.price') AS price
FROM products;

-- 更新 JSON
UPDATE products SET info = JSON_SET(info, '$.price', 1150) WHERE id = 1;
UPDATE products SET info = JSON_INSERT(info, '$.discount', 0.1) WHERE id = 1;
UPDATE products SET info = JSON_REMOVE(info, '$.specs.storage') WHERE id = 1;
UPDATE products SET info = JSON_ARRAY_APPEND(info, '$.tags', 'gadget') WHERE id = 1;

-- 查询 JSON 数组
SELECT info->'$.tags[0]' FROM products WHERE id = 1; -- "electronics"
SELECT JSON_CONTAINS(info->'$.tags', '"computer"') FROM products; -- 1 (true)
SELECT JSON_SEARCH(info, 'one', 'Mouse') FROM products; -- "$.name"

十、常用系统命令与工具

-- 查看服务器状态
SHOW STATUS LIKE 'Threads_connected'; -- 当前连接数
SHOW STATUS LIKE 'Innodb_row_lock_waits'; -- InnoDB 行锁等待次数
SHOW VARIABLES LIKE 'max_connections'; -- 最大连接数

-- 查看进程列表
SHOW PROCESSLIST;
KILL [process_id]; -- 终止某个连接

-- 查看表状态
SHOW TABLE STATUS FROM database_name LIKE 'table_name';

-- 分析表
ANALYZE TABLE table_name; -- 更新索引的基数信息
OPTIMIZE TABLE table_name; -- 整理碎片(仅对MyISAM和InnoDB有效)

-- 检查表
CHECK TABLE table_name;

-- 查看字符集和排序规则
SHOW CHARACTER SET;
SHOW COLLATION;

十一、一个MySQL数据库的容量是多大,可以放多少张表,多少行数据

MySQL 的容量非常灵活,并没有一个固定的“数据库大小上限”,它主要受限于你的硬盘空间和操作系统

维度理论上限实际约束
单个数据库最大容量无限(受文件系统限制)受硬盘物理空间限制,以及文件系统单文件大小限制(如 FAT32 的 4GB 限制,NTFS 几乎无限制)
单表最大容量256 TB(InnoDB 默认页大小 16KB)实际受硬盘限制,且大表会影响性能
单表最大行数2^64 - 1(约 1844 亿亿)受主键类型和硬盘空间限制,实际远小于理论值
单表最大列数1017 列(InnoDB)受行大小限制,实际通常远小于这个数
单行最大大小65535 字节(约 64KB)这是硬性限制,但不包括 BLOB/TEXT 等大字段类型
索引最大长度767 字节(InnoDB 默认) / 3072 字节(开启参数后)受 innodb_large_prefix 参数影响
主键字段最大长度3072 字节受 innodb_large_prefix 和 innodb_page_size 影响
自增主键最大值2^31 - 1(约 21.47 亿)int 类型)或 2^63 - 1bigint 类型)使用 int 类型自增主键时,行数不能超过 21.47 亿

说明:数据库总容量没有理论上限,完全取决于你的硬盘大小和操作系统限制。比如你挂载一个 2TB 的硬盘,数据库最大就能到 2TB 左右。

不同存储引擎的容量对比

对比项InnoDB(默认)MyISAMMemory
单表最大容量256 TB(页大小 16KB)256 TB(受操作系统文件大小限制)受 max_heap_table_size 限制(默认 16MB)
单表最大行数2^64 - 12^64 - 1受内存大小限制,约几百万行
是否支持事务✅ 支持❌ 不支持❌ 不支持
行级锁✅ 支持❌ 仅表级锁❌ 仅表级锁
崩溃恢复✅ 支持❌ 不支持❌ 不支持
适用场景生产环境所有场景读多写少的历史表、日志表临时表、缓存表
不同存储引擎的容量对比
数据量级别建议存储方式性能表现说明
小于 100 万行单表直接存储查询极快(毫秒级)不需要考虑任何优化
100 万 ~ 500 万行单表存储 + 合理索引查询较快(几十毫秒)需要建立正确索引,定期维护
500 万 ~ 2000 万行单表 + 分区表/归档查询中速(百毫秒级)建议对历史数据做归档或分区(如按月分区)
2000 万 ~ 1 亿行分库分表(按业务维度)查询中速(需设计好分片策略)必须分库分表,建议使用 ShardingSphereMyCat
> 1 亿行分库分表 + 大数据组件中等速度,依赖架构设计建议用 TiDB 或 OLAP 数据库(如 ClickHouse

突破 2000 万行限制的常用方案

方案适用场景核心原理
分区表(Partition)单表数据量大,但可按时间/范围等业务维度拆分物理上分成多个子表,逻辑上对外暴露一张表
分库分表数据量巨大(亿级、十亿级)按业务键(如用户ID)将数据分散到多个物理库/表
使用 TiDB需要 MySQL 协议兼容、自动水平扩展分布式数据库,自动分片和负载均衡
使用 ClickHouse海量数据的分析查询场景列式存储,压缩比高,查询极快
数据归档历史数据不常查询将老旧数据迁移到冷存储,主表只保留近期数据
总结
单个 MySQL 数据库最多能有多大?没有上限,受硬盘空间限制。
最多能放多少张表?受文件系统限制,InnoDB 理论支持最多 40亿 个表,实际受文件描述符限制。
最多能放多少行数据?InnoDB 理论支持 1844 亿亿 行,实际受硬盘空间和索引结构限制。
单表超过 2000 万行怎么办?考虑分区、分库分表或迁移到分布式数据库。
生产环境应该用什么?绝大多数业务用 InnoDB,常规表控制在 2000 万行以内,达到或超过该数量及时进行分区或分库分表。

十二、Web服务器和SQL数据库服务器

浏览器(HTTP)
    ↓
Web服务器(Nginx,处理HTTP协议)
    ↓
应用服务器(Spring Boot,处理业务逻辑)
    ↓
JDBC驱动(把Java调用翻译成MySQL协议)
    ↓
SQL数据库服务器(MySQL,处理MySQL协议)
    ↓
返回数据

十三、MySQL数据库服务器的作用与职责

作用维度具体职责通俗解释
监听与连接管理• 在默认端口(3306)上监听来自客户端的TCP/IP连接请求
• 认证客户端身份(验证用户名、密码、来源IP)
• 为每个连接分配线程或进程,维护连接池
像个值班的门卫,登记来访者身份,为每个来访者分配一个专属“接待员”。
SQL指令解析与执行• 接收并解析客户端发来的SQL语句(SELECT、INSERT等)
• 检查SQL语法和语义是否正确
• 生成执行计划,选择最优算法(如索引查找、全表扫描)
像个翻译官,把“数据库语言”翻译成机器能执行的指令。
存储引擎交互• 调用底层存储引擎(如InnoDB、MyISAM)
• 负责数据的实际读写、索引维护、事务日志记录
像个仓库管理员,指挥叉车工(存储引擎)把货物(数据)放到指定货架(磁盘)上。
事务管理与锁控制• 管理事务的ACID特性(原子性、一致性、隔离性、持久性)
• 实现MVCC(多版本并发控制),提供不同隔离级别
• 管理表锁、行锁等,保证并发操作的数据一致性
像个裁判,保证多个人同时操作同一张表时,数据不乱套。
结果集返回• 将查询到的数据按客户端要求的格式(如结果集、JSON、CSV)返回
• 返回操作状态(如“受影响的行数”)
像个送货员,把打包好的数据结果安全送回给客户端。
安全与权限管理• 管理用户账户、角色和权限(如SELECT、INSERT权限)
• 记录操作日志,提供审计功能
像个保安队长,决定谁能进哪个房间(数据库),能拿什么东西(表/字段)。
缓存与性能优化• 管理查询缓存(Query Cache)
• 管理InnoDB缓冲池,预读和缓存数据页
• 通过慢查询日志、执行计划分析,辅助性能调优
像个管家,把常用的东西(数据/指令)放在随手能拿到的地方(缓存),以提高效率。
数据备份与恢复• 提供逻辑备份工具(如mysqldump
• 维护二进制日志(binlog),用于数据恢复和主从复制
像个档案员,定期给重要资料做副本,并记录所有的“改动日志”。
高可用与复制• 支持主从复制,将数据同步到备用服务器
• 支持组复制、InnoDB Cluster等高可用方案
像个备胎管理员,确保一旦主服务器出问题,备用车(从库)能立刻顶上。
MySQL数据库服务器是一个集门卫、翻译官、仓库管理员、裁判、送货员、保安队长、管家、档案员、备胎管理员于一体的“全能型后台服务进程”,它负责安全、高效、可靠地处理所有对数据库的访问请求和数据操作。
数据库服务器“天生就懂”自己的专属协议(比如MySQL协议),所以在和它通信时,确实不需要像处理HTTP请求那样,再去做一次“翻译”。

十四、常见数据库的通信协议与JDBC驱动

数据库使用的通信协议JDBC驱动类(示例)连接URL格式(示例)
MySQLMySQL协议 (基于TCP);
所以不需要像HTTP协议那样做“协议转换”或“翻译”
com.mysql.cj.jdbc.Driver (MySQL 8+)jdbc:mysql://localhost:3306/mydb
PostgreSQLPostgreSQL协议 (基于TCP)org.postgresql.Driverjdbc:postgresql://localhost:5432/mydb
SQL ServerTDS (Tabular Data Stream) 协议com.microsoft.sqlserver.jdbc.SQLServerDriverjdbc:sqlserver://localhost:1433;databaseName=mydb
OracleOracle Net协议oracle.jdbc.driver.OracleDriverjdbc:oracle:thin:@//localhost:1521/orcl
你可以看到,连接URL的通用格式是 jdbc:子协议:子名称,这里的“子协议”就指明了具体要和哪个数据库通信。

十五、JDBC与HTTP的对比

对比维度Java应用 → SQL数据库 (JDBC)Java应用 → Web服务 (HTTP)
通信协议MySQL协议 / TDS协议 / Oracle Net协议等HTTP / HTTPS
主要用途执行SQL语句,存取关系型数据调用RESTful API,交换数据(如JSON/XML)
中间件/工具JDBC驱动程序HTTP客户端(如HttpClientRestTemplate
典型端口3306 (MySQL), 1433 (SQL Server), 5432 (PostgreSQL)80 (HTTP), 443 (HTTPS)
Java应用与SQL数据库的通信是一个多语言、多协议的世界。JDBC标准提供了统一的编程接口,而其底层的驱动则负责根据数据库类型,自动切换并使用其对应的专属网络协议,如MySQL协议或TDS协议。

十六、Java MySQL 对比 浏览器 → Java后端 (HTTP)

对比点Java → MySQL (JDBC)浏览器 → Java后端 (HTTP)
通信双方Java应用 (JDBC驱动)浏览器 (JS代码) → Java后端 (Spring MVC)
应用层协议MySQL协议 (直接用)HTTP协议 (直接用)
是否有翻译?❌ 没有! 因为双方从设计之初就约定好使用MySQL协议,天生就懂。❌ 也没有! 因为浏览器和Java后端也都原生支持HTTP协议,天生就懂。
那“翻译”在哪?在应用内部:JDBC驱动把Java方法调用转化成MySQL协议数据包。这属于“内部流程”,不是“协议转换”。在后端内部:Spring MVC把HTTP请求里的JSON数据,解析成Java对象。同样属于“内部流程”,不是“协议转换”。
你会发现,真正需要“翻译”的情况,是当通信双方使用完全不同的应用层协议时。 例如,把一个HTTP请求转换成内部微服务能懂的gRPC协议,这才叫协议转换。

十七、JDBC 核心知识一览表

维度具体内容通俗解释
1. 是什么Java数据库连接(Java Database Connectivity),是Java提供的一套标准API,用于让Java程序与各种关系型数据库进行通信。它是Java程序与数据库之间的“通用翻译器”。无论底层是哪种数据库,Java程序都通过这套统一的API来操作,而不用关心每种数据库的“方言”。
2. 核心用途• 建立与数据库的连接
• 发送SQL语句(查询、更新等)
• 接收并处理数据库返回的结果
它是Java程序访问数据库的唯一官方通道。没有它,Java程序就无法操作数据库。
3. 关键组件DriverManager:管理并注册JDBC驱动,负责建立连接。
Connection:代表与特定数据库的物理连接会话。
Statement / PreparedStatement:用于执行SQL语句的对象。
ResultSet:代表查询结果集的数据表。
• DriverManager:像一个出租车调度中心,帮你叫一辆能开往指定数据库(目的地)的“车”(连接)。
• Connection:就是你叫到的那辆“车”,代表你和数据库之间的一个网络连接。
• Statement:是车上的“方向盘”,用来操控“车”(执行SQL)去拿数据。
• ResultSet:是车开回来后,你手里拿到的那份“购物清单”,里面是查询到的数据行。
4. 工作流程1. 注册驱动:加载数据库驱动类。
2. 获取连接:通过DriverManager获取Connection。
3. 创建语句:基于Connection创建Statement/PreparedStatement。
4. 执行查询:执行SQL,获取ResultSet。
5. 处理结果:遍历ResultSet,处理数据。
6. 关闭资源:反向关闭ResultSet、Statement、Connection。
1. 告诉调度中心你要去哪(注册驱动)。
2. 调度中心派一辆车给你(获取连接)。
3. 你手握方向盘(创建语句)。
4. 开车到目的地并执行任务(执行查询)。
5. 你拿到购物清单(处理结果)。
6. 还车、交回方向盘、扔掉清单(关闭资源)。
5. 常用方法• DriverManager.getConnection():建立连接。
• Connection.createStatement():创建普通语句。
• Connection.prepareStatement(sql):创建预编译语句(防SQL注入)。
• Statement.executeQuery(sql):执行查询,返回ResultSet。
• Statement.executeUpdate(sql):执行更新(INSERT/UPDATE/DELETE)。
• ResultSet.next():移动光标到下一行。
• ResultSet.getString("列名"):获取指定列的值。
6. 重要特性• 平台无关:JDBC API是Java标准库的一部分,不依赖特定数据库。
• 数据库无关:通过更换驱动,同一套代码可连接不同数据库。
• 预编译(PreparedStatement):可防止SQL注入,并提升性能。
• 事务支持:支持手动提交和回滚事务。
7. 事务管理• 默认自动提交(每条SQL独立事务)。
• 可通过 connection.setAutoCommit(false) 开启手动事务。
• connection.commit() 提交事务。
• connection.rollback() 回滚事务。
默认是“每办一件事就立刻结账”;手动事务是“办完一系列事,确认无误后统一结账,出问题就全部撤销”。
8. 主要异常SQLException(及其子类),几乎所有JDBC操作都可能抛出此异常。这是JDBC的通用“警报”,表明与数据库通信或操作过程中出现了问题。
9. 最佳实践• 使用PreparedStatement代替Statement,防止SQL注入。
• 在finally块中关闭资源(或使用try-with-resources)。
• 使用连接池(如HikariCP)管理连接,提高性能。
• 妥善处理事务边界
10. 进阶框架MyBatis:半ORM(对象关系映射)框架,灵活控制SQL。
Hibernate / JPA:全ORM框架,以操作对象的方式操作数据库。
Spring Data JPA:在JPA之上进一步简化数据访问层代码。
JDBC是“手动挡”;MyBatis是“自动挡但能随时手动介入”;Hibernate/JPA是“自动驾驶”。
JDBC是Java生态中最基础、最重要的数据库访问技术。它不仅是一门技术,更是一个思想标准——用统一的接口,连接不同的数据库。理解了JDBC,你就明白了Java应用与数据库交互的底层逻辑,这为后续学习任何ORM框架(如MyBatis、Hibernate)都打下了坚实的基础。

十八、Java服务器、Web服务器、数据库的协作关系

浏览器(HTTP)
    ↓
Web服务器(Nginx:接收HTTP请求,转发给Java应用)
    ↓
Java应用服务器(Tomcat/Spring Boot)
    │
    ├── 底层容器:把HTTP请求解析成Java对象(这是翻译)
    ├── Controller:接收Java对象,调用业务逻辑
    ├── Service:执行业务计算
    ├── DAO:通过JDBC驱动,用MySQL协议请求数据库
    ↓
MySQL服务器:执行SQL,返回数据(用MySQL协议)
    ↓
Java应用服务器:把结果封装成JSON/HTML,通过HTTP响应返回给Web服务器/浏览器

浏览器顾客说“我想要一杯拿铁”(发送HTTP请求)
Web服务器(Nginx)前台服务员接待顾客,记录需求,把“拿铁”的指令传给后厨
Java应用服务器后厨接到“做一杯拿铁”的指令(解析后的HTTP请求),按照配方(业务逻辑)制作拿铁(查数据库、计算),把做好的拿铁(结果数据)交给前台
MySQL服务器食材仓库存放原料(数据),后厨需要时去取(执行SQL)

十九、查看 Mysql 版本

# 查看版本(不连接)

mysql --version

# 连接数据库(会提示输入密码)

mysql -u root -p

# 用管道方式导入 SQL(PowerShell 写法)

Get-Content backend/src/main/resources/db/schema.sql | mysql -u root -p mysql_learn

# 或者切换到 cmd 执行(支持 < 重定向)

cmd /c "mysql -u root -p < backend/src/main/resources/db/schema.sql"

二十、查看数据库启动状态

Get-Service -Name "*mysql*" | Format-Table Name, Status, StartType -AutoSize

属性说明
服务名mysqlWindows 系统服务中注册的名称
状态Running服务当前正在运行中,可正常接受连接
启动类型Automatic系统启动时自动启动,无需每次手动开启

二十一、如果后端项目连不上 MySQL,用下面这张表逐项排查

排查项检查方法正常结果异常时的处理
MySQL 服务状态services.msc 查看Running手动启动服务
端口是否监听netstat -ano | findstr 3306显示 LISTENING 状态检查端口占用或 MySQL 配置文件
命令行能否登录mysql -u root -p输入密码后进入 mysql> 提示符检查用户名/密码是否正确
数据库是否存在SHOW DATABASES; 查看结果能看到项目配置的数据库名(如 mysql_learn如果不存在则需要手动创建
连接 URL 是否正确检查 application.yml 中的 urljdbc:mysql://127.0.0.1:3306/数据库名?...核对 IP、端口、数据库名、参数

二十二、Windows 下手动管理 MySQL 服务的命令

22.1、验证是否链接成功

mysql -u root -p -e "SELECT 1"

22.2、启动

# 需要管理员权限的终端

net start mysql

# 不用管理员权限,直接启动 mysqld 进程

"C:\mysql\mysql-9.7.1-winx64\bin\mysqld.exe" --console

# 通过 PowerShell 提权执行

Start-Process powershell -Verb RunAs -ArgumentList "net start mysql"

22.3、停止

net stop mysql

# 通过 PowerShell 提权执行

Start-Process powershell -Verb RunAs -ArgumentList "net stop mysql"

# 通过 Windows 服务管理界面(最简单)
Win + R 输入 services.msc 回车
找到 mysql 服务
右键 → 停止

22.4、重启

# 需要管理员权限的终端

net stop mysql; net start mysql

二十三、数据库怎么链接的 / application-dev.yml

。。

二十四、建表、导数据

CREATE DATABASE 就是创建这个"文件夹"。

文件夹创建好了,里面的表和数据由 schema.sql(建表)和 data.sql(导数据)负责填充。

二十五、修改密码

-- 先登录

mysql -u root -p

-- 登录后执行

ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';

FLUSH PRIVILEGES;

mysql -u root -p -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码'; FLUSH PRIVILEGES;"

二十六、DDL 是啥

DDL 是 Data Definition Language(数据定义语言)的缩写,是 SQL 中用于定义和管理数据库结构的一组命令。

简单说,DDL 就是 "建表、改表、删表" 用的 SQL 语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值