C API向MySQL插入批量数据的快速方法——关于mysql_autocommit

MySQL默认的数据提交操作模式是自动提交模式(autocommit)。这就表示除非显式地开始一个事务,否则每个查询都被当做一个单独的事务自动执行。我们可以通过设置autocommit的值改变是否是自动提交autocommit模式。查询当前数据库事务提交方式的命令为:

mysql> show variables like ‘autocommit‘;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.04 sec)

其中“ON”代表autocommit模式为打开状态,使用MySQL C API关闭事务自动提交的代码为:

        MYSQL mysql;
        mysql_init(&mysql);
        if(!mysql_real_connect(&mysql, host, user, password, schema, port, NULL, 0))
        {
            printf("MySQL数据库连接失败。\n");
            return -1;
        }
        int set_cs_r = mysql_set_character_set(&mysql, "gbk");
        mysql_autocommit(&mysql, 0);

  MySQL默认的存储引擎是MyISAM,MyISAM存储引擎不支持事务处理,所以改变autocommit没有什么作用,InnoDB存储引擎支持事务处理。InnoDB表引擎下关闭mysql自动事务提交可以大大提高数据插入的效率,这是因为如果需要插入1000条数据,mysql会自动发起(提交)1000次的数据写入请求,如果把autocommit关闭掉,通过程序来控制,只要一次commit就可以搞定。示例代码(逻辑过程)如下:

int H_Utility::insertRecordsToMySQL(
    const char* dataFilePath,
    const char* host,
    const char* user,
    const char* password,
    const char* schema,
    const char* table,
    const int    port,
    const char* logFilePath)
{
    ifstream rpf;
    rpf.open(dataFilePath);
    int lineCount = 0;
    if (rpf.is_open())
    {
        MYSQL mysql;
        mysql_init(&mysql);
        if(!mysql_real_connect(&mysql, host, user, password, schema, port, NULL, 0))
        {
            printf("MySQL数据库连接失败。\n");
            return -1;
        }
        ofstream f1(logFilePath);
        if (!f1.is_open())
        {
            printf("日志文件创建失败!\n");
            return 0;
        }
        mysql_autocommit(&mysql, 0);//关闭自动提交
        char* out_text = new char[1024];
        int cursor = 0;
        while (!rpf.eof())
        {
            memset(out_text,0x00,1024);
            rpf.getline(out_text,1024);
            string str(out_text);
            if (str.length()>0)
            {
                lineCount++;
                if (lineCount>1)
                {
                    std::vector<string> strVec;
                    int cellCount = H_Utility::stringSplitToVector(str.c_str(), strVec, ",");
                    if (cellCount<3)
                    {
                        printf("第%d行数据不完整,写入失败:\n",lineCount);
                        f1<<str<<endl;
                        continue;
                    }
                    string sql_str = "";
                    sql_str.append("INSERT INTO `").append(SCHEMA_NAME).append("`.`").append(TABLE_NAME).append("` ");
                    sql_str.append("(id,name,birthday) values (");
                    sql_str.append(strVec[0]).append(",‘").append(strVec[1]).append("‘,");
                    sql_str.append("STR_TO_DATE(‘").append(strVec[31]).append("‘,‘%Y-%m-%d %H:%i:%s‘))");
                    int iSuccess = mysql_query(&mysql, sql_str.c_str());
                    if (iSuccess != 0)
                    {
                        const char *mysql_err = mysql_error(&mysql);
                        printf("%s\n",mysql_err);
                        f1<<str<<endl;
                    }
                    else
                    {
                        cursor++;
                    }
                    if (cursor==50000)//每50000条记录提交一次
                    {
                        mysql_commit(&mysql);
                        cursor = 0;
                        printf("%d\n",lineCount);
                    }
                }
            }
        }
        delete []out_text;
        rpf.close();
        f1.flush();
        f1.close();
        mysql_close(&mysql);
    }
    return lineCount;
}

  在本人笔记本电脑上(Thinkpad T430; i5-3380 CPU; 4G DDR3 RAM; 500G&7200RPM HDD; Win7 旗舰版 x64; MySQL 5.6 社区版)的测试结果为:上述代码往mysql中插入200万条记录(数据文件大小约为300M)耗时仅约为345秒,而逐条提交时运行约3小时仅仅写入了 不到50万条数据,由此可见在使用InnoDB数据引擎进行大数据量插入时,代码中必须对该问题进行优化。

