I'm Aron

MySQL 基础(四):用户权限、事务 ACID 与隔离级别

1151 字
6 分钟
MySQL 基础(四):用户权限、事务 ACID 与隔离级别

1. DCL:用户与权限#

用户由“用户名 + 主机”共同标识,例如 'report_user'@'localhost''report_user'@'%' 是两个不同账号。

1.1 用户管理#

-- 查看用户
SELECT User, Host FROM mysql.user;
-- 创建仅允许本机访问的用户
CREATE USER 'report_user'@'localhost'
IDENTIFIED BY '请替换为高强度密码';
-- 修改密码
ALTER USER 'report_user'@'localhost'
IDENTIFIED BY '请替换为新的高强度密码';
-- 删除用户
DROP USER 'report_user'@'localhost';

IDENTIFIED WITH mysql_native_password 是指定认证插件的兼容性写法。没有旧客户端兼容要求时,通常只写 IDENTIFIED BY,让服务器使用默认认证插件。

1.2 权限控制#

-- 查看权限
SHOW GRANTS FOR 'report_user'@'localhost';
-- 仅授予查询权限
GRANT SELECT ON mysql_learn.*
TO 'report_user'@'localhost';
-- 授予多项权限
GRANT SELECT, INSERT, UPDATE ON mysql_learn.emp
TO 'app_user'@'10.%';
-- 撤销权限
REVOKE INSERT, UPDATE ON mysql_learn.emp
FROM 'app_user'@'10.%';

安全原则:

  • 遵循最小权限原则,不轻易授予 ALL PRIVILEGES
  • 生产应用不要使用 root 连接数据库。
  • '%' 表示任意主机,范围很大,应结合网络、防火墙和 TLS 策略谨慎使用。
  • 密码不要写入代码仓库或命令历史,应使用安全的配置和密钥管理方式。

2. 事务#

2.1 事务的作用#

事务是一组不可分割的操作,要么全部成功,要么全部失败。典型场景是转账:付款方扣款和收款方加款必须作为一个整体。

默认情况下,MySQL 通常开启自动提交,每条独立 DML 语句执行后会自动提交:

SELECT @@autocommit;

2.2 基本控制#

推荐显式开启事务:

START TRANSACTION;
UPDATE account
SET money = money - 1000
WHERE id = 1;
UPDATE account
SET money = money + 1000
WHERE id = 2;
COMMIT;
-- 发生异常时执行 ROLLBACK;

也可以修改当前会话的自动提交:

SET SESSION autocommit = 0;
COMMIT;
SET SESSION autocommit = 1;

长期关闭自动提交容易忘记提交或回滚,学习和业务代码中通常更推荐明确的事务边界。

2.3 SAVEPOINT#

保存点可以只回滚事务的一部分:

START TRANSACTION;
UPDATE account SET money = money - 100 WHERE id = 1;
SAVEPOINT after_debit;
UPDATE account SET money = money + 100 WHERE id = 2;
ROLLBACK TO SAVEPOINT after_debit;
RELEASE SAVEPOINT after_debit;
COMMIT;

ROLLBACK TO SAVEPOINT 不会结束整个事务;最终仍需 COMMITROLLBACK

2.4 ACID#

特性含义
Atomicity,原子性事务中的操作要么全部成功,要么全部失败
Consistency,一致性事务前后数据必须满足业务规则和约束
Isolation,隔离性并发事务之间尽量互不干扰
Durability,持久性事务提交后的结果应被持久保存

回滚是原子性的表现;“持久性”主要指提交后的改变。课程原文中“提交或回滚后的改变永久”表述不够严谨,因为回滚的目标是撤销未提交的改变。

2.5 并发事务问题#

问题含义
脏读读到其他事务尚未提交的数据
不可重复读同一事务两次读取同一行,值发生变化
幻读同一事务按相同条件查询,返回的行集合发生变化

2.6 隔离级别#

隔离级别脏读不可重复读幻读(SQL 标准定义)
READ UNCOMMITTED可能可能可能
READ COMMITTED避免可能可能
REPEATABLE READ避免避免可能
SERIALIZABLE避免避免避免

InnoDB 默认使用 REPEATABLE READ,并通过 MVCC、间隙锁等机制处理许多并发场景;具体表现还取决于查询是否为快照读、当前读以及是否使用索引。

-- 查看当前会话隔离级别
SELECT @@transaction_isolation;
-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

隔离级别越高,并发能力通常越低。应根据一致性要求和访问模式选择,而不是简单追求最高级别。

2.7 转账示例的进一步完善#

转账还需要考虑余额不足和并发扣款。可在事务中锁定账户行:

START TRANSACTION;
SELECT id, money
FROM account
WHERE id IN (1, 2)
ORDER BY id
FOR UPDATE;
-- 应用层确认付款方余额充足后再执行
UPDATE account
SET money = money - 1000
WHERE id = 1
AND money >= 1000;
UPDATE account
SET money = money + 1000
WHERE id = 2;
COMMIT;

实践要点:

  • 金额字段使用 DECIMAL,不要使用 DOUBLE
  • 应检查扣款语句影响行数,若为 0 则回滚。
  • 多行加锁时采用一致顺序,可降低死锁概率。
  • 事务尽量短,不要在事务中等待用户输入或执行耗时外部调用。
  • CREATEALTERDROPTRUNCATE 等 DDL 通常会触发隐式提交,不要把它们当成普通 DML 回滚。

评论区

文章目录