数据库事务到底是什么?

目录

场景(两个用户之间进行转账操作):

 需要的操作步骤:

事务

事务的四大特性:

一、原子性

(1)什么是回滚操作

(2)数据库恢复操作,如何知道数据恢复如初?(如何知道数据回滚正确)

 二、一致性

 三、持久性 

 四、隔离性(重点)

1. 脏读

 解决脏读:

2. 不可重复读

 解决不可重复读:

3. 幻读

 解决幻读:

4. 区分不可重复读和幻读

总结并发处理事务的三个典型问题:

MySQL内置的机制(对应上述几种隔离级别)


前言

    数据库事务的相关知识也是面试常考的问题,这篇文章介绍为什么要有事务以及事务的概念,事务的特性,以及数据库基于隔离性(特性)产生并发执行所引出的问题,如何解决这个问题。

场景(两个用户之间进行转账操作):

    用户A要给用户B进行转账,就要操作数据库中的数据表;如下图:

 需要的操作步骤:

(1)update acccount set balance = balance - 500 where id = 1;

(2)update account set balance = balance + 500 where id = 2;

     假设在执行转账的过程中,执行完sql语句(1)之后,数据库崩溃了/主机宕机了,此时用户1的钱扣了,但是2的钱没到账。

    那针对这样的问题数据库该如何解决?

事务

    事务就是为了解决上述问题,事务的本质就是把多个sql语句给打包成一个整体,要么全部执行成功,要么就一个都不执行,而不会出现 ”执行一半“ 这样的中间状态。(这就是事务出现的初心)

事务的四大特性:

1. 原子性(回滚)上述 ”一点都补执行“ 不是真正的没有执行,而是在中间状态进行了 ”回滚“ 操作
2. 一致性

数据进行修改之后,要和之前的数据能够对应上。

3. 持久性数据持久保存
4.隔离性(重点介绍)这个特性是为了解决事务 ”并发执行“ 引起的问题

一、原子性

    原子性是数据库设计事务的初心,这点要清楚,上述场景出现后,事务就是为了解决这个问题,

事务的本质就是把多个要执行的sql语句打包成一个整体,使事务变成要执行的一个基本单位,不能再分。(要么就不执行这个事务,要么就一次执行完事务)

(1)什么是回滚操作

    当一个事务执行到一半时,此时数据库崩溃了,数据库在下一次启动时就要把未执行完的数据恢复到之前的状态,这个恢复数据的操作,称为 ”回滚“。

  注:上述 ”事务要么一点都不执行“,不是真正的没有执行,而是说看起来好像没有执行一样,事务执行一半,数据库崩溃,数据库再次启动后,此时选择恢复数据,就是把未执行完的数据还原成了未执行之前的状态了。

 (2)数据库恢复操作,如何知道数据恢复如初?(如何知道数据回滚正确)

    数据库中有专门记录事务的日志,用日志来记录事务的操作步骤。日志就是写到磁盘上的文件,断电之后,日志也不会消失,所以数据库重新启动后,就把数据进行正确的恢复。

    注:正因如此,使用事务后,执行sql语句的开销也就更大了,效率也更低了。

 二、一致性

         执行sql语句前后的数据要能够保证正确性。

    数据执行的前后,数据时靠谱的,也就是能够和正确的操作数据能够对应上,如:用户1给用户2转账500,此时2的账户上就多了500,不能多出来5000,50000。

    没有引入事务的时候,这个 特性就是要必须保证的,有了事务之后,这个特性也不能丢失。

 三、持久性 

    事务修改的内容是写到硬盘上的,持久存在的,数据库重启之后,也能保证数据没有丢失。

    还是转账这个场景,此时如果数据库崩溃之后,所有的用户的余额都是保存在数据库中的,此时不能说数据库崩了,用户的钱也跟着一起没了,这是不靠谱的,所以说数据库中的数据是持久保存的。

 四、隔离性重点

    解决事务 “ 并发”执行引起的问题。

    注:数据库是客户端服务器这样的一个结构,数据库也是服务器;就有可能出现多个客户端同时提交给数据库多个事务,此时数据库就需要并发处理多个事务。

    如果是修改的同一张表中的同一个数据,此时就有可能出现问题,如:多个客户尝试对同一个账户进行转账操作,就有可能把这个数据搞乱。

    并发执行事务可能产生的问题:

(1)脏读问题
(2)不可重复读问题
(3)幻读问题

1. 脏读

    一个事务 正在对数据进行修改的过程中,还没有提交数据之前,另外一个事务B也对同一个数据进行读取,此时B的读数据操作称为 “脏读”,读到的数据也是称为 “脏数据”,(脏的意思是无效,就是读到的数据是无效的数据)

 解决脏读:

    mysql引入“给读操作加锁” 的机制   

(多线程中同步锁问题,详解可以看这篇文章:锁策略和 cas 优化过程_良月初十♧的博客  )

加锁之后写操作和读操作就不能并发执行了(不能同时进行),给写操作加锁,就降低了并发的程度(也降低了效率),提高了隔离性(提高了数据的准确性)。

2. 不可重复读

    事务1已经提交了数据,此时事务2开始去读数据,在读的过程中,事务3又提交了新的数据,此时意味着同一个事务2之内,多次读数据读出来的结果是不一样的(预期是一个事务中,多次读取的结果是一样的),此时就称为 “不可重复读”。

 解决不可重复读:

    给读操作也进行加锁,通过给读加锁,又进一步降低了事务的并发处理能力(处理效率也降低),提高事务的隔离性(数据的准确性又提高了)。

3. 幻读

    在给读和写数据加锁的前提下,一个事务两次读取同一个数据,发现读取的数据内容是一样的,但是结果集不一样,此时称为 “幻读”。

 解决幻读:

    数据库使用串行化的方式来解决幻读,彻底放弃并发执行,一个接着一个的串行的处理事务,此时并发程度是最低的(效率是最慢的),隔离性是最高的(数据的准确性也是最高的)。

4. 区分不可重复读和幻读

    不可重复读是指事务多次读取数据,预期读到的数据内容是一样的,但是结果是多次读取数据,数据的内容是不一样的。

    而幻读是指一个事务多次读取数据,预期是读到的数据是一样多的,没有新数据集的产生,但是结果是一个事务多次读取数据,内容虽然是一样的,但是在原有的基础上多了一部分结果集。

总结并发处理事务的三个典型问题:

1. 脏读问题给读加锁
2. 不可重复读问题给写加锁
3. 幻读彻底执行串行化

MySQL内置的机制(对应上述几种隔离级别)

1. read uncommitted读未提交,没有进行任何话锁限制并发最高(效率最高),隔离性最低(数据的准确性最低)在处理并发事务时,同时有脏读,不可重复读,幻读问题。
2. read committed读已提交,给写加锁了,并发程度 降低,隔离性提高了(数据准确性提高)解决了脏读问题,但是不可重复读和幻读问题还存在。

3. repeatable read

可重复读,给读进行加锁,并发程度进一步降低,隔离性进一步提高(这也是Mysql 默认事务隔离级别)解决了不可重复读问题,但是幻读问题还存在。
4. serializable事务串行化,并发程度最低,隔离性最高此时不存在上述三个问题,数据的准确性也是最高的

    可以通过修改MySQL的配置文件来设置当前MySQL是工作在哪种情况下。

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良月初十♧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值