首页 > 数据库 >mysql事务实现原理详解

mysql事务实现原理详解

时间:2022-10-31 10:31:56浏览次数:38  
标签:事务 Log Redo 详解 提交 mysql 数据


说说MySQL中的Redo log Undo log都在干啥

undo日志用于存放数据修改被修改前的值,假设修改 tba 表中 id=2的行数据,把Name='B' 修改为Name = 'B2' ,那么undo日志就会用来存放Name='B'的记录,如果这个修改出现异常,可以使用undo日志来实现回滚操作,保证事务的一致性。对数据的变更操作,主要来自 INSERT UPDATE DELETE,而UNDO LOG中分为两种类型,一种是 INSERT_UNDO(INSERT操作),记录插入的唯一键值;一种是 UPDATE_UNDO(包含UPDATE及DELETE操作),记录修改的唯一键值以及old column记录。00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC)。- 事务的原子性(Atomicity)事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在执行的过程中发生了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过。Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为Undo Log)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。除了可以保证事务的原子性,Undo Log也可以用来辅助完成事务的持久化。- 事务的持久性(Durability)事务一旦完成,该事务对数据库所做的所有修改都会持久的保存到数据库中。不能因为错误/重启/宕机而丢失已经COMMIT的数据。为了保证持久性,数据库系统需要将修改后的数据完全的记录到持久的存储上。- 用Undo Log实现原子性和持久化的事务的简化过程假设有A、B两个数据,值分别为1,2。B.记录A=1到undo log的内存buffer.C.在内存中修改A=3.D.记录B=2到undo log的内存buffer.E.在内存中修改B=4.F.将undo log的buffer写到磁盘。G.将内存中修改后的数据写到磁盘。这里有一个前提条件:‘数据都是先读到内存中,然后修改内存中的数据,最后将数据写回磁盘’。以上过程之所以能同时保证原子性和持久化,是因为以下特点:A. 更新数据前记录Undo log。B. 为了保证持久性,必须将数据在事务提交前写到磁盘。只要事务成功提交,数据必然已经持久化。C. Undo log必须先于数据持久化到磁盘。如果在G,H之间系统崩溃,undo log是完整的,可以用来回滚事务。D. 如果在A-F之间系统崩溃,因为数据没有持久化到磁盘。所以磁盘上的数据还是保持在事务开始前的状态。缺陷:每个事务提交前将数据和Undo Log写入磁盘,这样会导致大量的磁盘IO,因此性能很低。如果能够将数据缓存一段时间,就能减少IO提高性能。但是这样就会丧失事务的持久性。因此引入了另外一种机制来实现持久化,即Redo Log.01 – Redo Log和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交时,只要将Redo Log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是Redo Log已经持久化。系统可以根据Redo Log的内容,将所有数据恢复到最新的状态。- Undo + Redo事务的简化过程假设有A、B两个数据,值分别为1,2.B.记录A=1到undo log的内存buffer.C.内存中修改A=3.D.记录A=3到redo log的内存buffer.E.记录B=2到undo log的内存buffer.F..内存中修改B=4.G.记录B=4到redo log的内存buffer.H.将redo log的内存buffer写入磁盘。- Undo + Redo事务的特点A. 为了保证持久性,必须在事务提交时将Redo Log持久化。B. 数据不需要在事务提交前写入磁盘,而是缓存在内存中。C. Redo Log 保证事务的持久性。D. Undo Log 保证事务的原子性。E. 有一个隐含的特点,数据必须要晚于redo log写入持久存储。这是因为Recovery要依赖redo log. 如果redo log丢失了,系统需要保持事务的数据也没有被更新。Undo + Redo的设计主要考虑的是提升IO性能。虽说通过缓存数据,减少了写数据的IO. 但是却引入了新的IO,即写Redo Log的IO。如果Redo Log的IO性能不好,就不能起到提高性能的目的。为了保证Redo Log能够有比较好的IO性能,InnoDB 的 Redo Log的设计有以下几个特点:A. 尽量保持Redo Log存储在一段连续的空间上。以顺序追加的方式记录Redo Log,通过顺序IO来改善性能。因此在系统第一次启动时就会将日志文件的空间完全分配,从而保证Redo Log文件在存储上的空间有更好的连续性。B. 批量写入日志。日志并不是直接写入文件,而是先写入redo log buffer.当需要将日志刷新到磁盘时 (如事务提交),才将许多日志一起写入磁盘,这样可以减少IO次数。C. 并发的事务共享Redo Log的存储空间,它们的Redo Log按语句的执行顺序,依次交替的记录在一起,以减少Redo Log的IO次数。例如,Redo Log中的记录内容可能是这样的:记录1: 记录2: 记录3: 记录4: 记录5: D. 因为C的原因,当一个事务将Redo Log写入磁盘时,也会将其他未提交的事务的日志写入磁盘。E. Redo Log上只进行顺序追加的操作,当一个事务需要回滚时,它的Redo Log记录也不会从Redo Log中删除掉。InnoDB的做法时将回滚操作也记入Redo Log(具体做法看下一节).

