文章目录
- 一、什么是事务?
- [二、ACID 四大特性](#二、ACID 四大特性)
-
- [1. Atomicity(原子性)](#1. Atomicity(原子性))
- [2. Consistency(一致性)](#2. Consistency(一致性))
- [3. Isolation(隔离性)](#3. Isolation(隔离性))
- [4. Durability(持久性)](#4. Durability(持久性))
- 三、为什么要使用事务
- [四、MySQL 事务应用](#四、MySQL 事务应用)
-
- [1. 基本语法](#1. 基本语法)
- [2. 转账案例](#2. 转账案例)
-
- [① 事务提交:数据永久修改](#① 事务提交:数据永久修改)
- [② 事务回滚:数据回到最初](#② 事务回滚:数据回到最初)
- [3. 保存点 savepoint](#3. 保存点 savepoint)
- [4. 自动提交 / 手动提交](#4. 自动提交 / 手动提交)
- 五、事务的隔离性与隔离级别
-
- [5.1 什么是隔离性](#5.1 什么是隔离性)
- [5.2 隔离级别](#5.2 隔离级别)
- [5.3 不同隔离级别存在的问题](#5.3 不同隔离级别存在的问题)
-
- [1. 脏读 Dirty Read](#1. 脏读 Dirty Read)
- [2. 不可重复读 Non-Repeatable Read](#2. 不可重复读 Non-Repeatable Read)
- [3. 幻读 Phantom Read](#3. 幻读 Phantom Read)
- [5.4 查看 / 设置 隔离界别](#5.4 查看 / 设置 隔离界别)
- 六、用户权限管理
-
- [6.1 为什么要做用户与权限管理?](#6.1 为什么要做用户与权限管理?)
- [6.2 用户基础操作](#6.2 用户基础操作)
-
- [1. 查看所有用户](#1. 查看所有用户)
- [2. 创建用户](#2. 创建用户)
- [3. 修改密码](#3. 修改密码)
- [4. 删除用户](#4. 删除用户)
- [6.3 权限管理:授权与回收](#6.3 权限管理:授权与回收)
-
- [1. 常用权限](#1. 常用权限)
- [2. 授权语法](#2. 授权语法)
- [4. 回收权限](#4. 回收权限)
- [6.4 标准流程](#6.4 标准流程)
一、什么是事务?
事务就是把一组 SQL 打包成一个不可分割的整体:要么全部成功,要么全部失败,允许只执行一半。
举个例子:银行转账
张三给李四转 100 元需要两步:
- 张三余额 -100
- 李四余额 +100
如果第一步成功、第二步失败,钱就"凭空消失"了。
事务就是用来杜绝这种灾难的。
二、ACID 四大特性
事务之所以可靠,全靠 ACID 四大特性保驾护航:
1. Atomicity(原子性)
- 要么全成功,要么全回滚
- 中途出错、宕机、异常,都像没执行过一样
- 对应操作:
ROLLBACK
2. Consistency(一致性)
- 事务前后,数据库完整性约束不被破坏
- 例如转账前后总金额不变、数据合法、约束有效
这是业务最终追求的目标
3. Isolation(隔离性)
- 多个事务同时跑,互相不干扰
- 防止并发下的数据错乱:脏读、不可重复读、幻读
- 通过隔离级别控制安全与性能
4. Durability(持久性)
- 事务一旦提交,修改永久落盘
- 就算数据库崩溃、重启,数据也不会丢
原子性保证操作不半途而废,一致性保证结果正确,隔离性保证并发不乱,持久性保证数据不丢。
三、为什么要使用事务
事物具备的ACID特性,就是使用事务的原因,在日常的业务场景中有大量的需求要用事务来保证。
支持事物的数据库能够简化编程模型,不需要去考虑各种而样的钱砸错误和并发问题,在使用事务的过程中,要么提交,成功修改,就可以安全的保存,要么回滚,恢复到事务之初。不需要考虑网络异常,服务器宕机等其他因素。
我们经常接触的事务本质上是数据库对ACID模型的一个实现,是为应用层服务的。
四、MySQL 事务应用
MySQL 里只有 InnoDB 支持事务,MyISAM 不支持
sql
show engines;
可以查看MySQL中支持的存储引擎

transactions显示yes,表明InnoDB支持事务
1. 基本语法
sql
-- 开启事务
start transaction; -- 或 begin;
-- 执行 SQL:insert/update/delete...
-- 提交:永久生效
commit;
-- 回滚:全部撤销
rollback;
- 开启一个事务之后,sql语句就包含在事务之中,这些sql语句都具有ACID特性。
- 提交后就会落盘,不允许回滚,但是可以再修改。
- 无论提交还是回滚事务都会关闭。
2. 转账案例
建表:
sql
create table account(
id bigint primary key auto_increment,
name varchar(20),
balance decimal(5,2)
);
insert account values
(1,"张三",1000.00),
(2,"李四",1000.00);
① 事务提交:数据永久修改
sql
start transaction;
update account set balance = balance + 100 where name = "张三";
update account set balance = balance - 100 where name = "李四";
commite;
执行后:张三 1100,李四 900,永久生效。
② 事务回滚:数据回到最初
sql
start transaction;
update account set balance = balance + 100 where name = "张三";
update account set balance = balance - 100 where name = "李四";
rollback;
执行后:数据完全没变,回到最初状态。
3. 保存点 savepoint
事务太长,可以设置"检查点",回滚到指定位置:
sql
start transaction;
-- 操作1
savepoint sp1;
-- 操作2
savepoint sp2;
-- 回滚到 sp1
rollback to sp1;
-- 回滚全部,关闭事务
rollback;
适合调试、批量操作、分步撤销。
4. 自动提交 / 手动提交
MySQL 默认 自动提交(每条 SQL 自成事务):
sql
-- 查看
show variables like 'autocommit';
-- 关闭自动提交(手动控制)
set autocommit = 0;
-- 开启自动提交
set autocommit = 0;

显示on,表示自动提交已打开,可以手动设置为关闭。
注意:
- 只要使用
begin / start transaction开启事务,就必须使用commit / rollback才能结束事务。 - 手动提交模式下,不会显示开启事务,但是需要手动
commit / rollback来结束事务 - 自动提交打开时,一个事务只包含一个DML语句
DML语句是指update,insert,delete等数据操作语言 - DDL 语句会强制提交事务
DDL语句是对库、表、结构做定义、修改、删除的数据定义语言
如果在事务里执行create database / create table / alter table/ drop table这类 DDL,事务会被自动提交,后面的 SQL 就不在这个事务里了,也无法回滚前面的操作。 - 设置手动提交,如果重启电脑会恢复成自动提交,如果想要永久设置成手动提交,可以在配置文件中修改
五、事务的隔离性与隔离级别
5.1 什么是隔离性
MySQL服务可以同时被多个客户端访问,每个客户端执行的DML语句是以事务为单位,那么不同的客户端都同一张表的同一条数据进行修改的时候可能出现相互影响的情况。
为了保证不同的事务之间执行过程不受影响,那么事物之间需要相互隔离,这种特性就是隔离性
5.2 隔离级别
事物的隔离级别描述了事务之间的隔离程度。
不同的隔离级别在性能和安全方面做了取舍,有的隔离界别注重并发性,有的注重安全性,有的则是安全与并发适中。
在MySQL的InnoDB引擎中事务的隔离界别有四种,安全性逐渐增强,性能逐渐减弱:
- read uncommitted,读未提交
- read committed,读已提交
- repeatable read,可重复读(默认)
- serializable,串行化
5.3 不同隔离级别存在的问题
多个事务同时跑,会出现 3 种经典数据错乱:
1. 脏读 Dirty Read
事务A读到事务B没提交的数据,如果事务B回滚,事务A读到的就是"假数据"。
2. 不可重复读 Non-Repeatable Read
在同一个事务A内,多次读取同一行数据,期间数据被另一个已提交的事务B修改,导致多次读取结果不一致。这种现象就是不可重复读
3. 幻读 Phantom Read
同一个事务内,两次范围查询条数不一样。InnoDB 用 Next-Key 锁,锁住了目标行和之前的"间隙",解除了部分幻读问题
serializable 串行化解决了所有数据安全问题,所有事务一个挨一个执行,同时效率也是最低的。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
| READ UNCOMMITTED(读未提交) | ✅ 有 | ✅ 有 | ✅ 有 | 最快 |
| READ COMMITTED(读已提交) | ❌ 无 | ✅ 有 | ✅ 有 | 快 |
| REPEATABLE READ(可重复读) | ❌ 无 | ❌ 无 | ✅ 有 | 中等 |
| SERIALIZABLE(串行化) | ❌ 无 | ❌ 无 | ❌ 无 | 最慢 |
5.4 查看 / 设置 隔离界别
sql
-- 全局作用域
select @@global.transaction_isolation;
-- 局部作用域
select @@session.transaction_isolation
-- 设置会话级别
set session transaction isolation level read committed;

六、用户权限管理
在实际开发中,数据库绝对不能所有人都用 root 账号乱操作。用户隔离 + 权限控制是安全的第一道防线。
6.1 为什么要做用户与权限管理?

- root 是超级管理员,权限太大,不安全
- 一个项目对应一个库、一个专用用户
- 有的用户只能读,有的能读写,互不干扰
- 防止误删库、误改数据、越权访问
6.2 用户基础操作
MySQL 的用户信息存在 mysql 库的 user 表中。
1. 查看所有用户
sql
use mysql;
select host, user, authentication_string from user;
- host:允许登录的地址(白名单)
- user:用户名
- authentication_string:加密密码
2. 创建用户
sql
CREATE USER '用户名'@'允许登录地址' IDENTIFIED BY '密码';
常用示例:
sql
-- 只能本机登录
CREATE USER 'test'@'localhost' IDENTIFIED BY '123456';
-- 允许 192.168.1.x 网段登录
CREATE USER 'test'@'192.168.1.1/24' IDENTIFIED BY '123456';
注意:
localhost:只能本机连%:任何地址都能连(生产环境禁止用)
3. 修改密码
sql
-- root 给别人改密
ALTER USER 'bit'@'localhost' IDENTIFIED BY '987654';
-- 自己改自己密码
SET PASSWORD = '111111';
4. 删除用户
sql
DROP USER 'bit1'@'192.168.1.1/24';
6.3 权限管理:授权与回收
新建用户默认没有任何权限,只能看见系统库,必须手动授权。
1. 常用权限
SELECT:查询INSERT:插入UPDATE:更新DELETE:删除ALL [PRIVILEGES]:所有权限USAGE:没权限(默认)
2. 授权语法
sql
GRANT 权限 ON 库.表 TO '用户'@'地址';
常用示例:
sql
-- 给 test 用户授权 java01 库所有表的 查询权限
GRANT SELECT ON java01.* TO 'test'@'localhost';
-- 给 test 用户授权 java01 库所有权限(增删改查)
GRANT ALL ON java01.* TO 'test'@'localhost';
授权后需要刷新:
sql
FLUSH PRIVILEGES;
``
### 3. 查看用户权限
```sql
SHOW GRANTS FOR 'test'@'localhost';
4. 回收权限
sql
-- 回收所有权限
REVOKE ALL ON *.* FROM 'test'@'localhost';
FLUSH PRIVILEGES;
6.4 标准流程
sql
-- 1. 创建专用用户(本机登录)
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'App@123456';
-- 2. 授权指定库的所有权限
GRANT ALL ON mydb.* TO 'appuser'@'localhost';
-- 3. 刷新权限
FLUSH PRIVILEGES;
-- 4. 查看权限
SHOW GRANTS FOR 'appuser'@'localhost';
-- 5. 回收(不需要时)
REVOKE ALL ON *.* FROM 'appuser'@'localhost';
FLUSH PRIVILEGES;
-- 6. 删除用户
DROP USER 'appuser'@'localhost';