达永编程网

程序员技术分享与交流平台

【MySQL篇】事务和四个主要特征的认知

何为事务?

事务(Transaction)是指一组操作的集合,这些操作要么全部执行成功,要么全部不执行。事务通常用于保证数据库的一致性、完整性和可靠性,确保数据的完整性与正确性。

有效地避免了因“不完全”或“不完全”而产生的各种问题;

引入例子:

假设以下场景: 转账
第一步A用户转账给B用户100元 账户-100



第二步B用户收到A转账100元 账户+100



如果在这个时候,因为一些原因,比如网络故障、主机关闭、 MySQL服务器崩溃等,造成了第二步无法进行,那么就会造成很大的损失,比如 A莫名其妙地少了100个点,这是绝对不能允许的。

此时由于是俩个操作,所有MySQL会将这俩个操作打包成一个操作(原子性),要么一起完成,要么都不完成。

如果在执行过程中出现了一个不正常的情况,那么这个动作就会被“回滚”。所有操作将会被撤销。

附加: MySQL在 MySQL的日志中记录了每个步骤,因此可以基于日志来恢复。

在 MySQL 中,事务是由多个 SQL 语句组成的一个操作单元,要么所有的操作都成功执行(提交,commit),要么在发生错误时,所有操作都不执行(回滚,rollback)。通过事务,MySQL 能够提供更强的错误恢复能力,并保证数据库在并发访问时的一致性。

事务的四大特性:

事务有四个核心特性,通常被称为 ACID 特性:原子性(Atomicity),一致性(Consistency),持久性(Durability),隔离性(Isolation);

原子性:

在上述操作中,将多个操作打包成一个操作时,此时代表这个操作具有“原子”的,原子就是以前最小的单位,不可拆分。

事务中的操作要么全部成功,要么全部失败。原子性确保了事务是最小的执行单位,无法再分割。即使在事务执行的过程中发生故障,数据库也会通过回滚操作使事务的状态恢复到事务开始之前。

一致性:

在执行事务开始前后,要保证数据是一致的,不会出现对不上的情况。一旦触发“回滚”操作,也要保证回滚回去的数据跟原来一样;

事务执行前后,数据库的状态必须从一个一致的状态转变到另一个一致的状态。所有事务都必须遵循数据库的完整性约束,如主键、外键等,确保数据的完整性和准确性。

持久性:

一旦事务提交,它对数据库的更改是永久性的,即使发生系统崩溃或断电,提交的事务所做的更改也会保留下来。

隔离性:

在并发环境下,多个客户端同时对服务器发起事务请求,一个事务的执行不应受到其他事务的干扰。每个事务应该像是在独占数据库一样执行,直到它提交或回滚。

事务的四大特性:

事务有四个核心特性,通常被称为 ACID 特性:原子性(Atomicity),一致性(Consistency),持久性(Durability),隔离性(Isolation);

原子性:

在上述操作中,将多个操作打包成一个操作时,此时代表这个操作具有“原子”的,原子就是以前最小的单位,不可拆分。

事务中的操作要么全部成功,要么全部失败。原子性确保了事务是最小的执行单位,无法再分割。即使在事务执行的过程中发生故障,数据库也会通过回滚操作使事务的状态恢复到事务开始之前。

一致性:

在执行事务开始前后,要保证数据是一致的,不会出现对不上的情况。一旦触发“回滚”操作,也要保证回滚回去的数据跟原来一样;

事务执行前后,数据库的状态必须从一个一致的状态转变到另一个一致的状态。所有事务都必须遵循数据库的完整性约束,如主键、外键等,确保数据的完整性和准确性。

持久性:

一旦事务提交,它对数据库的更改是永久性的,即使发生系统崩溃或断电,提交的事务所做的更改也会保留下来。

隔离性:

在并发环境下,多个客户端同时对服务器发起事务请求,一个事务的执行不应受到其他事务的干扰。每个事务应该像是在独占数据库一样执行,直到它提交或回滚。

