热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

Mysql事务(标贝科技)

@目录事务InnoDB对ACID的支持隔离级别不同隔离级别下读读取数据可能出现的情况不可重复读和幻读区别redolog(共享表空间)redologblock刷redolog策略:i

@

目录



  • 事务

    • InnoDB对ACID的支持

    • 隔离级别



        • 不同隔离级别下读读取数据可能出现的情况

        • 不可重复读和幻读区别





    • redo log (共享表空间)

      • redo log block

        • 刷redo log策略:

        • innodb存储引擎中checkpoint:

          • 触发逻辑

          • 解决问题



        • Log sequence number日志序列号

          • innodb从执行修改语句开始:







    • undo log 日志(共享表空间)



        • 记录日志的方式








事务

InnoDB对ACID的支持
































特性说明InnoDB支持
原子性一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样autocommit,commit,rollcack
一致性在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。(比如:A向B转账,不可能A扣了钱,B却没有收到)双InnoDB写缓冲区,“双写缓冲区”,InnoDB崩溃恢复
隔离性数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。(例:A正在从一张银行卡里面取钱,在A取钱的过程中,B不能向这张银行卡打钱)事务隔离级别
持久性(涉及硬件选购)事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失双InnoDB写缓冲区,“双写缓冲区”(innodb_flush_log_at_trx_commit 变量。(例如sync_binlog变量,innodb_file_per_table 变量),存储设备中的写入缓冲区(例如磁盘驱动器、SSD 或 RAID 阵列,存储设备中的电池后备缓存。用于运行 MySQL 的操作系统,特别是它对fsync()系统调用的支持)

隔离级别


不同隔离级别下读读取数据可能出现的情况

脏读:一个事务处理过程里读取了另一个未提交的事务中的数据
不可重复读:一个事务在它运行期间,两次查找相同的表,出现了不同的数据
幻读:在一个事务中读取到了别的事务插入的数据,导致前后不一致
串行化:既不允许脏读,也不允许不可重复读,并且还不允许幻读









































隔离级别说明脏读不可重复读)幻读
未提交读(Read uncommitted)所有事务都可以看到没有提交事务的数据可能可能可能
已提交读(Read committed)事务成功提交后才可以被查询到不可能可能可能
可重复读(Repeatable read)同一个事务内多次查询却返回了不同的数据值不可能不可能可能
可串行化(Serializable )强制的进行排序,在每个读读数据行上添加共享锁不可能不可能不可能

隔离级别是在多个事务同时进行更改和执行查询时微调结果的性能、可靠性、一致性和可再现性之间的平衡的设置


不可重复读和幻读区别

(1)不可重复读是读取了其他事务更改的数据,针对update操作

解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据

(2)幻读是读取了其他事务新增的数据,针对insert与delete操作

解决:使用间隙锁,表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据

幻读和不可重复读都是指的一个事务范围内的操作受到其他事务的影响了。只不过幻读是重点在插入和删除,不可重复读重点在修改


redo log (共享表空间)

innodb通过预写日志(force log at commit)机制实现事务的持久性

优点:日志顺序写速度远远大于数据页随机写磁盘

两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log)

redo log写入流程

请添加图片描述


redo log block

redo log以块为单位进行存储的,每个块占512字节。log buffer、redo log file中,都是这样以512字节的块存储的

redo log block包含4部分:



  • Ÿ log_block_hdr_no:(4字节)该日志块在redo log buffer中的位置ID

  • Ÿ log_block_hdr_data_len:(2字节)该log block中已记录的log大小。写满该log block时为0x200,表示512字节

  • Ÿ log_block_first_rec_group:(2字节)该log block中第一个log的开始偏移位置

  • Ÿ lock_block_checkpoint_no:(4字节)写入检查点信息的位置

relog block块头的第三部分 log_block_first_rec_group ,因为有时候一个数据页产生的日志量超出了一个日志块,这是需要用多个日志块来记录该页的相关日志。例如,某一数据页产生了552字节的日志量,那么需要占用两个日志块,第一个日志块占用492字节,第二个日志块需要占用60个字节,那么对于第二个日志块来说,它的第一个log的开始位置就是73字节(60+12)。如果该部分的值和 log_block_hdr_data_len 相等,则说明该log block中没有新开始的日志块,即表示该日志块用来延续前一个日志块