mysql a事物在写 b事物能读吗

我们先来看看事务的语法。现在的社会比较浮躁,大家往往只在乎如何解决问题,而不去考虑问题的本质到底是什么。

所以我决定先来介绍事务的语法:

1.开启事务starttransaction,可以简写为begin2.然后记录之后需要执行的一组sql

3.提交commit

4.如果所有的sql都执行成功,则提交,将sql的执行结果持久化到数据表内。

5.回滚rollback

6.如果存在失败的sql,则需要回滚,将sql的执行结果,退回到事务开始之时7.无论回滚还是提交,都会关闭事务!需要再次开启,才能使用。

8.还有一点需要注意,就是事务只针对当前连接。

下面我们来进行演示:

使用第一个链接A,开启事务后,执行一条update语句。

结果成功,数据已经变成修改之后!

这里写图片描述

此时我们没有提交。

再从其他连接B来查看,发现数据为更改:

这里写图片描述

此时如果连接A选择提交,也就是commit操作。则连接B的数据也会发生变化。

而如果连接A选择回滚,也就是rollback操作。则连接A再次查询则发现数据还原。

语法说完了,浮躁的人也不用继续看下去了。下面简单说一下事务的基本原理吧。

提交,就会将结果持久化,不提交就不会。

如果我们不开启事务,只执行一条sql,马上就会持久化数据,可以看出,普通的执行就是立即提交。

这是因为MySQL默认对sql语句的执行是自动提交的。

也就是说,开启事务,实际上就是关闭了自动提交的功能,改成了commit手动提交!

我们可以通过简单的对是否自动提交加以设置,完成开启事务的目的!

自动提交的特征是保存在服务的一个autocommit的变量内。可以进行修改:

这里写图片描述

还需要注意一点,就是事务类似于外键约束,只被innodb引擎支持。

下面来说说事务的特点ACID。也就是原子性,一致性,隔离性和持久性。

原子性:事务是不可分割的。

一致性:保证数据在事务的执行周期内,是一致的!

隔离型:多个事务之间的干扰关系!隔离级别!

持久性:事务一旦被提交,就不可能再被回滚!

事务并发会带来一些问题,所以才有了不同的事务隔离级别。要想了解事务的隔离级别,就必须首先了解事务并发会带来的问题。

一般来说,会出现三类数据读问题和数据更新问题。

一个事务正在对一条记录做修改,但未提交,另一个事务读取了这些脏数据,并进一步处理,就会产生未提交的数据依赖。

举一个例子:

时间转账事务A取款事务B

T1开始事务

T2开始事务

T3查询账户余额为1000元

T4取出500元把余额改为500元

T5查询账户余额为500元(脏读)

T6撤销事务余额恢复为1000元

T7汇入100元把余额改为600元

T8提交事务

A读取了B尚未提交的脏数,导致最后余额为600元。

不可重复读

一个事务在不同时间读取数据不一致。

举一个例子:

时间取款事务A转账事务B

T1开始事务

T2开始事务

T3查询账户余额为1000元

T4查询账户余额为1000元

T5取出100元把余额改为900元

T6提交事务

T7查询账户余额为900元(和T4读取的不一致)可以看到最后读取的数据不一致。

幻读和不可重复读的概念类似,都是不同时间数据不一致,只不过幻读是针对新增数据,而不可重复读是针对更改数据。

看一个例子:

时间统计金额事务A转账事务B

T1开始事务

T2开始事务

