MySQL事务学习

事务重点知识

什么是事务?

数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合。事务在执行的过程中,不会被其他客户端发送的命令请求所打断。

事务四大特性(ACID)

原子性:事务是最小的执行单位,要么全成功,要么全失败。

一致性:事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
如果数据库系统运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库的话,这时数据库就处于一种不正确的状态,或者说不一致的状态。

隔离性:一个事务内部的操作及使用的数据对其他并发事务是隔离性的,多个事务并发执行时,一个事务的执行不影响其他事务的执行。
四种隔离级别:RU(读未提交)、RC(读已提交)、RR(可重复读)、SERIALIZABLE (串行化)

持续性:事务提交后,对数据的修改是永久性的,即使系统故障也不会丢失。

事务的并发问题,什么是脏读?幻读?不可重复读?

脏读: 当前事务可以读到其他事务未提交的数据(脏数据)

不可重复读: 事务两次读同一个数据,数据不同。

  • 脏读与不可重复读的区别:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据。

幻读: 事务两次读同一条数据,条数不同。 例如有一个事务查询了几列(row)数据,而另一个事务却在此时插入了新的几列数据,之前的事务在接下来的查询中,就会发现有几列数据是它先前没有的。

  • 不可重复的与幻读的区别:前者是数据变了,后者是数据的行数变了。
  • 不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

事务的隔离级别

读未提交: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读、不可重复读。

读已提交: 允许读取并发事务已经提交的数据,可以阻止脏读,但可能发生幻读或不可重复读。

可重复读: mysql默认隔离级别 。对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但仍可能发生幻读。

可串行化: 最高隔离级别,完全服从ACID。所有的事务依次逐个执行,事务之间不可能产生干扰,可以防止脏读、不可重复读、幻读。

  • MySQL默认采用可重复读隔离级别,Oracle默认采用读已提交。
  • 事务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的是MVVC(多版本并发控制),通过保存修改的旧版本信息来支持并发一致性读和回滚等特性。
  • 隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是读已提交,但是InnoDB使用的是可重复读。
  • InnoDB引擎在分布式事务的情况下一般会用到可串行化隔离级别。什么是分布式事务?

在这里插入图片描述

如何实现ACID

深入学习MySQL事务:ACID特性的实现原理
原子性: 实现原子性的关键是当事务回滚时能够撤销所有已经成功执行的sql语句。InnoDB实现回滚靠的是undo log :当事务对数据库进行修改时,InnoDB会生成对应的undo log ;如果事务执行失败或调用了 rollback, 导致事务需要回滚,便可以利用undo log 中的信息将数据回滚到修改之前的样子。

一致性:

  1. 保证原子性、持久性和隔离性,如果这些特性无法保证,事务的一致性也无法保证
  2. 数据库本身提供保障,例如不允许向整形列插入字符串值、字符串长度不能超过列的限制等
  3. 应用层面进行保障,例如如果转账操作只扣除转账者的余额,而没有增加接收者的余额,无论数据库实现的多么完美,也无法保证状态的一致

隔离性: 各个隔离级别原理各不相同

持久性: MySQL事务的持久性是通过redo log来实现的。redo log也是InnoDB存储引擎特有的。具体实现方式是:当数据修改时,除了修改Buffer Pool中的数据,还会在redo log记录这次操作;当事务提交时,会调用fsync接口对redo log进行刷盘。如果MySQL宕机,重启时可以读取redo log中的数据,对数据库进行恢复。redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到Buffer Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。
redo log是物理日志,记录的是在某个数据页做了什么修改,而不是SQL语句的形式。它有固定大小,是循环写的方式记录日志,空间用完后会覆盖之前的日志。

隔离级别实现原理

读未提交(READ UNCOMMITTED): 读不会加任何锁,写会加排它锁,并到事务结束之后释放。实例:写-写:阻塞

读已提交(READ COMMITTED): InnoDB在该隔离级别下写数据时,使用排它锁,读取数据不加锁而是使用了MVCC机制。在读已提交的级别下,都会通过MVCC获取当前数据的最新快照,不加任何锁,也无视任何锁(因为历史数据是构造出来的,身上不可能有锁)。
但是该级别下存在不可重复读和幻读问题:MVCC版本的生成时机是每次select时。这意味着如果我们在事务A中执行多次的select,在每次select之间有其他事务更新了我们读取的数据并提交了,那就出现了不可重复读。

可重复读(REPEATABLE READ): 可重复读级别不同的是MVCC版本的生成时机。 即:一次事务中只在第一次select时生成版本,后续的查询都在这个版本上进行,从而实现可重复读。
不能彻底解决。MVCC对于幻读的解决并不彻底,只解决了读情况下的幻读问题,而写操作依旧存在幻读问题

原因:

  • select读操作是快照读的模式,会记录下这次select的结果,之后select 返回的也是这次快照的数据。此时其他事务提交的数据无影响。
  • update、insert、delete写操作是当前读的模式,会记录最新的结果。此时其他事务提交的数据有影响

解决方法:

  • MVCC+next-key locks
  • 使用可串行化读的隔离级别

可串行化(SERIALISABLE): 完全使用读锁和写锁保证数据一致性。针对同一数据的所有读写都变成互斥,可靠性大大提高,并发性大大降低。

参考

  • https://blog.csdn.net/qq_42914528/article/details/103790555
  • https://www.jianshu.com/p/dab1c0ecbac0
  • https://www.cnblogs.com/kismetv/p/10331633.html
  • https://www.cnblogs.com/huanongying/p/7021555.html
  • https://blog.csdn.net/qq_43255017/article/details/106442887
  • https://blog.csdn.net/suchahaerkang/article/details/81407308
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL事务是一组关联的SQL操作,它们被看作是一个整体,要么全部执行成功,要么全部回滚。事务具有四个ACID属性:原子性、一致性、隔离性和持久性。 首先,原子性意味着事务中的所有操作要么全部成功执行,要么全部回滚。如果事务中的一个操作发生错误,会导致整个事务回滚到之前的状态。 其次,一致性表示事务执行完毕后,数据库将会进入一个有效的状态。在事务开始之前和结束之后,数据库的完整性约束必须得到保持,确保数据的正确性。 隔离性是指每个事务的操作在执行过程中是相互隔离的,不会互相干扰。事务并发执行时可能会出现的问题包括脏读、不可重复读和幻读。为了解决这些问题,数据库系统提供了四个隔离级别:未提交读取、已提交读取、可重复读取和串行化。 最后,持久性是指一旦事务被提交,对数据库的修改将会永久保存,即使在系统故障的情况下也是如此。数据库系统通过将事务的日志记录到磁盘上来实现持久性。 在MySQL中,可以使用START TRANSACTION语句来开始一个事务,COMMIT语句来提交一个事务,ROLLBACK语句来回滚一个事务。此外,可以使用事务控制语句来设置隔离级别,如SET TRANSACTION ISOLATION LEVEL。要保证事务的正确性和性能,还应注意事务的边界,避免事务嵌套过深。 深入学习MySQL事务需要理解事务的四个ACID属性以及MySQL事务控制语句。此外,还需要了解事务的隔离级别,以便在并发执行的情况下避免数据不一致的问题。掌握MySQL事务的概念和操作方法,可以保证数据库操作的一致性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值