默认redolog由ib_logfile0、ib_logfile1组成,以追加写入的方式循环轮训写入。即先在第一个log file(即ib_logfile0)的尾部追加写,直到满了之后向第二个log file(即ib_logfile1)写。当第二个log file满了会清空一部分第一个log file继续写入


刷redo log策略:

1.发出commit动作时。commit发出后是否刷日志由变量 innodb_flush_log_at_trx_commit 控制

2.每秒刷一次。这个刷日志的频率由变量 innodb_flush_log_at_timeout 值决定,默认是1秒。要注意,这个刷日志频率和commit动作无关

3.当log buffer中已经使用的内存超过一半时

4.当有checkpoint时,checkpoint在一定程度上代表了刷到磁盘时日志所处的LSN位置

MySQL支持用户自定义在commit时如何将log buffer中的日志刷log file中。这种控制通过变量 innodb_flush_log_at_trx_commit 的值来决定。该变量有3种值:0、1、2,默认为1。



  • 当设置为1的时候,事务每次提交都会将log buffer中的日志写入os buffer并调用fsync()刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差

  • 当设置为0的时候,事务提交时不会将log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到log file on disk中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据

  • 当设置为2的时候,每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到log file on disk

请添加图片描述


innodb存储引擎中checkpoint:

redolog日志太大怎么办?

解决问题:1、缩短数据库的恢复时间 2、缓冲池不够用时,将脏页刷新到磁盘 3、重做日志不可用时,刷新脏页


触发逻辑


  • sharp checkpoint:在重用redo log文件(例如切换日志文件)的时候,将所有已记录到redo log中对应的脏数据刷到磁盘

  • fuzzy checkpoint:一次只刷一小部分的日志到磁盘,而非将所有脏日志刷盘。有以下几种情况会触发该检查点:

    • master thread checkpoint:由master线程控制,每秒或每10秒刷入一定比例的脏页到磁盘

    • flush_lru_list checkpoint:从MySQL5.6开始可通过 innodb_page_cleaners 变量指定专门负责脏页刷盘的page cleaner线程的个数,该线程的目的是为了保证lru列表有可用的空闲页

    • async/sync flush checkpoint:同步刷盘还是异步刷盘。例如还有非常多的脏页没刷到磁盘(非常多是多少,有比例控制),这时候会选择同步刷到磁盘,但这很少出现;如果脏页不是很多,可以选择异步刷到磁盘,如果脏页很少,可以暂时不刷脏页到磁盘

    • dirty page too much checkpoint:脏页太多时强制触发检查点,目的是为了保证缓存有足够的空闲空间。too much的比例由变量 innodb_max_dirty_pages_pct 控制,MySQL 5.6默认的值为75,即当脏页占缓冲池的百分之75后,就强制刷一部分脏页到磁盘




解决问题


  • 当数据库发生宕机时,数据库不需要重做所有的日志,因为Checkpoint之前的页都已经刷新回磁盘。数据库只需对Checkpoint后的重做日志进行恢复,这样就大大缩短了恢复的时间

  • 当缓冲池不够用时,根据LRU算法会溢出最近最少使用的页,若此页为脏页,那么需要强制执行Checkpoint,将脏页也就是页的新版本刷回磁盘

  • 当重做日志出现不可用时,因为当前事务数据库系统对重做日志的设计都是循环使用的,并不是让其无限增大的,重做日志可以被重用的部分是指这些重做日志已经不再需要,当数据库发生宕机时,数据库恢复操作不需要这部分的重做日志,因此这部分就可以被覆盖重用。如果重做日志还需要使用,那么必须强制Checkpoint,将缓冲池中的页至少刷新到当前重做日志的位置


Log sequence number日志序列号

LSN称为日志的逻辑序列号(log sequence number),在innodb存储引擎中,lsn占用8个字节。LSN的值会随着日志的写入而逐渐增大

根据LSN,可以获取到几个有用的信息:

1.数据页的版本信息

2.写入的日志总量,通过LSN开始号码和结束号码可以计算出写入的日志量

3.可知道检查点的位置

实际上还可以获得很多隐式的信息


innodb从执行修改语句开始:

(1).首先修改内存中的数据页,并在数据页中记录LSN,暂且称之为data_in_buffer_lsn

(2).并且在修改数据页的同时(几乎是同时)向redo log in buffer中写入redo log,并记录下对应的LSN,暂且称之为redo_log_in_buffer_lsn

(3).写完buffer中的日志后,当触发了日志刷盘的几种规则时,会向redo log file on disk刷入重做日志,并在该文件中记下对应的LSN,暂且称之为redo_log_on_disk_lsn

(4).数据页不可能永远只停留在内存中,在某些情况下,会触发checkpoint来将内存中的脏页(数据脏页和日志脏页)刷到磁盘,所以会在本次checkpoint脏页刷盘结束时,在redo log中记录checkpoint的LSN位置,暂且称之为checkpoint_lsn

(5).要记录checkpoint所在位置很快,只需简单的设置一个标志即可,但是刷数据页并不一定很快,例如这一次checkpoint要刷入的数据页非常多。也就是说要刷入所有的数据页需要一定的时间来完成,中途刷入的每个数据页都会记下当前页所在的LSN,暂且称之为data_page_on_disk_lsn


undo log 日志(共享表空间)

当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录

作用:



  • 提供回滚

  • 多个行版本控制(MVCC)当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取


记录日志的方式



  • insert操作记录delete操作,但是可能只是打delete flag标签,由最终的主线程完成

  • delete操作实际上不会直接删除,而是将delete对象打上delete flag,标记为删除,最终的删除操作是purge线程完成的

  • update分为两种情况:update的列是否是主键列

    • 如果不是主键列,在undo log中直接反向记录是如何update的。即update是直接进行的

    • 如果是主键列,update分两部执行:先删除该行,再插入一行目标行



参考文献

[1]https://dev.mysql.com/doc/dev/mysql-server/latest/PAGE_PROTOCOL.html

[2]https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_packets.html#sect_protocol_basic_packets_packet

[3]https://www.jianshu.com/p/5e6b33d8945f

[4]https://cloud.tencent.com/developer/article/1768901

[5]https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_authentication_methods.html

[6]https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_command_phase.html

[7]https://dev.mysql.com/doc/internals/en/

[8]https://www.cnblogs.com/wyq178/p/11576065.html

[9]Mysql技术内幕:InnoDB存储引擎 (第2版). 姜承尧

[10]MySQL运维内参:MySQL、Galera、Inception核心原理与最佳实践. 周彦伟,王竹峰,强昌金

[11]https://dev.mysql.com/doc/refman/5.7/en/innodb-architecture.html

[12]https://dev.mysql.com/doc/refman/5.7/en/faqs-innodb-change-buffer.html



推荐阅读
  • Principle for Mac(交互式屏幕设计软件)免激活版
    Mac上好用的交互式屏幕设计软件,PrincipleforMac是一款交互式屏幕设计软件,principle mac让您的设计将以原则出现,随时为您注入新的活力。如果您进行更改,再 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了在Pygame中使用矩形对表面进行涂色的方法。通过查阅Pygame文档中的blit函数,可以了解到如何将一个表面的特定部分复制到另一个表面的指定位置上。具体的解决方法和参数说明在文中都有详细说明。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • IB 物理真题解析:比潜热、理想气体的应用
    本文是对2017年IB物理试卷paper 2中一道涉及比潜热、理想气体和功率的大题进行解析。题目涉及液氧蒸发成氧气的过程,讲解了液氧和氧气分子的结构以及蒸发后分子之间的作用力变化。同时,文章也给出了解题技巧,建议根据得分点的数量来合理分配答题时间。最后,文章提供了答案解析,标注了每个得分点的位置。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了[从头学数学]中第101节关于比例的相关问题的研究和修炼过程。主要内容包括[机器小伟]和[工程师阿伟]一起研究比例的相关问题,并给出了一个求比例的函数scale的实现。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了如何将CIM_DateTime解析为.Net DateTime,并分享了解析过程中可能遇到的问题和解决方法。通过使用DateTime.ParseExact方法和适当的格式字符串,可以成功解析CIM_DateTime字符串。同时还提供了关于WMI和字符串格式的相关信息。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
author-avatar
执信电影频道
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有