T3统计总存款数为10000元

T4新增一个存款账户,存款为100元

T5提交事务

T6再次统计总存款数为10100元(幻象读)

两个事务对同一数据进行更新,后者会覆盖先者的更新。

时间取款事务A转账事务B

T1开始事务

T2开始事务

T3查询账户余额为1000元

T4查询账户余额为1000元

T5汇入100元把余额改为1100元

T6提交事务

T7取出100元将余额改为900元

T8撤销事务

T9余额恢复为1000元(丢失更新)

事务并发带来的问题前文已经描述得非常仔细了。事务的隔离级别就是为了针对并发出现的问题,不同的级别可以保证不同的一致性。

为了解决上面讲到的并发事务处理带来的问题,SQL标准提出了4个等级的事务隔离级别。不同的隔离级别在同样的环境下会出现不同的结果。

下面看看四种隔离级别的比较:

隔离级别读数据一致性脏读不可重复读幻读

未提交读(Readuncommitted)最低级别,只能保证不读取物理上损坏的数据是是是已提交读(Readcommitted)语句级否是是

可重复读(Repeatableread)事务级否否是

可序列化(Serializable)最高级别,事务级否否否

你对mysql数据库事务有理解吗?

我同学是学PHP的,我是学ASP的,至于事务我想应该咱们学的都差不多吧,用事务写程序感觉挺简单的,方便isam执行读取操作的速度很快,而且不占用大量的内存和存储资源。

isam的两个主要不足之处在于,它不支持事务处理,也不能够容错:如果你的硬盘崩溃了,那么数据文件就无法恢复了。如果你正在把isam用在关键任务应用程序里,那就必须经常备份你所有的实时数据,通过其复制特性,mysql(和php搭配之最佳组合)能够支持这样的备份应用程序。

myisammyisam是mysql(和php搭配之最佳组合)的isam扩展格式和缺省的mysql数据库引擎。除了提供isam里所没有的索引和字段管理的大量功能,myisam还使用一种表格锁定的机制,来优化多个并发的读写操作。其代价是你需要经常运行optimize table命令,来恢复被更新机制所浪费的空间。

myisam还有一些有用的扩展,例如用来修复mysql数据库文件的myisamchk工具和用来恢复浪费空间的myisampack工具。

heapheap允许只驻留在内存里的临时表格。驻留在内存里让heap要比isam和myisam都快,但是它所管理的数据是不稳定的,而且如果在关机之前没有进行保存,那么所有的数据都会丢失。在数据行被删除的时候,heap也不会浪费大量的空间。heap表格在你需要使用select表达式来选择和操控数据的时候非常有用。要记住,在用完表格之后就删除表格。让我再重复一遍:在你用完表格之后,不要忘记删除表格。

innodb和berkley db

innodb和berkley db(bdb)数据库引擎都是造就mysql(和php搭配之最佳组合)灵活性的技术的直接产品,这项技术就是mysql(和php搭配之最佳组合)++ api。在使用mysql(和php搭配之最佳组合)的时候,你所面对的每一个挑战几乎都源于isam和myisam数据库引擎不支持事务处理也不支持外来键。尽管要比isam和myisam引擎慢很多,但是innodb和bdb包括了对事务处理和外来键的支持,这两点都是前两个引擎所没有的。如前所述源码天空

Mysql中的事务是什么如何使用

事务能保证你做的一系列动作,要么全部成功。如果有一个操作失败,就回退到修改前。 比如你要做下面几个操作, 1.删除表A中的某些记录 2.向B添加一些记录。 3.修改C表中的一些数据。 使用事务,如果1,2都成功了,3却失败了。就会回退到第1步执行前的样子,ABC表都没被修改。什么是事务?

事务是逻辑上的一组操作,组成这组操作的各个单元,要不全都成功要不全都失败,这个特性就是事务

注意:mysql数据支持事务,但是要求必须是innodb存储引擎

解决这个问题:

mysql的事务解决这个问题,因为mysql的事务特性,要求这组操作,要不全都成功,要不全都失败,这样就避免了某个操作成功某个操作失败。利于数据的安全

如何使用:

(1)在执行sql语句之前,我们要开启事务 start transaction;

(2)正常执行我们的sql语句

(3)当sql语句执行完毕,存在两种情况:

