暂无图片
MySQL事务的ACID是怎么保证的?
我来答
分享
L
lelepapa
2023-01-11
MySQL事务的ACID是怎么保证的?

MySQL事务的ACID是怎么保证的?

我来答
添加附件
收藏
分享
问题补充
2条回答
默认
最新
手机用户5704

MySQL事务的ACID,其中(C)一致性是最终目的。

保证一致性的措施有:
A原子性:靠undo log来保证(异常或执行失败后进行回滚)。
D持久性:靠redo log来保证(保证当MySQL宕机或停电后,可以通过redo log最终将数据保存至磁盘中)。
I隔离性:事务间的读写靠MySQL的锁机制来保证隔离,事务间的写操作靠MVCC机制(快照读、当前读)来保证隔离性。
C一致性:事务的最终目的,即需要数据库层面保证,又需要应用层面进行保证,并且MySQL底层通过两阶段提交事务保证了事务持久化时的一致性。

注:什么是undo log和redo log
undo log 属于逻辑日志,它记录的是SQL执行相关的信息。当事务对数据库进行修改时,InnoDB会生成与之对应的undo log。如果事务执行失败或者调用的rollback,导致事务需要回滚,InnoDB引擎会根据undo log中的记录,将数据回滚到之前的样子。

redo log:持久性是指事务一旦提交,对数据库的操作就是永久性的,接下来的其他操作和异常故障不应该对它有任何影响。
我们都知道MySQL的数据最终是存放在磁盘中的,所以才会有磁盘的容量大小决定数据容量的大小。但是如果对MySQL的操作都是通过读写磁盘来进行的话,那么光是磁盘的I/O就够把效率大大的拉低了。
所以InnoDB为MySQL提供了缓冲池(Buffer Pool),Buffer Pool中包含了磁盘中部分数据页的映射。
当从数据库读取数据时,会先从Buffer Pool中读取数据,如果Buffer Pool中没有,则从磁盘读取后放入到Buffer Pool中。
当向数据库写入数据时,会先写入到Buffer Pool中,Buffer Pool中更新的数据会定期刷新到磁盘中(此过程称为刷脏)。
虽然Buffer Pool为MySQL的读写提高了效率,但是却也带来了新的问题,那就是如果数据刚更新到Buffer Pool中还没来得及刷新到磁盘中时,MySQL突然宕机了,这就会导致数据丢失,造成事务的持久性无法保证了。
为了解决这个缓存的一致性问题,redo log就出现了。在对Buffer Pool中的数据进行修改的时候通过redo log记录这次操作,当事务提交时会通过fsync接口对redo log进行刷盘。
因为在事务提交时会把redo log是同步在磁盘中的,所以当MySQL出现宕机时,可以从磁盘中读取redo log进行数据的恢复,从而保证了事务的持久性。
redo log 采用的预写的方式记录日志,即先记录日志,再更新Buffer Pool,这样就强行的保证了,数据只要保存在了redo log中就一定会存储到磁盘中了。

这要解释一下,redo log 也是写磁盘,刷脏也是写磁盘,为啥要先记录redo log而不是直接刷脏?
主要原因就是redo log比刷脏快很多。
第一点是,redo log是追加操作日志,是顺序IO;而刷脏是随机IO,因为每次更新的数据不一定是挨着的,也就是随机的。
第二点是,刷脏是以数据页(Page)为单位的(即每次最少从磁盘中读取一页数据到内存,或者最少刷一页数据到磁盘),MySQL默认页大小是16KB,对一个页上的修改,都要整个页都刷到磁盘中;而redo log只包含真正的需要写入磁盘的操作日志。

暂无图片 评论
暂无图片 有用 1
打赏 0
暂无图片
D
dyf1

MySQL事务的ACID,其中(C)一致性是最终目的。

保证一致性的措施有:
A原子性:靠undo log来保证(异常或执行失败后进行回滚)。
D持久性:靠redo log来保证(保证当MySQL宕机或停电后,可以通过redo log最终将数据保存至磁盘中)。
I隔离性:事务间的读写靠MySQL的锁机制来保证隔离,事务间的写操作靠MVCC机制(快照读、当前读)来保证隔离性。
C一致性:事务的最终目的,即需要数据库层面保证,又需要应用层面进行保证,并且MySQL底层通过两阶段提交事务保证了事务持久化时的一致性。

注:什么是undo log和redo log
undo log 属于逻辑日志,它记录的是SQL执行相关的信息。当事务对数据库进行修改时,InnoDB会生成与之对应的undo log。如果事务执行失败或者调用的rollback,导致事务需要回滚,InnoDB引擎会根据undo log中的记录,将数据回滚到之前的样子。

