MySQL事物记录

编程入门 行业动态 更新时间:2024-10-09 03:19:05

MySQL<a href=https://www.elefans.com/category/jswz/34/1759949.html style=事物记录"/>

MySQL事物记录

  • 事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。

1、事务的四大特性(ACID)

1.1、原子性(Atomicity)

原子性是指事务包含的一系列操作要么全部成功,要么全部回滚,不存在部分成功或者部分回滚,是一个不可分割的操作整体(这个侧重点是事务执行的完整)。

利用InnoDB的undo log(回滚日志)记录需要回滚的日志信息,是实现原子性的关键,当事务回滚时能够撤销所有已经成功执行的sql语句

例如:

delete一条数据的时候,就会记录这条数据的曾经的信息,回滚的时候,insert这条旧数据

update一条数据的时候,就会记录之前的旧值,回滚的时候,根据旧值执行update操作

insert一条数据的时候,就会这条记录的主键,回滚的时候,根据主键执行delete操作

undo log记录了这些回滚需要的信息,当事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

1.2、一致性(Consistency)

数据库总是从一种一致性状态转换到另一种一致性状态,有非法数据时,事务回滚,任何事务处理过程中所做的数据改变,也不会影响到数据库的内容。

一致性是要保证操作前和操作后数据或者数据结构的一致性,关注数据的中间状态,也就是一致性需要监视中间状态的数据,如果有变化,即刻回滚。

一致性是基础,也是最终目的,其他三个特性(原子性、隔离性和持久性)都是为了保证一致性的。    

1.3、隔离性(Isolation)

隔离性是指当多个用户并发操作数据库,比如操作同一张表,数据库为每一个用户开启的事务,不能被其他的事务所干扰或者影响,事务之间是彼此独立的,如果有变化,即刻回滚(隔离性是多个事务的时候,事务之间感知不到彼此的存在,就好像只存在本身一个事务一样, 相互不能干扰)。

1.4、永久性(Durability)

永久性是指一个事务一旦提交了,那么对数据库中数据的改变就是永久的,即使是在数据库发生故障时,也不会丢失事务提交的数据。

PS:一致性和原子性的区别

原子性和一致性的的侧重点不同:

原子性关注状态,要么全部成功,要么全部失败,不存在部分成功的状态。

而一致性关注数据的可见性,中间状态的数据对外部不可见,只有最初状态和最终状态的数据对外可见。

2、InnoDB如何保证这些事务特性的

  • redo log重做日志用来保证事务的持久性
  • undo log回滚日志保证事务的原子性
  • undo log+redo log保证事务的一致性
  • 锁(共享、排他)用来保证事务的隔离性

2.1、重做日志 redo log

重做日志 redo log 分为两部分:

一部分是内存中的重做日志缓冲(redo log buffer),是易丢失的;

二部分是重做日志文件(redo log file),是持久的,redo log日志的大小是固定的,即记录满了以后就从头循环写。

InnoDB通过Force Log at Commit机制来实现持久性,当commit时,必须先将事务的所有日志写到重做日志文件进行持久化,待commit操作完成才算完成。

InnoDB在下面情况下会将重做日志缓冲的内容写入重做日志文件:

  • master thread 每一秒将重做日志缓冲刷新到重做日志文件;
  • 每个事务提交时
  • 当重做日志缓冲池剩余空间小于1/2时

为了确保每次日志都写入重做日志文件,在每次将日志缓冲写入重做日志文件后,InnoDB存储引擎都需要调用一次fsync(刷盘)操作。但这也不是绝对的。用户可以通过修改
innodb_flush_log_at_trx_commoit参数来控制重做日志刷新到磁盘的策略,这个可以作为大量事务提交时的优化点。

  • 1参数默认值,表示事务提交时必须调用一次fsync操作。
  • 0表示事务提交时,重做日志缓存并不立即写入重做日志文件,而是随着Master Thread的间隔进行fsync操作。
  • 2表示事务提交时将重做日志写入重做日志文件,但仅写入文件系统的缓存中,不进行fsync操作。
  • fsync的效率取决于磁盘的性能,因此磁盘的性能决定了事务提交的性能,也就是数据库的性能。所以如果有人问你如何优化Mysql数据库的时候别忘了有硬件这一条,让他们提升硬盘配置,换SSD固态硬盘
  • 重做日志都是以512字节进行存储的,称之为重做日志块,与磁盘扇区大小一致,这意味着重做日志的写入可以保证原子性,不需要doublewrite技术。它有以下3个特性:

       1、重做日志是在InnoDB层产生的

       2、重做日志是物理格式日志,记录的是对每个页的修改

       3、重做日志在事务进行中不断被写入,而且是顺序写入

2.2、回滚日志 undo log

为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为Undo Log),然后进行数据的修改。如果出现了错误或者用户执行了 ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。

undo log实现多版本并发控制(MVCC)来辅助保证事务的隔离性。

回滚日志不同于重做日志,它是逻辑日志,对数据库的修改都逻辑的取消了。当事务回滚时,它实际上做的是与先前相反的工作。对于每个INSERT,InnoDB存储引擎都会完成一个DELETE;对于每个UPDATE,InnoDB存储引擎都会执行一个相反的UPDATE。

事务提交后并不能马上删除undo log,这是因为可能还有其他事务需要通过undo log 来得到行记录之前的版本。故事务提交时将undo log 放入一个链表中,是否可以删除undo log 根据操作不同分以下2种情况:

  • Insert undo log: insert操作的记录,只对事务本身可见,对其他事务不可见(这是事务隔离性的要求),故该undo log可以在事务提交后直接删除。不需要进行 purge操作。
  • update undo log:记录的是对 delete和 update操作产生的 undo log。该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待 purge线程进行最后的删除。