1,全都成功,我们要将sql语句对数据库造成的影响提交到数据库中,committ

2,某些sql语句失败,我们执行rollback(回滚),将对数据库操作赶紧撤销

(注意:mysql数据支持事务,但是要求必须是innodb存储引擎)

mysql> create table bank(name varchar(20),money decimal(5,1))engine=innodb defau

lt charset=utf8;

mysql> inset into bank values('shaotuo',1000),('laohu',5000);

mysql> select*from bank;

+---------+--------+

| name | money |

+---------+--------+

| shaotuo | 1000.0 |

| laohu | 5000.0 |

+---------+--------+

------没有成功“回滚”执行rollback

mysql> start transaction; //开启事务

query ok, 0 rows affected (0.00 sec)

mysql> update bank set money=money+500 where name='shaotuo';

query ok, 1 row affected (0.00 sec)

rows matched: 1 changed: 1 warnings: 0

mysql> update bank set moey=money-500 where name='laohu';

error 1054 (42s22): unknown column 'moey' in 'field list'

mysql> rollback; //只要有一个不成功,执行rollback操作

query ok, 0 rows affected (0.01 sec)

mysql> select*from bank;

+---------+--------+

| name | money |

+---------+--------+

| shaotuo | 1000.0 |

| laohu | 5000.0 |

+---------+--------+

------成功之后 进行commit操作

mysql> start transaction; //开启事务

query ok, 0 rows affected (0.00 sec)

mysql> update bank set money=money+500 where name='shaotuo';

query ok, 1 row affected (0.01 sec)

rows matched: 1 changed: 1 warnings: 0

mysql> update bank set money=money-500 where name='laohu';

query ok, 1 row affected (0.00 sec)

rows matched: 1 changed: 1 warnings: 0

mysql> commit; //两个都成功后执行commit(只要不执行commit,sql语句不会对真实的数据库造成影响)

query ok, 0 rows affected (0.05 sec)

mysql> select*from bank;

+---------+--------+

| name | money |

+---------+--------+

| shaotuo | 1500.0 |

| laohu | 4500.0 |

+---------+--------+

标签:事务,Log,Redo,详解,提交,mysql,数据
From: https://blog.51cto.com/yetaotao/5808598

相关文章

  • MySQLdebug binaries
    mysql-5.7.21-winx64-debug-test.zip解压之后怎么使用啊,怎么才能用NavicatforMySQL连接,求帮忙参考教程:MySQL压缩解压包的安装配置Mysql过程怎么单步debug看图说话,第四步,传......
  • 事务隔离级别和锁
    一次封锁or两段锁?因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会用到哪些数据,然后全部锁住,在方法运行之后,再全部解锁......
  • datagrip安装驱动时候 解决Driver class ‘com.mysql.cj.jdbc.Driver‘ not found.
         ......
  • Mysql学习笔记
    Mysqlshodan:"product:MySQL"fofa:app="Oracle-MySQL"描述MySQL是一个关系型数据库管理系统,由瑞典MySQLAB公司开发,目前属于Oracle公司。MySQL是一种关联......
  • MYSQL索引
    索引的优点索引大大减少了服务器需要扫描的数据量索引可以帮助服务器避免排序和临时表索引可以将随机I/O变成顺序I/O索引只要帮助存储引擎快速查找到记录,带来......
  • mysql主从复制-docker
    1、拉取mysql:5.7镜像dockerpullmysql:5.72、创建主服务器配置文件mkdir-p/mydata/mysql-master/confvi/mydata/mysql-master/conf/my.cnfcat/mydata/mysql-......
  • Latex Table 合并行/列详解
    1.整体逻辑整个table是由大小一致的单元格组成的,在这个基础上,我们通过合并单元格(行/列)的方式,实现整个table的设计:竖线用“|”,横线用“\cline“,列合并用”\multicolumn“,......
  • 【763】MySQL and SQL 相关
    参考:MySQL教程参考:MySQLonMac—GettingStarted参考:SQL教程......
  • ORM查询方法详解
    ORM查询方法 ......
  • Memcache详解
    Memcache详解参考链接https://blog.51cto.com/freeloda/1289806https://acecodeinterview.com/memcached/https://hoverzheng.github.io/post/technology-blog/archite......