在数据库应用编程中,通常为了修改语句的执行效率会将数据库的自动提交模式关闭,然后采用事务的方式提交更改。然后问题就来了,下面是一段被精简的程序,用的是Mysql C API:

MYSQL *conn=mysql_init(NULL);
    mysql_real_connect(conn,"198.120.0.199","shr","shr","sp5000",3306,NULL,0);
    int num = 2;
    char sql[512] = "select name from aaa";
    MYSQL_STMT *stmt;
    MYSQL_BIND  column[1];
    mysql_autocommit(conn, 0);  //设置自动提交关闭
   stmt = mysql_stmt_init(conn);
   for(int jj=0;jj<100;jj++){
        mysql_stmt_prepare(stmt,sql,strlen(sql);
        mysql_stmt_execute(stmt);
        memset(column,0,sizeof(column));
        unsigned long length[1];
        my_bool is_null[1];
        char name[100];

        column[0].buffer_type = MYSQL_TYPE_VAR_STRING;
        column[0].buffer =(char *)name;
        column[0].buffer_length = 100;
        column[0].is_null= &is_null[0];
        column[0].length = &length[0];

        mysql_stmt_bind_result(stmt,column);
        mysql_stmt_store_result(stmt);
        while(true){
            rel=mysql_stmt_fetch(stmt);
            if(rel!=0)  break;
            printf("data: %s  \n",name);
        }
        getchar();
    }
	mysql_stmt_free_result(stmt);
    mysql_stmt_close(stmt);



mysql默认是自动提交,通过 mysql_autocommit(conn, 0)将自动关闭关闭。在循环查询中发现每次查询的结果都一样!尽管在其他地方修改了这张表并提交成功,当然每次程序重新启动的第一次还是能正确读取到数据。我一开始以为是mysql缓存带来的影响,因此将mysql的缓存关闭,但是发现还是同样的问题。好吧接着我索性就把


[i]stmt =mysql_stmt_init(conn);


mysql_stmt_free_result(stmt);


mysql_stmt_close(stmt);[/i]这三句代码移动到了循环内部,我每次生成新的查询对象,但是结果还是让我失望了。百思不得其解时我注释掉了所有能注释的语句,最终被我注释了 mysql_autocommit(conn, 0),然后一切都正常了,每次查询都是最新的表内容。


自动提交对select竟然也有影响!但是我又不能不禁用自动提交,如何解决这个问题呢。因为程序是从oracle换成mysql而改写的,提一下oracle,程序采用的是OCI库,其中OCIStmtExecute执行sql语句时通过第八个参数(oci的函数参数都是多的...)mode来决定立即提交还是等显示调用commit后提交,默认的是非自动提交,对于select语句参数同样设置的是default模式,的确select语句需要提交吗?在各种数据库的查询过程中,我们敲一行select语句之后并不需要commit,大多数数据库都是这样的。


但是mysql偏偏不是这样,难道真的要提交,于是我在[i]mysql_stmt_prepare(stmt,sql,strlen(sql);[/i]之后添加了提交代码: [i]mysql_commit(conn);[/i]问题顿时解决了,再循环查询中数据库的变动也能立即查询到了!


然后我打开mysql终端测试了下基本的查询,发现mysql cmd中存在同样的现象。大家可以根据我下面的步骤简单的测试下:打开终端A连上mysql,对于每个连接其默认的提交模式是自动提交,可输入命令show variables like 'autocommit';查看其默认是


+---------------+-------+


| Variable_name | Value |


+---------------+-------+


| autocommit | ON |


+---------------+-------+


输入命令set session autocommit = 0;将自动提交关闭,这时再查看参数为OFF,然后查询一张表;另开一个终端B对表数据进行修改并提交;返回终端A重复查询,可以发现其结果始终未变!然后默默的敲上commit;再次查询一次结果才是最新的表数据!也就是说我们查询一个表需要select....;commit;select....;这样的语句才能实时查询出结果!Mysql版本是5.5。


来看一下oracle,sqlplus连上数据库,输入show autocommit,显示默认为OFF(如果为ON,通过et autocommit off关闭),重复上面的测试,oracle虽然自动提交为OFF但是对于select并未有mysql的现象。


对于select读操作,oracle和mysql在自动提交设置关闭的情况下有着不同的处理,读操作是否需要提交,读虽然也算的上是一个事务,但是就像select....;commit;select....;这样才能查到正确数据的写法未免让人感觉别扭!先记住吧,以后有时间试下MYSQL C++ 类库或JDBC,看下是否有改变。