redo log:持久性是指事务一旦提交,对数据库的操作就是永久性的,接下来的其他操作和异常故障不应该对它有任何影响。
我们都知道MySQL的数据最终是存放在磁盘中的,所以才会有磁盘的容量大小决定数据容量的大小。但是如果对MySQL的操作都是通过读写磁盘来进行的话,那么光是磁盘的I/O就够把效率大大的拉低了。
所以InnoDB为MySQL提供了缓冲池(Buffer Pool),Buffer Pool中包含了磁盘中部分数据页的映射。
当从数据库读取数据时,会先从Buffer Pool中读取数据,如果Buffer Pool中没有,则从磁盘读取后放入到Buffer Pool中。
当向数据库写入数据时,会先写入到Buffer Pool中,Buffer Pool中更新的数据会定期刷新到磁盘中(此过程称为刷脏)。
虽然Buffer Pool为MySQL的读写提高了效率,但是却也带来了新的问题,那就是如果数据刚更新到Buffer Pool中还没来得及刷新到磁盘中时,MySQL突然宕机了,这就会导致数据丢失,造成事务的持久性无法保证了。
为了解决这个缓存的一致性问题,redo log就出现了。在对Buffer Pool中的数据进行修改的时候通过redo log记录这次操作,当事务提交时会通过fsync接口对redo log进行刷盘。
因为在事务提交时会把redo log是同步在磁盘中的,所以当MySQL出现宕机时,可以从磁盘中读取redo log进行数据的恢复,从而保证了事务的持久性。
redo log 采用的预写的方式记录日志,即先记录日志,再更新Buffer Pool,这样就强行的保证了,数据只要保存在了redo log中就一定会存储到磁盘中了。

这要解释一下,redo log 也是写磁盘,刷脏也是写磁盘,为啥要先记录redo log而不是直接刷脏?
主要原因就是redo log比刷脏快很多。
第一点是,redo log是追加操作日志,是顺序IO;而刷脏是随机IO,因为每次更新的数据不一定是挨着的,也就是随机的。
第二点是,刷脏是以数据页(Page)为单位的(即每次最少从磁盘中读取一页数据到内存,或者最少刷一页数据到磁盘),MySQL默认页大小是16KB,对一个页上的修改,都要整个页都刷到磁盘中;而redo log只包含真正的需要写入磁盘的操作日志。
————————————————
版权声明:本文为CSDN博主「YangYoung_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/YangYoung_/article/details/117195841

暂无图片 评论
暂无图片 有用 0
打赏 0
回答交流
Markdown


请输入正文
提交
相关推荐
MySQL 如果一直向一个txt文件里面写入日志数据,时间长了,会不会导致文件巨大,从而导致无法写入的情况?
回答 2
啥意思。。。没明白
请问show engine innodb status输出中INSERT BUFFER AND ADAPTIVE HASH INDEX如何解读?
回答 1
INSERTBUFFER(插入缓冲):当有多个插入操作时,InnoDB会将这些操作缓存起来,然后在适当的时候一次性执行,以提高插入性能。在这个输出中,可以看到Ibuf的大小为1,空闲列表长度为0,段大
MySQL查询结果可以直接into到shell变量里不?
回答 1
已采纳
你要将查询结果赋值给shell变量肯定不能用into这么直接搞啊,可以按下面的格式:targetdbexistsmysqluxxxhxxxpxxxNLe"SQL语句"来实现。
MySQL无法启动,日志里面提升非正常关闭。
回答 1
目前了解下来,这个没啥办法,就得mysqldump出来重新导入数据才可以的
MySQL 建立联合索引时,应该把低基数的列放在前还是把高基数的列放在前?
回答 1
已采纳
联合(组合)索引不一定由基数的高低来决定谁是前导列。经常进行等值查询,且选择性较好的列可以作为前导列。以下列出几个组合索引使用的场景总结:1.组合索引适合用在单独查询时返回记录很多,组合查询返回记录很
请问 :mysql的谓词锁是干啥用的?
回答 1
https://dev.mysql.com/doc/refman/5.7/en/innodblocking.htmlinnodbpredicatelocks空间索引的谓词锁:解决空间空间索引的表的隔离
mysql配置文件里面mysql.sock这个文件的作用是?
回答 1
已采纳
这个文件中记录了sql服务器的IP\端口等信息。你可以直接使用socket文件,而不需要再指定主机IP和端口,即可连接到mysqlserver中,如mysqluxxxpsocket/tmp/mysql
mysql主键等于一个随机数的 查询出来两条数据
回答 2
有人说是不确定性函数的问题,会全表扫描,对于每刚行数据都执行rand函数,匹配就返回,所以返回多个。这样说能理解,但是感觉就是不符合语意,oracle就只返回一行
MySQL初始化的时候,时好时坏的,经常生成不了mysql.sock等文件,偶尔一下又可以,可能是什么原因?
回答 5
还是通过mysql的错误日志文件来确定问题吧
MySQLdb的SSCursor为什么会越来越慢?
回答 1
mysql的本身不适合做一些复杂处理的工作。对于游标嵌套循环,遍历结果比对一行一行,生成临时表,随着数据量增加,逻辑复杂性能下降太厉害了。sql语句尽量走索引。这个确实有点不好调试。看看能不能用普遍的