undolog和redolog

undo日志用于记录事务开始前的状态,用于事务失败时的回滚操作;

redo日志记录事务执行后的状态,用来恢复未写入data file的已成功事务更新的数据。

例如某一事务的事务序号为T1,其对数据X进行修改,设X的原值是5,修改后的值为15,那么Undo日志为<T1, X, 5>,Redo日志为<T1, X, 15>。

redolog和binlog

redo log是物理日志,是数据页面的修改之后的物理记录。

binlog是逻辑日志,可以简单认为记录的就是sql语句。

2.3、

事务的隔离性的实现原理就是锁,因而隔离性也可以称为并发控制、锁等。事务的隔离性要求每个读写事务的对象对其他事务的操作对象能互相分离。再者,比如操作缓冲池中的LRU列表,删除,添加、移动LRU列表中的元素,为了保证一致性那么就要锁的介入。

锁的类型

InnoDB主要有2种锁:行级锁,意向锁

行级锁:

  • 共享锁(读锁 S),允许事务读一行数据。事务拿到某一行记录的共享S锁,才可以读取这一行,并阻止别的事务对其添加X锁。共享锁的目的是提高读读并发。
  • 排它锁(写锁 X),允许事务删除一行数据或者更新一行数据。事务拿到某一行记录的排它X锁,才可以修改或者删除这一行。排他锁的目的是为了保证数据的一致性。

行级锁中,除了S和S兼容,其他都不兼容。

意向锁:

  • 意向共享锁(读锁 IS ),事务想要获取一张表的几行数据的共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
  • 意向排他锁(写锁 IX),事务想要获取一张表中几行数据的排它锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

3、事务的隔离性

事务的隔离性。当多个线程开启事务操作数据库中的数据时,数据库要能进行隔离操作,以保证各个线程获取数据的准确性; 如果不考虑事务的隔离性,会发生以下几个问题;

3.1、脏读

脏读是指一个事务在处理过程中读取了另一个事务未提交的数据。比如,A向B转账

update account set money = money + 100 where name = 'B';
update account set money = money - 100 where name = 'A' 

当只执行第一条SQL时,A通知B查看账户,B发现确实钱已到账(此时即发生了脏读),
而之后无论第二条SQL是否执行,只要该事务不提交,则所有操作都将回滚,那么当B以后再次查看账户时就会发现钱其实并没有转

3.2、不可重复读

  • 不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
  • 例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发生了不可重复读。
  • 不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
  • 在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如对于同一个数据A和B依次查询就可能不同,A和B就可能打起来了……

3.3、幻读

幻读是事务非独立执行时发生的一种现象。
例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)

PS:不可重复读和幻读的区别

1) 不可重复读的重点是修改:

同样的条件, 你读取过的数据, 再次读取出来发现值不一样了

"不可重复读" 是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。


2)幻读的重点在于新增或者删除:

同样的条件, 第1次和第2次读出来的记录数不一样

幻觉读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。

4、MySQL的隔离级别

隔离级别的概念,就是为了解决脏读、幻读和不可重复读的问题(这些问题,其实就是导致无法保证一致性的几种情况)

4.1、未提交读(read uncommited)

在这个隔离级别中,在一个事务执行的操作就算不提交也能被其他的事务看到。在这个级别中一个事务可能读到其他事务还没提交的脏数据,即可能出现脏读

4.2、读已提交(Read committed )

在一个事务提交之后,其他事务才可以看到事务的修改。此隔离级别可能会出现同一个事务中执行相同的查询却读到不同的数据, 即不可重复读nonrepeatable read),另未提交读也可能出现不可重复读。

4.3、可重复读(repeatable read)

 这是MySQL的默认隔离级别在事务开始的时候会保存此刻的一个快照(这里啰嗦一下,实际上是开启事务后执行第一条语句的时   候准备的快照,准备快照的方法则是记录当前事务的版本号,没有进行数据的复制,不明白事务版本号或隐藏字段的可以看   看 MySQLMVCC),然后接下来这个事务的所有数据读取都是从这个快照读,所以不会出现不可重复读的情况,但是还是有可能   出现幻读。

4.4、可串行化(serializable)

意思就是事务要一个一个来,如果在一个事务中进行读操作,那么其他事务在该事务完成前只能进行读操作;如果进行写操作,那么其他事务的操作都进入等待(直到当前事务提交)。这种级别就可以防范目前出现的脏读、不可重复读、幻读等现象。

MVCC 只在 读已提交、可重复读两种隔离级别工作
如何实现的呢? 增加版本号
insert 保存当前事物的系统版本号
delete  存放当前系统版本号,作为删除标记
update 原数据:插入一行新数据版本号为系统版本号。旧数据 存放当前系统版本号,作为删除标记
select 1.仅仅查找版本号小于等于当前事物版本号的数据2.行的删除版本要么未定义,要么大于当前事物版本号。PS:MVCC在一定程度上解决了幻读,(但,如果 先 commit  create ,当A线程执行更新对应的语句后,再次select 依旧会出现幻读)在实现上,数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准。
在“可重复 读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。 
在“读提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的。
这里需要 注意的是:“读未提交”隔离级别下直接返回记录上的最新值,没有视图概念;
而“串行 化”隔离级别下直接用加锁的方式来避免并行访问。

文章参考自:

MySQL事务的四大特性和隔离级别 - 风中的蜗牛 - 博客园

粗谈MySQL事务的特性和隔离级别 - 张小云的博客 - 博客园

今日头条

更多推荐

MySQL事物记录

本文发布于:2024-02-14 00:40:59,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1761172.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:事物   MySQL

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!