• mysql 批处理 innodb_flush_at_trx_commit 测试分析


    背景

      有个业务场景是需要大量写入库的,就会出现一个问题,日志文件很快就满了,dba扩展,扩展没多久又满...后来我们分析代码,发现有个小可爱, 每条每条的commit,这样做不仅产生大量的redo log和undo log,还会很慢。下面我们测试下为什么会慢。仅从InnoDB日志同步这块测试。线程池呀,binlog,索引创建等等因素先不考虑。

    innodb_flush_at_trx_commit 

      控制缓存日志刷新到磁盘的策略。有三种策略如下:

    innodb_flush_log_at_trx_commit =1   每次事务提交从log buffer 提交到 logfile on disk中,默认策略
    innodb_flush_log_at_trx_commit =0   每秒从log buffer 提交到 Log  file on disk中,最多丢失1s
    innodb_flush_log_at_trx_commit =2   0,1值的混合,即每秒提交一次,每次会话提交也会同步到Log file 中去。

    创建测试表

    表不是我写的,从网上摘得,也是够懒的。

    drop table if exists test_flush_log;
    create table test_flush_log(id int,name char(50))engine=innodb;

    创建存储过程

    存储过程也是从网上摘得,批量的是根据单次的调整的。

    # 批量提交
    drop procedure if exists proc_batch;
    delimiter $$
    create procedure proc_batch(i int)
    begin
        declare s int default 1;
        declare c char(50) default repeat('a',50);
        start transaction;
        while s<=i do
            
            insert into test_flush_log values(null,c);
            set s=s+1;
        end while;
         commit;
    end$$
    delimiter ;
    #  单次提交
    drop procedure if exists proc;
    delimiter $$
    create procedure proc(i int)
    begin
        declare s int default 1;
        declare c char(50) default repeat('a',50);
        while s<=i do
            start transaction;
            insert into test_flush_log values(null,c);
            commit;
            set s=s+1;
        end while;
    end$$
    delimiter ;

    测试场景

    ##############innodb_flush_log_at_trx_commit =1   默认策略就是1
    
    [mysql> call proc(100000);
    Query OK, 0 rows affected (12.95 sec)
    
    [mysql> call proc_batch(100000);
    Query OK, 0 rows affected (0.97 sec)
    
    
    ##############innodb_flush_log_at_trx_commit =0
    
    set @@global.innodb_flush_log_at_trx_commit
    = 0; [mysql> call proc(100000); Query OK, 0 rows affected (1.60 sec) [mysql> call proc_batch(100000); Query OK, 0 rows affected (0.95 sec) ##############innodb_flush_log_at_trx_commit =2
    [mysql> set @@global.innodb_flush_log_at_trx_commit =2; [mysql> call proc(100000); Query OK, 0 rows affected (2.99 sec) [mysql> call proc_batch(100000); Query OK, 0 rows affected (0.96 sec)
    • 批处理比单数据提交快
    • 在大量的写情况下 =1策略最慢,但是最安全。
    • 在每次事务提交过程中,都会涉及到redo log undo log 缓存同步到磁盘,调用fsync函数,会出现IO等待。

    解决方案

    • 修改单次改为批量,设置会话级别的innodb_flush_log_at_trx_commit=0策略,当然看实际业务要求。
    • 使用固盘,加快IO读写。

      

    参考文档:

  • 相关阅读:
    转贴:Asp.Net 学习资源列表
    实现简单的写字板
    android绘图—Paint path 旋转
    Eclipse Android编程快捷键
    android Bitmap学习总结
    各种颜色对应的十六进制数
    Android surfaceView 与View 的区别
    SQLite设置_id自增的方法
    数据库表外键设置
    android自定义View的用法
  • 原文地址:https://www.cnblogs.com/--net/p/12748990.html
Copyright © 2020-2023  润新知