天元建设集团有限公司是国企还是央企,关键词优化一年多少钱,如何在工商局网站做企业年报,为什么很多网站用php做前言
redo log#xff1a;为了持久化数据#xff0c;当内存中的数据还没写入到磁盘而宕机时#xff0c;会读取该日志持久化数据到磁盘
undo log#xff1a;为了保证原子性#xff0c;事务的操作都会记录一条相反的sql到该日志#xff0c;出现错误就会根据该文件恢…前言
redo log为了持久化数据当内存中的数据还没写入到磁盘而宕机时会读取该日志持久化数据到磁盘
undo log为了保证原子性事务的操作都会记录一条相反的sql到该日志出现错误就会根据该文件恢复事务之前的数据
binlog为了复制和恢复数据mysql重启可以通过该日志恢复
以上三大日志是MySQL的原子性、持久性、数据一致性的保证。
bin log
bin log全称binary log二进制日志文件它记录了数据库所有执行的 DDL 和 DML 等数据库更新的语句但是不包含select或者show等没有修改任何数据的语句。它是MySQL级别的日志也就是说所有的存储引擎都会产生bin log而redo log或者undo log事务日志只有innoDB存储引擎才有。 可以使用show binary logs; 命令查看所有二进制日志列表。可以看到binlog 日志文件名为 文件名.00000 形式。* 通过 show binlog events in ‘binlog.000008’ limit 10; 命令查看日志的具体内容。另外一定要指定 limit不然查询出来的日志文件内容太多。另外 MySQL 内置了 binlog 查看工具 mysqlbinlog可以解析二进制文件。 1、写入方式
binlog 通过追加的方式进行写入大小没有限制。另外可以通过max_binlog_size参数设置每个 binlog 文件的最大容量当文件大小达到给定值之后会生成新的 binlog 文件来保存日志不会出现前面写的日志被覆盖的情况。
写入流程
1为了保证写的效率会将事务的bin log先写到binlog cache中这个cache位于事务线程的内存中主要是一个事务的bin log不能被拆开是一个整体。
**2在提交事务的时候将binlog cache中的数据统一写到文件系统缓存page cache中**这个过程速度也很快
3然后根据不同的策略将文件系统缓存中的bin logfsync刷到磁盘中这里的策略后面详细讲解。
2、3种binlog 的格式
1Statement 模式 每一条会修改数据的sql都会被记录在binlog中如inserts, updates, deletes。 **2Row 模式 推荐: 为了解决Statement缺点记录具体哪一个分区中的、哪一个页中的、哪一行数据被修改了。**但是适用于数据量比较大的场景否则记录分区信息,查找规则磁盘IO、网络带宽开销很大。
3Mixed 模式 Statement 模式和 Row 模式的混合。 **默认使用 Statement 模式少数特殊具体场景自动切换到 Row 模式。**MySQL 5.1.5 之前 binlog 的格式只有 STATEMENT5.1.5 开始支持 ROW 格式的 binlog从 5.1.8 版本开始MySQL 开始支持 MIXED 格式的 binlog。MySQL 5.7.7 之前默认使用 Statement 模式。MySQL 5.7.7 开始默认使用 Row 模式。 相比较于 Row 模式来说Statement 模式下的日志文件更小磁盘 IO 压力也较小性能更好有些。不过其准确性相比于 Row 模式要差。可以使用 show variables like ‘%binlog_format%’; 查看 binlog 使用的格式。 3、应用场景
binlog 最主要的应用场景是 主从复制和数据恢复 主从复制常见是主备、主主、主从都离不开binlog需要依靠 binlog 来同步数据保证数据一致性。
可以使用show variables like ‘log_bin’;查看数据库是否启用 binlog 日志默认是开启的。
1主从复制的原理 主库将数据库中数据的变化写入到 binlog从库连接主库从库会创建一个 I/O 线程向主库请求更新的 binlog主库会创建一个 binlog dump 线程来发送 binlog 从库中的 I/O 线程负责接收从库的 I/O 线程将接收的 binlog 写入到 relay log 中。从库的 SQL 线程读取 relay log 同步数据本地也就是再执行一遍 SQL 。 2Canal主从复制原理; Canal 模拟 MySQL Slave 节点与 MySQL Master 节点的交互协议把自己伪装成一个 MySQL Slave 节点向 MySQL Master 节点请求 binlogMySQL Master 节点接收到请求之后根据偏移量将新的 binlog 发送给 MySQL Slave 节点Canal 接收到 binlog 之后就可以对这部分日志进行解析获取主库的结构及数据变更。 4、binlog 的刷盘时机
**对于InnoDB存储引擎而言事务在执行过程中会先把日志写入到binlog cache中只有在事务提交的时候才会把binlog cache中的日志持久化到磁盘上的binlog文件中。**写入内存的速度更快这样做也是为了效率考虑。 因为一个事务的binlog不能被拆开无论这个事务多大也要确保一次性写入所以系统会给每个线程分配一个块内存作为binlog cache。我们可以通过binlog_cache_size参数控制单个线程 binlog cache 大小如果存储内容超过了这个参数就要暂存到磁盘Swap。 刷盘策略
biglog有3种刷盘策略 bin log的write和fsync时机是由参数 sync_binlog 控制。 MySQL5.7 之前 sync_binlog 默认值为 0。在 MySQL5.7 之后 sync_binlog默认值为 1。
0不去强制要求。
表示每次提交事务都只 write由系统自行判断什么时候执行fsync。虽然性能得到提升但是机器宕机page cache里面的 binglog 会丢失。
1每次提交事务的时候都要将binlog写入磁盘也就是说都会执行fsyncN每 N 个事务才会将binlog写入磁盘累积N个事务后才fsync。
什么情况下会重新生成 binlog
●MySQL服务器停止或重启
●使用 flush logs 命令后
●binlog 文件大小超过 max_binlog_size变量的阈值后。
bin log没写完bin log 与redo log之间的一致性问题有什么解决方案
InnoDB存储引擎使用两阶段提交方案。将redo log的写入拆成了两个步骤prepare和commit。
假如现在写入bin log时MySQL发生异常这时候的redo log还处于prepare阶段重启MySQL后根据redo log记录中的事务ID发现没有对应的bin log日志回滚前面已写入的数据。
如果redo log 在commit阶段发生移除但是能通过事务id找到对应的bin log日志所以MySQL认为是完整的就会提交事务恢复数据。
数据恢复
通过使用 mysqlbinlog 工具来恢复数据。
redo log
MySQL InnoDB 引擎使用 redo log 来保证事务的持久性。redo log 主要做的事情就是记录页的修改比如某个页面某个偏移量处修改了几个字节的值以及具体被修改的内容是什么。redo log 中的每一条记录包含了表空间号、数据页号、偏移量、具体修改的数据甚至还可能会记录修改数据的长度取决于 redo log 类型。
redo log包含两部分内存中的日志缓冲redo log buffer和磁盘上的日志文件redo logfile。内存层面默认16M通过innodb_log_buffer_size参数可修改。
MySQL 每执行一条 DML 语句先将记录写入 redo log buffer后续某个时间点再一次性将多个操作记录写到 redo log file。
写入过程
在计算机操作系统中用户空间( user space )下的缓冲区数据一般情况下是无法直接写入磁盘的中间必须经过操作系统内核空间( kernel space )缓冲区( OS Buffer )。因此 redo log buffer 写入 redo logfile 实际上是先写入 OS Buffer 然后再通过系统调用 fsync() 将其刷到 redo log file中。
流程
先将原始数据从磁盘中读入内存中来修改数据的内存拷贝产生脏数据生成一条重做日志并写入redo log buffer记录的是数据被修改后的值默认在事务提交后将redo log buffer中的内容刷新到redo log file对redo log file采用追加写的方式定期将内存中修改的数据刷新到磁盘中这里指的是内存缓冲池中的脏页
写入策略
当redo log空间满了之后又会从头开始以循环的方式进行覆盖式的写入。MySQL 支持三种将 redo log buffer 写入 redo log file 的时机可以通过 innodb_flush_log_at_trx_commit 参数配置各参数含义如下
0延迟写表示每次事务提交时都只是把 redo log 留在 redo log buffer 中开启一个后台线程每1s刷新一次到磁盘中 ;1实时写实时刷表示每次事务提交时都将 redo log 直接持久化到磁盘真正保证数据的持久性2实时写延迟刷表示每次事务提交时都只是把 redo log 写到 page cache具体的刷盘时机不确定。
除了上面几种机制外还有其它两种情况会把redo log buffer中的日志刷到磁盘。
定时处理有线程会定时(每隔 1 秒)把redo log buffer中的数据刷盘。根据空间处理redo log buffer 占用到了一定程度( innodb_log_buffer_size 设置的值一半)占这个时候也会把redo log buffer中的数据刷盘。
重做日志缓冲redo log
重做日志redo log是数据库的重要组成他保证了数据库宕机并重启后数据恢复的正确性。重做日志共有两个文件ib_logfile0和ib_logfile1。每个文件的大小一直且循环写入也就是说先写ib_logfile0写满之后再写ib_logfile1又写满后继续写ib_logfile0。 **redo log日志里面记录的主要是表空间数据页号偏移量修改几个字节的值具体的值。**根据你修改了数据页里的几个字节的值redo log就划分为了不同的类型MLOG_1BYTE类型的日志指的就是修改了1个字节的值MLOG_2BYTE类型的日志指的就是修改了2个字节的值以此类推还有修改了4个字节的值的日志类型修改了8个字节的日志类型。如果修改了一大串的值类型就是MLOG_WRITE_STRING,就是代表你一下子在哪个数据页的某个偏移量的位置插入或者修改了一大串的值。 所以redo log看起来的结构如下日志类型类似MLOG_1BYTE之类的数据)表空间ID数据页号数据页中的偏移量,修改数据长度MLOG_WRITE_STRING类型的才有具体修改的数据。
当数据库修改页时会将修改信息放入重做日志缓冲区然后按一定频率默认每秒一次写入到重做日志文件重做日志缓冲区一般不需要设置很大只要保证每秒产生的事务量在这个缓冲区大小内即可缓冲区大小可以通过参数innodb_log_buffer_size配置默认为8MB。
写入触发
一般情况下对于通常的事务提交分为三个阶段
事务准备提交事务提交过程中事务提交完成
**主要过程是在事务提交时候 会发生强制的将 redo log buffer的日志缓存的数据强制写入 redo log file中 通常会调用一次操作系统的fsync()的操作。**其中还会经过操作系统的内核空间 OS buffer 因为MySQL的进行和日志缓存都工作在操作系统中环境下
本质
事务提交的过程中必须将日志缓存的数据持久化到磁盘的日志文件中期间还需要经过操作系统的 “内核空间缓存区”也就是OS Buffer区域Redo log从用户空间的 Log buffer 写入磁盘的Redo Log文件时需要要内核空间的OS buffer日志文件没有使用 O_DIRECT标识如果有这个标识就可以不经过这个os buffer的内核空间直接写入磁盘数据
问题
1为什么不直接修改磁盘中的数据
因为直接修改磁盘数据的话它是随机IO修改的数据分布在磁盘中不同的位置需要来回的查找所以命中率低消耗大而且一个小小的修改就不得不将整个页刷新到磁盘利用率低
与之相对的是顺序IO磁盘的数据分布在磁盘的一块所以省去了查找的过程节省寻道时间。使用后台线程以一定的频率去刷新磁盘可以降低随机IO的频率增加吞吐量这是使用buffer pool的根本原因。
2redo log一定能保证事务的持久性吗
不一定这要根据redo log的刷盘策略决定因为redo log buffer同样是在内存中如果提交事务之后redo log buffer还没来得及将数据刷新到redo log file进行持久化此时发生宕机照样会丢失数据。
刷盘写入策略。
3页修改之后为什么不直接刷盘呢
InnoDB 页的大小一般为 16KB而页又是磁盘和内存交互的基本单位。这就导致即使我们只修改了页中的几个字节数据一次刷盘操作也需要将 16KB 大小的页整个都刷新到磁盘中。而且这些修改的页可能并不相邻也就是说这还是随机 IO。
采用 redo log 的方式就可以避免这种性能问题因为 redo log 的刷盘性能很好。首先redo log 的写入属于顺序 IO。 其次一行 redo log 记录只占几十个字节。另外Buffer Pool 中的页脏页在某些情况下比如 redo log 快写满了也会进行刷盘操作。不过这里的刷盘操作会合并写入更高效地顺序写入到磁盘。
4什么情况下会将缓冲区内容写入到重做日志中
1主线程Master Thread每秒会写入一次
2每个事务提交时会写入一次
3当重做日志缓冲池剩余空间小于50%时会写入一次
undo log
undo log也属于引擎层(innodb)的日志由上可知redo log 和undo log的核心是为了保证innodb事务机制中的持久性和原子性事务提交成功由redo log保证数据持久性而事务可以进行回滚从而保证事务操作原子性则是通过undo log 来保证的。
应用场景
1事务回滚
后台线程会不定时的去刷新buffer pool中的数据到磁盘但是如果该事务执行期间出现各种错误(宕机)或者执行rollback语句那么前面刷进去的操作都是需要回滚的保证原子性undo log就是提供事务回滚的。
2MVCC
**在内部实现中InnoDB 通过数据行的 DB_TRX_ID 事务ID 和 Read View 来判断数据的可见性如不可见则通过数据行的 DB_ROLL_PTR 回滚指针 找到 undo log 的日志版本链做比较即遍历链表中的事务ID直到找到满足条件的DBTRXID,这个DBTRXID所在的旧记录就是当前事务能看到的最新老版本数据。**从中分析出该行记录以前的数据版本是怎样的从而让用户能够读取到当前事务操作之前的数据——快照读。
MVCC 的实现依赖于隐藏字段自增ID、事务ID、回滚指针、Read View、undo log。
undo log 数据格式
undo log 数据主要分两类
1insert undo log
insert 操作的记录只对事务本身可见对其他事务不可见(这是事务隔离性的要求)故该insert undo log可以在事务提交后直接删除不需要进行purge操作。
2update undo log
update undo log记录的是对delete和update操作产生的undo log。该undo log可能需要提供MVCC机制因此不能在事务提交时就进行删除。提交时放入undo log链表等待purge线程进行最后的删除。
在InnoDB存储引擎中undo log使用rollback segment回滚段进行存储每个回滚段包含了1024个undo log segment。MySQL5.5之后一共有128个回滚段。即总共可以记录128 * 1024个undo操作。
问题
1undo log 如何保证事务的原子性
每一个事务对数据的修改都会被记录到 undo log 当执行事务过程中出现错误或者需要执行回滚操作的话MySQL 可以利用 undo log 将数据恢复到事务开始之前的状态。undo log 属于逻辑日志记录的是 SQL 语句比如说事务执行一条 DELETE 语句那 undo log 就会记录一条相对应的 INSERT 语句。
2除了保证事务的原子性undo log 还有什么用
InnoDB存储引擎中 MVCC 的实现用到了 undo log 。当用户读取一行记录时若该记录已经被其他事务占用当前事务可以通过undo log读取之前的行版本信息以此实现非锁定读取。
总结
binlog 是MySQL server层的日志而redo log 和undo log都是引擎层InnoDB的日志要换其他数据引擎那么就未必有redo log和undo log了。
它的设计目标是支持innodb的“事务”的特性事务ACID特性分别是原子性、一致性、隔离性、持久性 一致性是事务的最终追求的目标。隔离性是通过MVCC锁机制来实现的而事务的原子性和持久性则是通过redo log 和undo log来保障的。
redo log让InnoDB有了崩溃恢复的能力binlog保证了MySQL集群架构的数据一致性。
在执行更新语句过程会记录redo log与binlog两块日志以基本的事务为单位redo log在事务执行过程中可以不断写入而binlog只有在提交事务时才写入所以redo log与binlog的写入时机不一样。
MySQL 三大日志中bin log属于Server的有缓冲buffer缓冲区域在事务线程的内存中。redo log undo log 属于innoDB存储引擎有缓冲buffer在内存缓冲区域由 LRU 链表和 Flush 链表管理。undo log 存储在引擎内部采用rollback segment回滚段进行存储。