脏读:

脏读指的是一个事务读取了另一个事务尚未提交的数据。这可能会导致读取到不一致的数据,因为另一个事务可能回滚,使得当前事务读取的数据变得无效。

例子:

假设有一场随堂考试,小明(学渣)抄袭小强(学霸)的试卷(这种行为是不好的,只是比喻),此时小强写完了试卷给小明抄,小明写着写着写完了之后,小明就直接提交试卷了。但小强在检查试卷的时候,发现检查试卷的时候很多答案填错了,那么小强肯定将答案改正了回来 ,而小明吃了大亏,心里想我*****,还不如自己写...................

核心在于:当小强不仅写完试卷,并且还检查完毕,确保不会修改的情况下,小明再去抄写他的答案,不然都可能出错

解法方法:

当事务B查看事务A(写操作)的数据时候,将事务A的数据进行“加锁”,此时事务B不能查看A的数据,必须等待事务A确定下来,才可以查看。

这就相当于降低了 "并发能力",也就降低了数据库服务器的处理效率,提高了 '隔离性' ,也提高了数据的准确性。在并发执行事务过程中,相互之间是互相影响的,彼此的影响越小,隔离性越高;反之影响越大,隔离性越低。

不可重复读

在上述基础上,我们已经把写操作加上锁,这就意味着读操作的事务不能中途查询,以免没有查询到最终结果。

例子:

当我们写博客的时候,此时读者必须等我们发布完成之后,才能阅读我们的博客。

假设我们写完已经发布了 这是事务A

然后读者去查看博客的内容 这是事务B

当我们发布完 我们还觉得内容需要修改一下 可能存在一点问题 又进行发布了 这是事务C

问题出现在事务B此时在读数据的时候,此时我们事务C也执行了,假设博客页面刷新了,事务B发现此时读到的数据跟刚才读到的数据不一样,这就是不可重复读问题;

解法:

在事务B读操作的时候 ,我们也不能执行事务C,必须等事务B执行完之后,才能修改数据,也就是说在“读数据”的时候也不能“写数据”;

所以对事务B读操作也加上“锁”,就可以保证事务 B 前后两次读取的数据都是一致的。

脏读和不可重复读的区别:

脏读关注的是一个事务读取另一个事务未提交的数据,且这个数据可能最终会被回滚,因此它是不可靠的。

不可重复读关注的是同一个事务内,在多次读取同一数据时,数据发生了变化(通常是由于其他事务的提交),导致读取结果不一致。

幻读:

幻读是指一个事务在查询数据时,其他事务可能插入、删除或修改记录,导致该事务查询的数据集发生变化,即查询结果出现"幻象"。在一个事务中,查询的结果集在不同的查询操作之间可能不一致。

例子:

刚才约定对读和写操作进行加上锁。

事务A发布第一篇博客

事务B在查询博客的内容

此时我们并不修改第一篇博客的内容,闲着也是闲着,于是我们继续写了新的一篇博客,第二篇博客。 事务C在B再一次查询的时候,发现了多出来了一篇博客,此时就是幻读。

解法:

当读者在阅读博客的时候,叫我们啥事别做了,好好休息,简单来说,就是一个事务一个事务来,在执行事务的时候,不要执行任何操作;

实现串行化操作,此时没有并发了,因此效率最低,并且也是隔离性最高的,数据是最准确的。

隔离性的隔离级别:



总结

脏读、不可重复读和幻读都是由于并发事务互相干扰所导致的问题。为了避免这些问题,可以选择合适的事务隔离级别:

读未提交:出现脏读,不可重复读,幻读。

读已提交:防止脏读,但可能会出现不可重复读和幻读。

可重复读:防止脏读和不可重复读,但可能会出现幻读。

串行化:完全避免所有并发问题,但性能最差。



控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言