mysql工作日的逻辑

经工作需要,要用到根据一个时间要在之后3个工作日修改状态,想了好久,终于想出了一个方法,感觉有点low

1.首先创建一张节假日表

CREATE TABLE `bs_holidays` (
  `h_id` date NOT NULL COMMENT '法定節假日日期',
  `the_year` varchar(10) COLLATE utf8_bin DEFAULT NULL COMMENT '年份',
  `days_ide` bigint(20) DEFAULT NULL COMMENT '節假日標識ID',
  `daysname` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '節假日標識名稱',
  `crter` bigint(20) DEFAULT NULL COMMENT '創建人',
  `crt_date` datetime DEFAULT NULL COMMENT '創建日期',
  `crt_ip` varchar(15) COLLATE utf8_bin DEFAULT NULL COMMENT '創建人ip',
  `opper` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '修改人',
  `opp_date` date DEFAULT NULL COMMENT '修改日期',
  `opp_ip` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '修改人ip',
  PRIMARY KEY (`h_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='國家法定節假日記錄表';

2.通过面向过程(函数)写筛选工作日:

参数:_end  varchar(20),_delay int

返回类型:varchar(20)

BEGIN
    #Routine body goes here..
    #DECLARE _end datetime;
    DECLARE _reweek INT;
    DECLARE intNums INT;
    DECLARE i INT;
    SET i = 1;
    WHILE i<=_delay DO
        SELECT DAYOFWEEK(STR_TO_DATE(_end,'%Y-%m-%d')) INTO _reweek;  
        IF _reweek = 1 THEN
        SET _end =  DATE_ADD(_end,INTERVAL 1 DAY);  
        ELSEIF _reweek = 7 THEN 
      SET _end =  DATE_ADD(_end,INTERVAL 1 DAY);  
        ELSE  
            SELECT COUNT(t.h_id) INTO intNums FROM bs_holidays t WHERE t.h_id = _end;
            IF intNums = 0 THEN
                SET _end =  DATE_ADD(_end,INTERVAL 1 DAY);
                SET i = i+1;
            ELSE
                SET _end =  DATE_ADD(_end,INTERVAL 1 DAY);
            END IF;
        END IF;
    END WHILE;

    RETURN _end;
END

 

转载于:https://my.oschina.net/SimTao/blog/1554694

<think>我们正在讨论MySQL的三种日志文件。根据引用内容,MySQL的三种重要日志是: 1. 二进制日志(Binlog) 2. 重做日志(Redo Log) 3. 回滚日志(Undo Log) 但是,引用[1]和引用[4]提到了二进制日志(Binlog)和通用查询日志(General_log),而引用[2][3][4]则提到了Binlog、Undo Log和Redo Log。因此,我们主要关注这三种日志:Binlog、Redo Log、Undo Log。 下面我将详细解释这三种日志: ### 1. 二进制日志(Binlog) **作用**:记录所有对数据库的修改操作(DDL和DML),但不包括查询操作(如SELECT)。它用于数据复制(主从复制)和数据恢复。 **特点**: - 逻辑日志:记录的是SQL语句的原始逻辑(如UPDATE语句)。 - 以事件形式记录:每个事件包含事件发生的时间、位置等信息。 - 事务安全:在事务提交时次性写入。 - 有三种记录格式:STATEMENT(记录SQL语句)、ROW(记录每行数据的变更)、MIXED(混合模式)。 **写入机制**: - 事务提交时,将整个事务的Binlog写入到Binlog文件中。 - 通过参数`sync_binlog`控制刷盘策略(0:依赖操作系统;1:每次提交都刷盘;N:每N个事务刷盘)。 引用[1]和[4]中提到的Binlog记录的是对数据库有更新的操作,并且以Log event的形式记录。 ### 2. 重做日志(Redo Log) **作用**:确保事务的持久性。在事务提交时,先将修改操作写入Redo Log,即使系统崩溃,重启后可以根据Redo Log重做已经提交的事务,保证数据不丢失。 **特点**: - 物理日志:记录的是在数据页上所做的修改(如“在某个数据页的某个偏移量修改了几个字节”)。 - 循环写入:Redo Log文件是固定大小的,循环覆盖使用。 - 属于InnoDB存储引擎特有的日志。 **写入机制**: - 事务执行过程中,每执行条修改操作,都会先写入Redo Log Buffer(内存中)。 - 然后按照定策略(由`innodb_flush_log_at_trx_commit`控制)刷到磁盘的Redo Log文件: - 0:每秒写入并刷盘(可能丢失1秒数据)。 - 1:每次事务提交都刷盘(最安全,性能较低)。 - 2:每次提交写入操作系统缓存,每秒刷盘(折中)。 引用[3]提到Redo Log是物理日志,记录的是在数据页上的修改。 ### 3. 回滚日志(Undo Log) **作用**: - 提供回滚操作:在事务执行过程中,如果执行了修改操作,Undo Log会记录修改前的数据,用于事务回滚。 - 实现多版本并发控制(MVCC):通过Undo Log可以构建数据的历史版本,用于致性锁定读。 **特点**: - 逻辑日志:记录与修改操作相反的操作(如INSERT对应DELETE,UPDATE对应反向UPDATE)。 - 存储在特殊的Undo段中(位于系统表空间或独立的Undo表空间)。 - 在事务提交后,Undo Log不会立即删除,因为可能还有其他事务需要读取历史版本(通过MVCC)。 引用[2]和[3]提到Undo Log用于回滚,并且是逻辑日志。 ### 三种日志对比 | 特性 | Binlog | Redo Log | Undo Log | |--------------|---------------------|----------------------------|------------------------| | **日志类型** | 逻辑日志 | 物理日志 | 逻辑日志 | | **作用** | 复制、恢复 | 崩溃恢复,保证持久性 | 事务回滚、MVCC | | **存储引擎** | 所有引擎 | InnoDB特有 | InnoDB特有 | | **存储方式** | 追加写入(文件) | 循环写入(固定大小文件) | 存储在表空间 | | **生命周期** | 长期保存(可配置) | 事务提交后逐渐覆盖 | 事务提交后可能保留段时间(MVCC需要) | ### 协同工作示例(以更新操作为例) 1. **执行UPDATE语句**: - 首先,将原始数据(修改前)写入Undo Log(用于回滚和MVCC)。 - 然后,在内存中修改数据。 - 同时,将修改操作记录到Redo Log Buffer(内存中)。 2. **事务提交**: - 将Redo Log Buffer中的内容按策略刷到磁盘的Redo Log文件(保证持久性)。 - 将Binlog写入到Binlog文件(根据配置刷盘)。 - 旦Binlog写入完成,就标记事务提交完成。 3. **崩溃恢复**: - 重启后,先检查Redo Log,将已提交的事务重做(Redo)。 - 然后,利用Undo Log回滚未提交的事务。 > 注意:在MySQL内部,为了保证Binlog和Redo Log的致性,使用了**两阶段提交(2PC)**: > 1. Prepare阶段:将事务写入Redo Log(标记为Prepare状态)。 > 2. Commit阶段:写入Binlog,然后将Redo Log标记为Commit状态。 ### 配置建议 - **Binlog**:通常开启,用于备份和复制。建议设置`sync_binlog=1`和`innodb_support_xa=ON`(保证分布式事务致性)。 - **Redo Log**:调整大小(`innodb_log_file_size`)以减少刷盘频率,建议设置`innodb_flush_log_at_trx_commit=1`(安全)或`2`(性能折中)。 - **Undo Log**:建议开启独立的Undo表空间(`innodb_undo_tablespaces`)并设置自动清理(`innodb_undo_log_truncate=ON`)。 ### 总结 - **Binlog**:用于数据复制和基于时间点的恢复,逻辑日志。 - **Redo Log**:保证事务的持久性,物理日志,崩溃恢复的核心。 - **Undo Log**:用于事务回滚和MVCC,逻辑日志。 这三种日志共同保障了MySQL的事务特性(ACID)和高可用性。 §§相关问题§§ 1. Binlog的三种格式(STATEMENT, ROW, MIXED)各有什么优缺点? 2. 两阶段提交(2PC)在MySQL内部是如何保证Binlog和Redo Log致的? 3. 如何配置MySQL的日志系统以实现最佳的性能和数据安全平衡? 4. Undo Log在MVCC中的具体工作流程是怎样的?</think>### MySQL 三大核心日志文件详解 #### 1. **二进制日志(Binlog)** **核心作用**:记录所有**修改数据库结构的操作**(DDL/DML),用于数据复制(主从同步)和基于时间点的数据恢复[^1][^4]。 **核心特性**: ```mermaid graph LR A[执行UPDATE操作] --> B[记录SQL逻辑到Binlog] B --> C[存储为Log Event] C --> D[写入Binlog文件] ``` - **逻辑日志**:记录原始SQL语句(如 `UPDATE users SET name='Alice' WHERE id=1;`)[^3] - **文件格式**: - 按序列存储(如 `mysql-bin.000001`) - 包含多种Log Event类型: - `Query event`(DDL语句) - `Row event`(DML行级修改) - `Xid event`(事务提交标识)[^4] - **写入机制**: - 事务提交时批量写入 - 刷盘策略由 `sync_binlog` 控制(0=依赖OS,1=强致,N=N次提交后刷盘) - **应用场景**: - 主从数据同步 - 误删数据时通过 `mysqlbinlog` 工具恢复 #### 2. **重做日志(Redo Log)** **核心作用**:确保事务**持久性**,崩溃恢复时重做已提交事务的物理修改[^3]。 **核心特性**: ```mermaid graph TB A[事务修改数据] --> B[写入Redo Log Buffer] B --> C{刷盘策略} C -->|innodb_flush_log_at_trx_commit=1| D[每次提交刷盘] C -->|=0或2| E[异步刷盘] ``` - **物理日志**:记录数据页的物理修改(如“表空间XX的页YY偏移量ZZ更新为值AAA”)[^3] - **循环写入**: - 固定大小文件(默认 `ib_logfile0`,`ib_logfile1`) - 写满后覆盖最旧日志 - **崩溃恢复流程**: ```python def crash_recovery(): scan_redo_log() # 扫描未应用的日志 apply_physical_changes() # 重做物理修改 rollback_uncommitted() # 回滚未提交事务 ``` #### 3. **回滚日志(Undo Log)** **核心作用**:实现事务**原子性**,支持回滚操作和多版本并发控制(MVCC)[^2]。 **核心特性**: ```mermaid graph LR A[事务UPDATE操作] --> B[保存旧数据到Undo Log] B --> C[构建数据历史版本] C --> D[其他事务MVCC读取] ``` - **逻辑日志**:记录反向操作(如UPDATE前保存旧值 `name='Bob'`)[^3] - **存储位置**: - 系统表空间(`ibdata1`) - 或独立Undo表空间(MySQL 8.0+) - **生命周期**: - 事务提交后不立即删除(为MVCC保留) - 由后台线程 `purge_thread` 清理过期版本 --- ### 三大日志对比表 | 特性 | Binlog | Redo Log | Undo Log | |--------------------|---------------------|----------------------|----------------------| | **日志类型** | 逻辑日志 | 物理日志 | 逻辑日志 | | **主要作用** | 数据复制/时间点恢复 | 崩溃恢复保证持久性 | 事务回滚/MVCC支持 | | **存储位置** | 独立文件 | `ib_logfile0/1` | 表空间(ibdata1) | | **写入时机** | 事务提交后 | 事务执行中 | 数据修改前 | | **是否可关闭** | 可配置关闭 | 不可关闭(InnoDB核心)| 不可关闭 | | **典型应用场景** | 主从复制 | 宕机后数据恢复 | 事务回滚/致性读 | --- ### 协同工作流程(以UPDATE为例) 1. **执行UPDATE语句**: - Undo Log记录旧值(`name='Bob'`) - 内存中更新数据为 `name='Alice'` - Redo Log记录物理修改(页+偏移量+新值) 2. **事务提交**: - Redo Log刷盘(`innodb_flush_log_at_trx_commit=1`) - Binlog写入SQL逻辑并刷盘(`sync_binlog=1`) - 标记事务完成 3. **崩溃恢复**: - 用Redo Log重做已提交事务 - 用Undo Log回滚未提交事务 - 通过Binlog修复主从数据差异 > 💡 **关键机制**: > - **两阶段提交**:保证Binlog和Redo Log的致性(先写Redo Log Prepare状态 → 写Binlog → 写Redo Log Commit) > - **MVCC实现**:Undo Log构建数据历史版本链,实现锁定读[^2][^3] --- ### 配置建议 ```ini # my.cnf 关键配置 [mysqld] # Binlog log_bin = /var/lib/mysql/mysql-bin binlog_format = ROW # 推荐ROW格式避免主从不致 sync_binlog = 1 # 每次提交刷盘(强致) # Redo Log innodb_log_file_size = 4G # 增大日志文件减少刷盘频率 innodb_flush_log_at_trx_commit = 1 # 每次提交刷盘 # Undo Log innodb_undo_tablespaces = 3 # MySQL 8.0+ 独立表空间 innodb_max_undo_log_size = 2G ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值