时间: 2025-01-08 04:58:37

C API向MySQL插入批量数据的快速方法——关于mysql_autocommit的相关文章

mysql 插入/更新数据

mysql 插入/更新数据 INSERT 语句 1.一次性列出全部字段的值,例如: INSERT INTO student VALUES('Chenqi','M', 29); INSERT INTO student VALUES('Bush','M', 60),('Obama', 'M', 45); 允许同时插入多个数据行: 2.只对部分字段赋值 INSERT INTO student(name, sex) VALUES ('Abby', 'F'),('Joseph', 'M'); 没有在INS

C# 获取存在DataTable1不存在DataTable2的数据的快速方法

通过合并和获得改变两个方法获得差异的部分: dataTable1.AcceptChanges();dataTable1.Merge(dataTable2);DataTable changesTable = dataTable1.GetChanges(); 这样可以快速获得dataTable2中存在而dataTable1中不存在的行,反之可以用dataTable2合并dataTable1. C# 获取存在DataTable1不存在DataTable2的数据的快速方法

MySQL插入中文数据乱码问题

一.MySQL插入中文不乱码5中方法小结 方法一:登录mysql,先做“set names latin1;”,然后再执行更新语句或执行语句文件. 方法二:在aql文件中指定set names latin1; 然后登录mysql,通过如下命令执行. 方法三:在sql文件中指定set names latin1; 然后通过mysql命令导入数据 方法四:通过指定mysql命令的字符集参数实现--default-character-set=latin1 方法五:在配置文件里设置客户端及服务端相关参数 不

sqlite 插入批量数据优化

插入sqlite插入数据的方法 1,execSQL() 直接拼接sql语句 2,insert() 3,compileStatement()预处理 这三中方式插入数据相对较快依次是 compileStatement ,insert,execSQL 插入大量数据是加上事务处理 1 package com.example.natedb; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase

mysql插入图片数据

import java.sql.*; import java.util.Scanner; import java.io.*; public class mysql插入图片 { private static final File File = null; private static String String; public static Connection getConn() { Connection conn = null; try { Class.forName("com.mysql.j

SQL Server 2012中快速插入批量数据的示例及疑惑

SQL Server 2008中SQL应用系列--目录索引 今天在做一个案例演示时,在SQL Server 2012中使用Insert语句插入1万条数据,结果遇到了一个奇怪的现象,现将过程分享出来,以供有兴趣的同学参考. 附:我的测试环境为:SQL Server 2012,命名实例 Microsoft SQL Server 2012 - 11.0.2100.60 (Intel X86) Feb 10 2012 19:13:17 Copyright (c) Microsoft Corporatio

Django使用Mysql已存在数据表的方法

在网上爬取了网上的一些数据,存储在了mysql数据库中,想使用Django将数据展示出来,在网上看到都是使用Django的models和makemigration,migrate命令来创建新表,并使用. 可是我的数据已经存在了已经创建好,并且已经存储有数据了,不能再重新创建新表了. 了解Django的表明和models名称的映射关系就可以让Django使用已经存在的表. 假如在Django存在models如下: from django.db import models Create your m

mysql 插入汉字出现问号 解决方法

mysql中文显示乱码或者问号是因为选用的编码不对或者编码不一致造成的,最简单的方法就是修改mysql的配置文件my.cnf.在[mydqld]和[client]段加入 default-character-set=utf8 (有的版本不支持default-character-set=utf8,用character_set_server=utf8来取代 default-character-set=utf8即可) 注:如果没有[client]就手工加入[client]段 ( 5.0以上版本修改方法:

mysql客户端导出数据表的方法

方法一 php教程用mysql的命令和shell select * into outfile './bestlovesky.xls' from bestlovesky where 1 order by id desc  limit 0, 50; 方法二 把bestlovesky.xls以文本方式打开,然后另存为,在编码选择ansi编码,保存 echo "select id,name from bestlovesky where 1 order by id desc limit 0, 50;&qu