概述
MySQL 事务主要用于处理操作量大, 复杂度高的数据. 比如说, 在人员管理系统中, 你删除一个人员, 你既需要删除人员的基本资料, 也要删除和该人员相关的信息, 如信箱, 文章等等, 这样, 这些数据库操作语句就构成一个事务.
在 MySQL 中只有使用了 InnoDB 数据库引擎的数据库或表才支持事务.
事务处理可以用来维护数据库的完整性, 保证成批的 SQL 语句要么全部执行, 要么全部不执行.
事务用来管理 insert,update,delete 语句
事务必须满足 4 个条件(ACID): 原子性(Atomicity, 或称不可分割性), 一致性(Consistency), 隔离性(Isolation, 又称独立性), 持久性(Durability).
原子性: 一个事务中的所有操作, 要么全部完成, 要么全部不完成, 不会结束在中间某个环节.
一致性: 在事务开始之前和事务结束以后, 数据库的完整性没有被破坏. 在事务执行前后状态都必须是稳定的.
隔离性: 事务之间不会相互影响. 数据库允许多个并发事务同时对其数据进行读写和修改的能力, 隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致. 事务隔离分为不同级别, 包括读未提交 (Read uncommitted), 读提交(read committed), 可重复读(repeatable read) 和串行化(Serializable).
持久性: 事务处理结束后, 对数据的修改就是永久的, 即便系统故障也不会丢失.
事务的控制语句
begin: 显式地开启一个事务;
commit: 提交事务. 使对数据库进行的所有修改成为永久性的;
rollback: 回滚事务. 撤销正在进行的所有未提交的修改;
savepoint savepoint_name: 在事务中创建一个保存点, 一个事务可有多个. 是在数据库事务处理中实现 "子事务"(subtransaction) , 也称为嵌套事务的方法. 事务可以回滚到 savepoint 而不影响 savepoint 创建前的变化, 不需要放弃整个事务.
rollback to savepoint_name: 事务回滚到标记点
release savepoint savepoint_name: 删除一个事务的保存点. 当没有指定的保存点, 则抛出异常.
set transaction: 设置事务的隔离级别.(InnoDB 存储引擎提供事务的隔离级别有 READ UNCOMMITTED,READ COMMITTED,REPEATABLE READ 和 SERIALIZABLE.)
MySQL 事务处理主要有两种方法:
1. 用 begin,rollback,commit 来说来实现
BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT 事务确认
2. 直接用 set 来改变 MySQL 的自动提交模式
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交
事务的隔离级别
先谈谈事务之间不是相互隔离, 可能出现的 3 个问题: 脏读, 不可重复读, 幻读
1. 脏读(dirty read)
简单来说, 就是一个事务在处理过程中读取了另外一个事务未提交的数据.
举例
B 事务并没有提交, A 事务便看到 B 事务修改的数据.
2. 不可重复读(non-repeatable read)
指一个事务范围内, 多次查询某个数据, 却得到不同的结果.
举例
A 事务第一次查询之后, B 事务进行修改数据, 此时 A 事务看到的还是原来的数据;
当 B 事务提交后, A 事务看到的是 B 事务所提交修改的数据. 但对于 A 事务来说, 什么都没做, 却得到两个结果, 有点吓人.
脏读是某一事务读取了另外一个事务未提交的数据, 不可重复读是读取了其他事务提交的数据.
其实, 有些情况下, 不可重复读不是问题, 比如, 小编提现期间, 一分钱被老婆支走了, 这不是问题!
而脏读, 是可以通过设置隔离级别避免的.
3. 幻读(phantom read)
事务非独立执行时发生的一种现象.
举例
其实上面的解释已经是一个例子了, 但是还是要举个例子.
比如, 小编准备提取你打赏的一分钱, 提取完了, 这时又有其他热心网友打赏了一分钱, 小编一看, 明明已经取出了, 怎么又有一分钱!?
小编此时以为像做梦一样, 我觉得也可以叫「梦读」, 哈哈.
幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),
所不同的是不可重复读查询的都是同一个数据项, 而幻读针对的是一批数据整体(比如数据的个数).
MySQL 的隔离性的隔离级别有四个
1. 读未提交: read uncommitted
最低的事务隔离级别, 一个事务还没提交时, 它做的变更就能被别的事务看到
2. 读已提交: read committed
保证一个事务提交后才能被另外一个事务读取. 另外一个事务不能读取该事务未提交的数据. 可避免脏读的发生, 当可能会造成不可重复读.
3. 可重复度: repeatable read 默认级别
多次读取同一范围的数据返回第一次查询的快照, 即使其他事务对该数据做了更新的修改. 事务在执行期间看到的数据前后必须是一致的.
但如果这个事务在读取某个范围内的记录时, 其他事务又在该范围内插入了新的记录, 当之前的事务再次读取该范围的记录时, 会产生幻行, 这就是幻读.
4. 串行化: serializable
花费最高代价但最可靠的事务隔离级别.
"写" 会加 "写锁","读" 会加 "读锁". 当出现读写锁冲突的时候, 后访问的事务必须等前一个事务执行完成, 才能继续执行. 事务 100% 隔离, 可避免脏读, 不可重复读, 幻读的发生.
通过一个表格, 总结各个隔离级别的情况
通过一个简单的例子, 解释四个隔离级别.
再次总结
读未提交: 别人改数据的事务尚未提交, 我在我的事务中也能读到.
读已提交: 被人改数据的事务已经提交, 我在我的事务中才能读到.
可重复读: 别人改数据的事务已经提交, 我在我的事务中也不去读.
串行: 我的事务尚未提交, 别人就别想改数据.
这 4 种隔离级别, 并行性能依次降低, 安全性依次提高.
总的来说, 事务隔离级别越高, 越能保证数据的完整性和一致性, 但是付出的代价却是并发执行效率的低下.
参考: https://www.baidu.com/link?url=tHE7vbyxkdAkVQjm68IxaiAlqZnwOaI8Z8sxOsSZx5yfIhpvGg4dO15edVzz8S_RFRYDaBohgv1JT4ZZuof6t_&wd=&eqid=8805de0c0000aa0c000000025e22b86d
来源: http://www.bubuko.com/infodetail-3386586.html