Mysql 自动提交对查询带来的影响 在数据库应用编程中,通常为了修改语句的执行效率会将数据库的自动提交模式关闭,然后采用事务的方式提交更改。然后问题就来了,下面是一段被精简的程序,用的是Mysql C API: MYSQL *conn=mysql_init(NULL); mysql_real_conn
Mysql 自动提交对查询带来的影响
在数据库应用编程中,通常为了修改语句的执行效率会将数据库的自动提交模式关闭,然后采用事务的方式提交更改。然后问题就来了,下面是一段被精简的程序,用的是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的缓存关闭,但是发现还是同样的问题。好吧接着我索性就把
stmt =mysql_stmt_init(conn);
mysql_stmt_free_result(stmt);
mysql_stmt_close(stmt);这三句代码移动到了循环内部,我每次生成新的查询对象,但是结果还是让我失望了。百思不得其解时我注释掉了所有能注释的语句,最终被我注释了 mysql_autocommit(conn, 0),然后一切都正常了,每次查询都是最新的表内容。
自动提交对select竟然也有影响!但是我又不能不禁用自动提交,如何解决这个问题呢。因为程序是从oracle换成mysql而改写的,提一下oracle,程序采用的是OCI库,其中OCIStmtExecute执行sql语句时通过第八个参数(oci的函数参数都是多的...)mode来决定立即提交还是等显示调用commit后提交,默认的是非自动提交,对于select语句参数同样设置的是default模式,的确select语句需要提交吗?在各种数据库的查询过程中,我们敲一行select语句之后并不需要commit,大多数数据库都是这样的。
但是mysql偏偏不是这样,难道真的要提交,于是我在
mysql_stmt_prepare(stmt,sql,strlen(sql);之后添加了提交代码:
mysql_commit(conn);问题顿时解决了,再循环查询中数据库的变动也能立即查询到了!
然后我打开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,看下是否有改变。