事务:
据说是面试中容易被考的一个概念。有时需要结合例子去向面试官说清楚自己对事务的四大特性的理解。
事务的四大特性 ACID:
1.原子性 atomicity
2.一致性 consistency
3.隔离性 isolation
4.持久性 durability
原子性:
这个针对于 一个事务 而言。一个事务中可能包含很多的 “操作” 。
这些 “操作” 产生的结果 有2种 :要么 全部执行成功,要么 全部执行失败。 不存在一部分成功 一部分失败的情况。
一致性:
针对于一个事务中。
一个事务 执行的结果 必须是使 数据库 从一个 一致性状态 变到另一个一致性状态。
什么是“一致性状态”?
当数据库只包含 成功事务 提交的结果时,就说数据库 处于一致性状态。
还是拿 A,B两个人转账的陈年例子来说明:
一开始 A和B分别有1000元,他俩的钱的和为2000元。
事务开始了:
A: 原本1000元 转账成功的话: 剩1000-200=800元 转账失败的话: A还是1000元
原本总共2000元 成功的话,A+B依然=2000元 失败的话,A+B也依然=2000元
B: 原本1000元 转账成功的话:剩1000+200=1200元 转账失败的话: B也还是1000元
隔离性:
针对于 事务 与 事务 之间。
还有一个大前提: 隔离级别足够高
在并发操作中(即很多事务同时进行着),不同事务之间是不会相互干扰到的。
eg:事务A 去访问数据库,它看到的数据库中的资源 要么是被其他事务 增删改 之前的样子;
要么是已经被其他事务 增删改 之后的样子。
别的事务的增删改的过程 事务A是看不到的。
持久性:
持久性,指的是 持久保存数据。
如果把数据存在内存中,这不叫持久保存数据,因为当浏览器/服务器关闭了,内存就释放了,内存中的数据也就没了。
但当数据库 存数据时,把数据以文件的形式 存放在硬盘上,那么就实现了数据的持久保存。
eg:
开启事务:A给B转账200元。
A 原有 1000元 给B转200: 1000-200=800 (如果最后成功commit了,数据库中记录这个过程的日志 就会 记录下来 :成功后 我就把 A 的钱更新为800元 )
B 原有 1000元 接收到200 : 1000+200=1200 (如果最后成功commit了,数据库中记录这个过程的日志 就会 记录下来: 成功后 我就把 B的钱更新为1200元 )
结束事务:回滚(会把日志删除)/成功提交(会修改日志中的内功)
额外的:
开启事务:start transaction
结束事务:commit (提交事务)
rollback (回滚事务)--可理解为 操作们被 撤回了。
再额外的:
事务并发读时 会存在的问题:
脏读:当一个数据库的隔离级别设置为最低时,可能会发生。
eg:A开启事务,给B转100元,但没commit。这时B开启事务,查到钱多了100元。
如果 A 使坏,rollback了这100元。 那么B 查钱时 查到的就是 “脏数据”!
脏读 结果很严重 ,作为一个数据库 一定要避免 脏读。
不可重复度: 在一个事务A中,对同一记录的两次读取结果不一致,因为在两次查询的间隙时间,另一个事务B 对数据库中的记录 做了修改 (针对修改操作)。
eg:
事务A:开启事务---
第一次读取账户W的金额:1000
(此时:另一头的事务B 开启了----从账户W中取走100元,账户W中剩900元,并且commit)
第二次又查了一次账户W的金额:900了
幻读(虚读):在一个事务A中,对同一张表的两次查询结果 不一致,因为在两次查询的间隙时间,另一个事务B 对这个表中,插入/删除了 记录 (针对 插入/删除)。
eg:
事务A:开启事务
第一次 看一个学生名单时 是: 喜羊羊,美羊羊,懒羊羊
(此时:另一头的事务B 开启了事务,往这个学生名单中 插入了一个 灰太狼 ,并且commit了 )
第二次 再看这个学生名单时 变成了:喜羊羊,美羊羊,懒羊羊, 灰太狼。---仿佛出现了幻觉~~
事务的隔离级别:
1.READ UNCOMMITTED (读 未提交的数据)
安全性最差,但性能最好 (不使用!!!)
2.READ COMMITTED (读 已提交的数据)
安全性较差,性能较好 (Oracle 数据库 默认是这种)
3.REPEATABLE READ (可重复读)
安全性较高,性能较差 (MySQL 数据库 默认是这种)
4.SERIALIZABLE (串行化)
安全性最高,性能最差。(不使用!)(eg:去大食堂吃饭,需要A吃完 从食堂出来,B才能进去吃饭)
拓展:
MySQL查询当前事务的隔离级别:
select @@tx_isolation;