事务

本文深入探讨了数据库事务的四大特性:原子性、一致性、隔离性和持久性,详细解释了这些特性的实现机制,包括redo和undo日志、MVCC、重做日志和回滚段的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事务的原子性:

原子性是指整个数据库事务是不可分割的工作单位,只有事务中所有的数据库操作执行都成功,才算真正的成功,如果事务中任何一个sql语句执行失败,那么已经执行成功的sql语句也必须撤销

数据库的状态应该回滚到执行事务前的状态

一致性:

指事务将数据库从一种状态转变为下一种一致的状态,在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏

 

隔离型

一个事务的影响在该事务提交前对其他事务都不可见–通过锁实现

 

 

持久性

事务一旦提交,其结果就是永久性的,即使发生宕机等故障,数据库也能将数据回复

 

隔离型是通过锁实现,而原子性,一致性,持久性通过数据库的redo 和undo来完成

MVCC

         Mysql中MVCC是在Innodb存储引擎中得到支持的,Innodb为每行记录都实现了三个隐藏字段:
         DB_TRX_ID:  6字节的事务ID, 用来标识该行所述的事务。

         DB_ROLL_PTR: 7字节的回滚指针。

         DB_ROW_ID:隐藏的ID,随着数据的增加而增加。

 

redo

当数据库对数据进行修改的时候,需要把数据也从磁盘读到buffer pool中,然后在buffer pool中进行修改,那么这个时候buffer pool中的数据页就遇磁盘上的数据页内容不一致,称buffer pool中的数据页为dirty page

脏数据,如果这个时候发生非正常的DB服务重启,那么这些数据还在内存,没有同步到磁盘文件中,也就会发生数据丢失,如果这个时候能够再有一个文件,当buffer pool中的的data page 变更结束后,把相应修改记录到这个文件,这个文件就是redo log,御用记录数据修改后的记录,顺序记录,它可以带来这些好处:

当buffer中的数据直接flush到disk file,是一个随机io ,效率太差,而把buffer pool中的数据记录到redo log,是一个顺序io,可以提高事务提交的速度

 

假设修改 tba 表中 id=2的行数据,把Name='B' 修改为Name = 'B2' ,那么redo日志就会用来存放Name='B2'的记录,如果这个修改在flush 到磁盘文件时出现异常,可以使用redo log实现重做操作,保证事务的持久性。

IdName
1A
2B
3C
4

D

 

    这里注意下redo log 跟binary log 的区别,redo log 是存储引擎层产生的,而binary log是数据库层产生的。假设一个大事务,对tba做10万行的记录插入,在这个过程中,一直不断的往redo log顺序记录,而binary log不会记录,直到这个事务提交,才会一次写入到binary log文件中。binary log的记录格式有3种:row,statement跟mixed,不同格式记录形式不一样。

 

 

重做日志

undo log  

重做日志记录了事务的行为,可以很好的通过其进行“重做” 但是事务有时还需要撤销,这时候就需要undo,undo与redo正好相反,对于数据库进行修改时,数据库不但会产生redo,而且还会产生undo

即使你事务或语句由于某种原因失败了,或者如果你用一条 ROLLBACK语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子,与redo不同的是,redo存放在重做日志文件中,undo存放在数据库内部的以特殊(segment)中,这称为undo段(undo segment)

 

 

segment

        回滚段这个概念来自Oracle的事物模型,在Innodb中,undo log被划分为多个段,具体某行的undo log就保存在某个段中,称为回滚段。可以认为undo log和回滚段是同一意思。

 

 

可能我们有这样的误解,undo用于将数据库物理的恢复到执行语句或事务之前的样子,数据库还是逻辑地恢复到原来的样子,所有修改都被逻辑的取消,但是数据结构本身在回滚之后可能大不相同,印在在多用户并发系统中,可能会有数十。数百甚至数千个并发事务,数据库的主要任务就是协调对于数据记录的并发访问,如一个事务在修改当前一个页中的几条记录,但同时还有背的事务在对同一个页中另几条记录进行修改。不能将一个页回滚到事务开始的样子,因为这样会影响其他事务正在的工作

 

当insert的时候 InnoDB会完成一个DELETED

当delete的时候 InnoDB会完成一个INSERT

当update InnoDB完成一个相反的update

 

update事务的过程

 

 

进行了如下的操作:

用排他锁锁定该行

记录redo log

把秀改前的值copy到unlog 即上图中下面的行

修改当前行的值,填写事务编号,使回滚指针指向undo log中修改前的行

 

与事务1相同,此时undo log中有两行记录,并且通过回滚指针连在一起。

因此,如果undo log一直不删除,则会通过当前记录的回滚指针回溯到该行创建时的初始内容,所幸的是在Innodb中存在purge线程,它会查询那些比现在最老的活动事务还早的undo log,并删除它们,从而保证undo log文件不至于无限增长。

Insert 事务

       当insert时,原始的数据并不存在,所以回滚时把insert undo log丢弃即可,而update undo log则必须遵守上述过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值