1. MySQL数据库基础与核心概念
MySQL作为最流行的开源关系型数据库管理系统,已经成为Web应用开发的标准配置。我第一次接触MySQL是在2010年一个电商项目上,当时就被它简洁高效的特性所吸引。经过十多年的发展,MySQL在性能、可靠性和功能丰富度上都有了显著提升,但它的核心操作逻辑——增删改查(CRUD)却始终保持一致。
1.1 关系型数据库的基本原理
关系型数据库的核心是表(table)结构,数据以行(row)和列(column)的形式组织。每张表就像Excel中的一个工作表,行代表记录,列代表字段。与Excel不同的是,MySQL通过严格的字段类型定义和约束条件来保证数据完整性。
主键(Primary Key)是表中唯一标识每条记录的字段或字段组合。一个好的主键设计应该满足三个条件:唯一性、非空性和不可变性。我见过太多项目因为使用业务字段(如用户名)作为主键而后悔莫及,最佳实践是使用自增整数或UUID这类与业务无关的值。
1.2 MySQL的安装与配置
虽然标题聚焦于增删改查,但合理的安装配置是基础。根据我的经验,90%的MySQL问题都源于不当的安装配置。以Linux(Ubuntu)为例,推荐使用官方仓库安装:
bash复制sudo apt update
sudo apt install mysql-server
sudo mysql_secure_installation
安装后有几个关键配置需要调整:
- 字符集设置为utf8mb4以支持完整Unicode(包括emoji)
- 调整innodb_buffer_pool_size(通常设为物理内存的70-80%)
- 设置合理的max_connections(根据应用负载)
提示:生产环境务必修改默认root密码,并创建专用应用账号,避免使用root账号连接应用。
1.3 连接MySQL的几种方式
作为开发者,我们主要通过三种方式与MySQL交互:
- 命令行客户端:
mysql -u username -p - 图形化工具:MySQL Workbench、DBeaver等
- 编程语言驱动:JDBC、PDO、mysql2等
我强烈建议初学者从命令行开始,这能帮助你真正理解MySQL的工作机制。图形化工具虽然方便,但容易掩盖底层细节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据库与表的基本操作
2.1 数据库的创建与管理
创建数据库是最基础的操作,但有几个细节需要注意:
sql复制CREATE DATABASE shop
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
这里显式指定了字符集和排序规则,避免了后续可能出现的中文乱码问题。我曾经接手过一个项目,因为使用默认的latin1字符集,导致大量中文数据无法正确存储。
查看已有数据库:
sql复制SHOW DATABASES;
删除数据库(谨慎操作):
sql复制DROP DATABASE shop;
2.2 表的创建与设计规范
创建表时需要考虑字段类型、约束和索引。以下是一个用户表的创建示例:
sql复制CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password CHAR(60) NOT NULL COMMENT '存储bcrypt哈希',
email VARCHAR(100) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_email (email)
) ENGINE=InnoDB;
几个设计要点:
- 使用自增主键id
- 用户名和邮箱添加UNIQUE约束
- 密码存储使用CHAR(60)以适应bcrypt哈希
- 自动维护创建和更新时间
- 为email字段添加索引提高查询效率
注意:VARCHAR和CHAR的区别在于前者是变长存储,后者是定长。密码哈希长度固定,适合用CHAR。
2.3 表结构的修改
随着业务发展,表结构经常需要调整。ALTER TABLE语句可以完成这些操作:
添加新列:
sql复制ALTER TABLE users ADD COLUMN phone VARCHAR(20) AFTER email;
修改列定义:
sql复制ALTER TABLE users MODIFY COLUMN phone VARCHAR(15);
删除列:
sql复制ALTER TABLE users DROP COLUMN phone;
重命名表:
sql复制ALTER TABLE users RENAME TO customers;
3. 数据的增删改查操作
3.1 插入数据(INSERT)
最基本的插入操作:
sql复制INSERT INTO users (username, password, email)
VALUES ('john_doe', '$2a$10$xJw...', 'john@example.com');
批量插入更高效:
sql复制INSERT INTO users (username, password, email) VALUES
('user1', '$2a$10$...', 'user1@example.com'),
('user2', '$2a$10$...', 'user2@example.com'),
('user3', '$2a$10$...', 'user3@example.com');
插入时处理冲突(MySQL特有语法):
sql复制INSERT INTO users (username, password, email)
VALUES ('john_doe', '$2a$10$...', 'john@example.com')
ON DUPLICATE KEY UPDATE
password = VALUES(password),
updated_at = NOW();
3.2 查询数据(SELECT)
基础查询:
sql复制SELECT * FROM users;
条件查询:
sql复制SELECT username, email FROM users WHERE created_at > '2023-01-01';
排序和分页:
sql复制SELECT * FROM users
ORDER BY created_at DESC
LIMIT 10 OFFSET 20; -- 获取第3页,每页10条
聚合查询:
sql复制SELECT
COUNT(*) as total_users,
DATE(created_at) as signup_date
FROM users
GROUP BY DATE(created_at)
HAVING COUNT(*) > 5;
3.3 更新数据(UPDATE)
基础更新:
sql复制UPDATE users SET email = 'new_email@example.com' WHERE id = 1;
批量更新:
sql复制UPDATE products SET price = price * 0.9 WHERE category = 'electronics';
使用JOIN更新:
sql复制UPDATE orders o
JOIN users u ON o.user_id = u.id
SET o.status = 'cancelled'
WHERE u.email = 'inactive@example.com';
3.4 删除数据(DELETE)
基础删除:
sql复制DELETE FROM users WHERE id = 1;
批量删除:
sql复制DELETE FROM log_records WHERE created_at < '2022-01-01';
清空表(不可恢复):
sql复制TRUNCATE TABLE temp_data;
4. 高级查询与性能优化
4.1 多表连接查询
内连接(只返回匹配的行):
sql复制SELECT o.order_id, u.username, o.amount
FROM orders o
INNER JOIN users u ON o.user_id = u.id;
左连接(返回左表所有行):
sql复制SELECT u.username, COUNT(o.order_id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id;
自连接(同一表内连接):
sql复制SELECT e.name, m.name as manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;
4.2 子查询与派生表
WHERE子句中的子查询:
sql复制SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);
FROM子句中的派生表:
sql复制SELECT c.name, o.order_count
FROM customers c
JOIN (
SELECT customer_id, COUNT(*) as order_count
FROM orders
GROUP BY customer_id
) o ON c.id = o.customer_id;
4.3 索引优化实战
查看表索引:
sql复制SHOW INDEX FROM users;
添加索引:
sql复制ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);
删除索引:
sql复制ALTER TABLE orders DROP INDEX idx_user_status;
EXPLAIN分析查询:
sql复制EXPLAIN SELECT * FROM users WHERE username = 'john_doe';
4.4 事务与锁机制
基本事务:
sql复制START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
-- 如果出错可以 ROLLBACK;
设置隔离级别:
sql复制SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
5. 实战经验与常见问题
5.1 批量操作的最佳实践
处理大量数据时,单个INSERT插入万条记录会导致锁表时间过长。我的经验是分批处理,每批500-1000条:
python复制# Python示例
batch_size = 500
for i in range(0, len(data), batch_size):
batch = data[i:i + batch_size]
execute_batch_insert(batch)
time.sleep(0.1) # 给数据库喘息时间
5.2 敏感数据的安全处理
密码存储必须使用哈希算法如bcrypt,绝对不要明文存储。在MySQL 8.0+中可以使用:
sql复制CREATE USER 'app_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'secure_password';
5.3 备份与恢复策略
定期备份至关重要。我常用的mysqldump命令:
bash复制mysqldump -u root -p --single-transaction --routines --triggers \
--all-databases > full_backup.sql
对于大型数据库,可以考虑物理备份工具如Percona XtraBackup。
5.4 性能监控与调优
几个关键指标需要监控:
- 慢查询:
long_query_time = 1并开启慢查询日志 - 连接数:
SHOW STATUS LIKE 'Threads_connected' - 缓存命中率:
SHOW STATUS LIKE 'Innodb_buffer_pool_read%'
我常用的优化技巧:
- 为常用查询添加合适的复合索引
- 避免SELECT *,只查询需要的列
- 对大表分页使用"延迟关联"技术
5.5 字符集与编码问题
中文乱码是最常见的问题之一。确保:
- 数据库、表和连接都使用utf8mb4
- 连接字符串指定字符集:
jdbc:mysql://...?useUnicode=true&characterEncoding=utf8 - 应用服务器和客户端也使用UTF-8编码
我曾经花费两天时间排查一个乱码问题,最终发现是应用服务器默认编码设置错误。
