1. MySQL数据库操作入门指南
刚接触MySQL时,我经常被各种SQL命令搞得晕头转向。作为最流行的开源关系型数据库,MySQL几乎成了Web开发的标配。但很多新手在使用过程中,常常混淆基础命令,或者不了解不同场景下的最佳实践。今天我就把自己多年积累的MySQL操作经验整理出来,从最基本的增删改查到高级优化技巧,帮你系统掌握这个必备技能。
2. 基础环境准备与连接
2.1 MySQL安装与配置
MySQL的安装根据操作系统不同有所差异。在Ubuntu上可以简单使用apt-get install mysql-server命令完成安装,而Windows用户则推荐下载官方安装包。安装完成后,安全配置是首要任务:
bash复制# 运行安全安装向导
sudo mysql_secure_installation
这个向导会引导你设置root密码、移除匿名用户、禁止root远程登录等安全措施。我强烈建议生产环境一定要完成这些配置,很多数据泄露事件都是因为忽略了基础安全。
2.2 连接MySQL服务器
连接MySQL有多种方式,最常用的是命令行客户端:
bash复制mysql -u username -p
输入密码后就会进入MySQL命令行界面。这里有个实用技巧:使用--prompt参数自定义提示符,能显著提高工作效率:
bash复制mysql -u root -p --prompt="\\u@\\h [\\d]> "
这样提示符会显示用户名、主机名和当前数据库,避免在多个数据库间切换时搞混。
3. 数据库与表的基本操作
3.1 数据库管理
创建和删除数据库是最基础的操作:
sql复制CREATE DATABASE shop;
DROP DATABASE shop;
但实际工作中,我建议总是加上IF EXISTS或IF NOT EXISTS条件判断:
sql复制CREATE DATABASE IF NOT EXISTS shop;
DROP DATABASE IF EXISTS shop;
这可以避免因重复创建或不存在的数据库导致的错误。查看所有数据库用SHOW DATABASES;命令,切换数据库用USE database_name;。
3.2 表结构操作
创建表时需要仔细设计字段类型和约束条件。例如创建一个用户表:
sql复制CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password CHAR(60) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
这里有几个关键点:
- 使用
AUTO_INCREMENT实现自增ID - 为用户名和邮箱添加
UNIQUE约束防止重复 - 密码字段使用固定长度CHAR存储哈希值
- 自动记录创建和更新时间
- 显式指定存储引擎和字符集
修改表结构使用ALTER TABLE命令:
sql复制ALTER TABLE users ADD COLUMN phone VARCHAR(20) AFTER email;
ALTER TABLE users MODIFY COLUMN username VARCHAR(30);
ALTER TABLE users DROP COLUMN phone;
注意:在生产环境修改大表结构可能导致锁表,建议在低峰期操作或使用pt-online-schema-change工具。
4. 数据操作语言(DML)
4.1 插入数据
基础插入语法:
sql复制INSERT INTO users (username, email, password)
VALUES ('john_doe', 'john@example.com', 'hashed_password');
批量插入能显著提高效率:
sql复制INSERT INTO users (username, email, password) VALUES
('user1', 'user1@example.com', 'hash1'),
('user2', 'user2@example.com', 'hash2'),
('user3', 'user3@example.com', 'hash3');
从其他表导入数据:
sql复制INSERT INTO user_backup SELECT * FROM users WHERE created_at < '2023-01-01';
4.2 更新数据
基本更新操作:
sql复制UPDATE users SET email = 'new_email@example.com' WHERE id = 1;
更新多个字段:
sql复制UPDATE users
SET username = 'new_name', email = 'new_email@example.com'
WHERE id = 1;
使用表达式更新:
sql复制UPDATE products SET price = price * 0.9 WHERE category = 'electronics';
警告:忘记加WHERE条件会导致全表更新!建议先写WHERE条件再写SET部分。
4.3 删除数据
删除特定记录:
sql复制DELETE FROM users WHERE id = 1;
清空表数据:
sql复制TRUNCATE TABLE temp_data;
DELETE和TRUNCATE的区别:
- DELETE逐行删除,可加WHERE条件,会触发触发器
- TRUNCATE直接删除表并重建,更快但不记录日志
5. 数据查询语言(DQL)
5.1 基础查询
最简单的查询:
sql复制SELECT * FROM users;
但实际开发中应该避免使用SELECT *,而是明确指定需要的字段:
sql复制SELECT id, username, email FROM users;
添加WHERE条件:
sql复制SELECT * FROM products WHERE price > 100 AND stock > 0;
5.2 高级查询技巧
排序:
sql复制SELECT * FROM products ORDER BY price DESC, name ASC;
分页:
sql复制SELECT * FROM products LIMIT 10 OFFSET 20; -- 第3页,每页10条
聚合函数:
sql复制SELECT
COUNT(*) as total_users,
MAX(created_at) as latest_user,
AVG(age) as average_age
FROM users;
分组统计:
sql复制SELECT
department_id,
COUNT(*) as employee_count,
AVG(salary) as avg_salary
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5;
5.3 多表连接查询
内连接:
sql复制SELECT
o.order_id,
c.customer_name,
o.order_date
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;
左连接:
sql复制SELECT
d.department_name,
e.employee_name
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id;
自连接(查询员工及其经理):
sql复制SELECT
e.employee_name,
m.employee_name as manager_name
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.employee_id;
6. 索引与性能优化
6.1 索引创建与管理
创建普通索引:
sql复制CREATE INDEX idx_username ON users(username);
创建唯一索引:
sql复制CREATE UNIQUE INDEX idx_email ON users(email);
复合索引:
sql复制CREATE INDEX idx_name_age ON employees(last_name, first_name, age);
查看索引:
sql复制SHOW INDEX FROM users;
删除索引:
sql复制DROP INDEX idx_username ON users;
6.2 查询性能分析
使用EXPLAIN分析查询:
sql复制EXPLAIN SELECT * FROM users WHERE username = 'john_doe';
关键指标解读:
- type:从最好到最差依次是 system > const > eq_ref > ref > range > index > ALL
- possible_keys:可能使用的索引
- key:实际使用的索引
- rows:预估需要检查的行数
慢查询日志配置:
sql复制SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 超过1秒的查询
SET GLOBAL slow_query_log_file = '/var/log/mysql/mysql-slow.log';
7. 事务与并发控制
7.1 事务基础
事务的ACID特性:
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
基本事务操作:
sql复制START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
-- 或者出错时 ROLLBACK;
7.2 隔离级别
MySQL支持四种隔离级别:
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ(默认)
- SERIALIZABLE
查看和设置隔离级别:
sql复制SELECT @@transaction_isolation;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
不同隔离级别解决的问题:
- 脏读:READ UNCOMMITTED可能发生
- 不可重复读:READ COMMITTED解决
- 幻读:REPEATABLE READ解决
8. 存储过程与触发器
8.1 存储过程
创建存储过程:
sql复制DELIMITER //
CREATE PROCEDURE transfer_funds(
IN from_account INT,
IN to_account INT,
IN amount DECIMAL(10,2),
OUT status VARCHAR(50)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET status = 'Error occurred';
END;
START TRANSACTION;
UPDATE accounts SET balance = balance - amount WHERE id = from_account;
UPDATE accounts SET balance = balance + amount WHERE id = to_account;
COMMIT;
SET status = 'Transfer successful';
END //
DELIMITER ;
调用存储过程:
sql复制CALL transfer_funds(1, 2, 100, @status);
SELECT @status;
8.2 触发器
创建触发器(记录用户信息变更):
sql复制CREATE TRIGGER before_user_update
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
INSERT INTO user_audit
SET user_id = OLD.id,
changed_field = 'username',
old_value = OLD.username,
new_value = NEW.username,
change_time = NOW();
END;
触发器适用场景:
- 数据审计
- 复杂业务规则验证
- 自动维护衍生数据
9. 备份与恢复
9.1 逻辑备份
使用mysqldump工具:
bash复制# 备份整个数据库
mysqldump -u root -p shop > shop_backup.sql
# 仅备份结构
mysqldump -u root -p -d shop > shop_schema.sql
# 仅备份数据
mysqldump -u root -p -t shop > shop_data.sql
9.2 物理备份
对于InnoDB可以使用MySQL Enterprise Backup或Percona XtraBackup:
bash复制xtrabackup --backup --user=root --password=password --target-dir=/backup/
9.3 恢复数据
从逻辑备份恢复:
bash复制mysql -u root -p shop < shop_backup.sql
时间点恢复(需要binlog):
bash复制mysqlbinlog --start-datetime="2023-01-01 00:00:00" \
--stop-datetime="2023-01-01 12:00:00" \
/var/log/mysql/mysql-bin.000001 | mysql -u root -p
10. 安全最佳实践
10.1 用户权限管理
创建最小权限用户:
sql复制CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE ON shop.* TO 'app_user'@'localhost';
FLUSH PRIVILEGES;
查看用户权限:
sql复制SHOW GRANTS FOR 'app_user'@'localhost';
10.2 数据加密
透明数据加密(TDE):
sql复制CREATE TABLE sensitive_data (
id INT PRIMARY KEY,
credit_card VARBINARY(255)
);
INSERT INTO sensitive_data VALUES (1, AES_ENCRYPT('4111111111111111', 'encryption_key'));
SELECT id, AES_DECRYPT(credit_card, 'encryption_key') FROM sensitive_data;
10.3 SQL注入防护
使用预处理语句(PHP示例):
php复制$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username');
$stmt->execute(['username' => $inputUsername]);
$user = $stmt->fetch();
永远不要直接拼接SQL:
php复制// 危险!容易导致SQL注入
$sql = "SELECT * FROM users WHERE username = '$inputUsername'";