MYSQL如何实现事务?

首先,我们需要了解事务的特性

1.原子性:即不可分割性,事务的操作要么全部执行,要么全部不执行

2.一致性:事务在开始之前到结束之后,数据库都是一致的状态。即,事务将数据库从一个一致状态转换到另一个一直状态

3.隔离性:确保并发执行后,各个事务之间互补干扰,独立执行

4.持久性:事务一旦执行完成,会将其结果永久的保存在数据库中

那么事务的特性是如何实现的呢?

在这次笔者主要分为两个模块进行介绍

1.事务的隔离级别

2.日志文件undo log和redo log  (保证原子性、持久性、一致性)

首先,事务的隔离性是通过隔离级别来实现的,这里有时会被叫做并发事务问题

1.读未提交

顾名思义,在该隔离级别中,所有的事务都可以读取到其他事务未提交的数据。这里的安全性是极差的,同时也会带来脏读的问题。

脏读问题:一个事务读取到了另一个事务未提交的数据

2.读已提交

一个事务在执行过程中,只能查询到其他事务已经提交了的更改,天然的避免了脏读问题,但是也引出了新的问题,不可重复度和虚度问题,这是因为一个事务可以看别的事务已经提交了的数据,就可能导致多次读取同一条数据时,该数据可能被其他事务所修改,导致第一次读取和后面读取的数据不一致。

不可重复读:一个事务内,多次读取同一数据时,由于其他事务的修改导致每次读取的结果不一致

虚度:一个事务中,查询结果集被其他事务的插入或者删除操作所改变

3.可重复读

MYSQL的默认隔离级别,他确保了一个事务中多个实例在并发读取数据的时候会读取到一样的数据,但存在幻读问题。

幻读:当用户对某一范围内的数据行时,另一个事务又在该范围内插入了一个新行,用户再次读取就会发现有新的幻影行

4.MVCC(多版本并发控制)

通过保持数据的不同版本来提高并发性能,从而避免了多个事务对同一数据的直接竞争

1.多版本存储:不同事务读取不同版本

2.锁机制独立:不适用锁的情况提供并发控制,提高系统性能

3.事务隔离级别:MVCC主要时读已提交和可重复读

4.innoDB实现:通过保存数据行的版本号来实现

MVCC的执行原理

全程Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突。

MVCC是如何保证数据的多个版本的呢?

首先,记录中是有一些隐藏字段的

  1. DB_TRX_ID:最近修改事务id,记录插入这条数据或最后一次修改该记录的事务ID。
  2. DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本
  3. DB_ROW_ID:隐藏主键,如果表结构没有指定主键,将会生成隐藏字段

然后,这里就用到了undo log日志文件

undo log:回滚日志,在insert,update,delete的时候产生的便于数据回滚的日志。

当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,立刻删除。

而update、delete的时候、产生的undo log日志不仅在回滚时需要,MVCC版本访问也需要,不会立即被删除。

所以,两者是如何联系起来的呢?

不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部时最新的旧记录,链表尾部是最早的旧记录(看图更容易理解)通过DB_ROLL_PTR回滚指针连接

图片来自于其他CSDN上的博客

5.可串行化(系列化)(serializable)

事务的最高级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争,一般为了提升程序的吞吐量不会采用这个;

了解完事务的隔离级别后,我们再来看看事务的原子性,一致性,持久性是如何保证的。

binlog和redolog

binlog:

二进制日志,记录插入更新删除等操作的信息。

作用:数据恢复和复制。进行点对点复制和主从复制。

通过重放binlog记录的事件进行恢复和同步

redo log

重做日志,主要用于记录数据库事务的修改。

作用:数据库系统崩溃后,利用redolog记录的信息恢复未完成的事务,从而保证事务的持久性和一致性

redo log——实现持久性

重做日志,记录的是事务提交时数据页的物理变化,服务宕机可以用来同步数据。

该日志文件由两部分:重做日志缓冲(内存中)(redo log buffer)以及重做日志文件(磁盘中)(redo log file)。当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用

undo log——实现原子性和一致性

回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚和MVCC(多版本并发控制)。undo log和redo log记录物理日志不一样,他是逻辑日志。

记录的是逻辑日志,当事务回滚时,通过逆操作恢复原来的数据

  1. 可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然
  2. 当update一条记录时,他记录一条对应相反的update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

总结:

redo log日志记录的是数据页的物理变化,服务宕机可用来同步数据,而undo log不同,它主要记录的是逻辑日志。当事务回滚的时候,通过逆操作来恢复数据,若删除一条数据,就会在undo log日志文件中新增一条delete语句,如果发生回滚则执行逆操作

  • 18
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 MySQL Connector/NET 提供的 Transaction 对象来实现事务回滚。以下是一个使用 vb.net 和 MySQL Connector/NET 实现事务回滚的示例: ``` Imports MySql.Data.MySqlClient Dim connectionString As String = "server=localhost;user id=root;password=yourpassword;database=yourdatabase" Dim sql As String = "INSERT INTO mytable (column1, column2) VALUES ('value1', 'value2')" Dim sql2 As String = "INSERT INTO mytable (column1, column2) VALUES ('value3', 'value4')" Using conn As New MySqlConnection(connectionString) conn.Open() ' Start the transaction. Dim tx As MySqlTransaction = conn.BeginTransaction() Try ' Execute the first SQL statement. Using cmd As New MySqlCommand(sql, conn, tx) cmd.ExecuteNonQuery() End Using ' Execute the second SQL statement. Using cmd As New MySqlCommand(sql2, conn, tx) cmd.ExecuteNonQuery() End Using ' Commit the transaction. tx.Commit() Catch ex As Exception ' Rollback the transaction if an exception occurs. tx.Rollback() Console.WriteLine("Error: " & ex.Message) End Try End Using ``` 在以上代码中,我们首先创建了一个 MySqlConnection,然后使用 BeginTransaction 方法创建了一个事务对象 tx。在 Try 块中,我们可以执行一系列 SQL 语句,如果所有的 SQL 语句都执行成功,则调用 tx.Commit() 方法提交事务;如果其中任何一个 SQL 语句执行失败,则调用 tx.Rollback() 方法回滚事务。注意:在回滚事务后,所有执行过的 SQL 语句的效果都会被撤销,数据将回到之前的状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值