Linux下MySQL使用InnoDB引擎笔记

 

前言:把日常工作以及学习过程中遇到的问题,常记笔记总结我觉得是非常有必要的,不仅可以方便以后在类似过程中遇到同样问题方便查找和解决,也便于其他需要帮助的人们可少找弯路!

 

一.简介:
1.最近在Linux下使用MySQL数据库时,为了支持事务操作需要用到InnoDB引擎,对于表中处理的插入,更新等操作失败时
,回滚前面不应该完成的操作是必须的.

 

2.一般MySQL默认的数据库引擎是MyISAM,不支持事务和外键,则可使用支持事务和外键的InnoDB引擎.关于如何在Linux下设置MySQL默认引擎InnoDB请参照我前面写的一篇文章小结

http://blog.csdn.net/sunrier/article/details/7475403

 

3.本笔记着重讲解MySQL的autocommit变量,如何在数据库中设置自动提交,禁止自动提交,如何在对表操作失败后回滚,对表操作成功后提交事务!

 

二.操作方法
MySQL的autocommit默认是打开的(ON为打开,OFF为关闭或者表示成1为打开,0为关闭)
打开或关闭即是打开自动提交或者关闭自动提交

1.MySQL命令:

方法1:
1.11)如果是支持事务的引擎,如InnoDB则有系统参数设置是否自动commit,查看参数如下:
   mysql> show variables like '%autocommit%';
   +---------------+-------+
   | Variable_name | Value |
   +---------------+-------+
   | autocommit    | ON    |
   +---------------+-------+
   1 row in set (0.01 sec)

   mysql>

  显示结果为ON,表示事务自动提交,即不用手工去commit。当然,你可以设置其为OFF,然后自己手工去commit。

1.12)打开和关闭自动提交功能命令:
   关闭自动提交功能命令
   mysql> set session autocommit=OFF; 
    
   mysql>
   或者
   mysql> set session autocommit=off;
   Query OK, 0 rows affected (0.00 sec)
 
   mysql>
   (注:off不区分大小写)
  
   设置后再次查看:
   mysql> show variables like '%autocommit%';
   +---------------+-------+
   | Variable_name | Value |
   +---------------+-------+
   | autocommit    | OFF    |
   +---------------+-------+
   1 row in set (0.01 sec)

   mysql>
  
   可猜测mysql> set session autocommit=on;应该为打开自动提交功能,不过猜是猜的,最好还是实践下这个命令打
开自动提交功能命令
   mysql> set session autocommit=ON; 
    
   mysql>  

   设置后再次查看:
   mysql> show variables like '%autocommit%';
   +---------------+-------+
   | Variable_name | Value |
   +---------------+-------+
   | autocommit    | ON    |
   +---------------+-------+
   1 row in set (0.01 sec)

   mysql>

   注:如果退出MySQL,下次登陆MySQL后autocommit还会自动设置为默认的变量,这里即autocommit为ON,事务自动提交
  

方法2:
1.21)如果你在刚才上面方法1.11)中查看参数出现下面的情况:
   mysql> show variables like '%autocommit%';
   Empty set (0.00 sec)

   mysql>
   这个情况在我装的虚拟机上就无法查看,然后在公司的服务器上安装的MySQL就没问题(注1.1X为公司的MySQL)。
   现在关于为什么会出现两种不同的结果,笔者还没解决这个问题,猜测可能是因为数据库版本的不同可能查看的命令
不一样,我最终在网上查找到例外的方法在命令下查看和设置autocommit变量

1.22)查看和设置autocommit变量
   
    查看autocommit变量
    mysql> select @@autocommit;
    +--------------+
    | @@autocommit |
    +--------------+
    |            1 |
    +--------------+
    1 row in set (0.00 sec)

    mysql>
    注:autocommit为1表示打开自动提交   

   
    设置autocommit变量
    mysql> set session autocommit=off;
    Query OK, 0 rows affected (0.00 sec)

    mysql> select @@autocommit;
    +--------------+
    | @@autocommit |
    +--------------+
    |            0 |
    +--------------+
    1 row in set (0.00 sec)

    mysql>
    注:autocommit为0表示关闭自动提交
   
2.MySQL的配置文件my.cnf:
  修改autocommit变量也可以通过修改配置文件my.cnf来关闭autocommit
  [mysqld]
  init_connect='SET autocommit=0'  //在my.cnf文件[mysqld]下面加上这句
 
3.MySQL数据库程序中使用C的API函数:

  切换autocommit模式,ON/OFF:
  my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)
  如果模式为"1",启用autocommit模式;如果模式为"0",禁止autocommit模式.
  返回值:如果成功返回0;如果出现错误返回非0值.


  回滚当前事务:
  my_bool mysql_rollback(MYSQL *mysql)
  该函数的动作取决于completion_type系统变量的值.尤其是如果completion_type的值为"2",终结事务后,服务器将
执行释放操作,并关闭客户端连接.客户端程序应调用mysql_close(),从客户端一侧关闭连接.
  返回值:如果成功返回0;如果出现错误返回非0值.


  提交当前事务:
  my_bool mysql_commit(MYSQL *mysql)
  该函数的动作受completion_type系统变量的值控制.尤其是如果completion_type的值为2,终结事务并关闭客户端连
接后,服务器将执行释放操作.客户端程序应调用mysql_close(),从客户端一侧关闭连接.
  返回值:如果成功返回0;如果出现错误返回非0值. 


三.实例说明:
1.MySQL下命令实例(注:student为我的MySQL数据库test中先前已经创建的一个student表信息):

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
+--------+---------+------+
6 rows in set (0.00 sec)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

mysql>
 
从上面可以看出此时数据库autocommit为1也就是自动提交
下面我想插入一个学生信息学号,名字,年龄分别是7,Nicky,22

mysql> insert into student values (7,"Nicky",22);
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
+--------+---------+------+
7 rows in set (0.00 sec)

mysql>

从MySQL插入命令后,执行查询结果可以看出,刚才插入的一条学生记录(7,"Nicky",22)已经插入到表里面,也许你为了保证执行结果确实是这样,你可能先退出MySQL,再次进入MySQL再查询下,出于这样的本能,我也是这样做的

mysql> exit
Bye
[root@localhost ~]# mysql -uroot -predhat test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11 to server version: 5.0.22

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
+--------+---------+------+
7 rows in set (0.00 sec)

mysql>

这样可以确信刚才那条学生记录已经确实插入到数据库test的student表里了.

开始主要的环节:

mysql> set session autocommit=off;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            0 |
+--------------+
1 row in set (0.00 sec)

mysql>

从上面可以看出此时数据库变量autocommit已经被设置为0也就是禁止自动提交
下面我想插入一个学生信息学号,名字,年龄分别是8,Jerry,21

mysql> insert into student values (8,"Jerry",21);
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
|      8 | Jerry   |   21 |
+--------+---------+------+
8 rows in set (0.00 sec)

mysql>

从MySQL插入命令后,执行查询结果可以看出,刚才插入的那条学生记录(8,"Jerry",21)也插入到表里面了。
也许你还是为了保证执行结果之外,你可能先退出MySQL,再次进入MySQL再查询下

[root@localhost ~]# mysql -uroot -predhat test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 12 to server version: 5.0.22

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
+--------+---------+------+
7 rows in set (0.00 sec)

mysql>

可以看出刚才那条学生记录(8,"Jerry",21)没有真正插入数据库test的student表里,这应该就是没有自动提交的效果,
说明了刚才设置变量autocommit为0时后来产生了作用。那么现在你也许会想,我现在设置了变量autocommit为0,不自
动提交执行结果了,那我应该怎么做才能使我执行的SQL语句还一样对数据库产生影响呢???基于这样的思考和探索下,对于我来说,我刚开始也一无所知,好在现在网络资源强大,我可以利用百度,google等可以利用的资源, 在网上找到了不少相关的知识介绍
发现了下面两个SQL命令:
mysql> rollback;

mysql> commit;

从字面意思上我们可以猜出了它们的大概意思rollback即回滚,commit即提交.现在回到刚才没有插入成功的那条记录那,为了我能够在数据库中变量autocommit设置为0的情况下,执行SQL命令也能对数据库产生影响,那就需要在执行DML的SQL命令后,执行一个commit提交命令

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

mysql> set session autocommit=off;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            0 |
+--------------+
1 row in set (0.00 sec)

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
+--------+---------+------+
7 rows in set (0.00 sec)

mysql>

上面为重新设置和查看,可以发现autocommit设置为0

mysql> insert into student values (8,"Jerry",21);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
|      8 | Jerry   |   21 |
+--------+---------+------+
8 rows in set (0.00 sec)

mysql> exit
Bye
[root@localhost ~]# mysql -uroot -predhat test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 13 to server version: 5.0.22

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
|      8 | Jerry   |   21 |
+--------+---------+------+
8 rows in set (0.00 sec)

mysql>

这样可以确信刚才那条学生记录(8,"Jerry",21)已经确实插入到数据库test的student表里了.

总结:在数据库中autocommit设置为0的情况下,所有的SQL执行命令的结果在遇到commit命令之后才真正提交到数据库中。也许到这会你发现我刚才说了两个SQL命令,到现在只说了commit命令,还有个rollback命令怎么用呢?

继续rollback命令

现在我想把数据库test的student表里名字为"Sunrier"这个小朋友的信息删除了。

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

mysql> set session autocommit=off;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            0 |
+--------------+
1 row in set (0.00 sec)

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   24 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
|      8 | Jerry   |   21 |
+--------+---------+------+
8 rows in set (0.00 sec)

mysql> delete from student where fname = "Sunrier";
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+--------+--------+------+
| studno | fname  | age  |
+--------+--------+------+
|      1 | Jack   |   67 |
|      2 | Tim    |   22 |
|      4 | Helen  |   26 |
|      5 | Tony   |   29 |
|      6 | Cherry |   30 |
|      7 | Nicky  |   22 |
|      8 | Jerry  |   21 |
+--------+--------+------+
7 rows in set (0.00 sec)

mysql>

从表里面可以看到名字为"Sunrier"的信息删除了,也许你可能马上后悔自己的选择,我找不到任何理由删除"Sunrier",这个小朋友,马上我着急了,我该如何找到该小朋友的原始信息呢,于是你眼前一亮,rollback这个命令,回滚,按照日常的用语是不是回过去的意思.于是你查询了下相关资料,好像可以哎,于是决定自己试试这个SQL命令

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   23 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
|      8 | Jerry   |   21 |
+--------+---------+------+
8 rows in set (0.00 sec)

mysql>

 

为了再次确认,退出MySQL后重新查看

mysql> exit
Bye
[root@localhost ~]# mysql -uroot -predhat test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 13 to server version: 5.0.22

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   23 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
|      8 | Jerry   |   21 |
+--------+---------+------+
8 rows in set (0.00 sec)

mysql>

 

从结果发现,名字为"Sunrier"小朋友的信息又回来了,真是太高兴了.


2.MySQL下使用C的API实例(注:student为我的MySQL数据库test中先前已经创建的一个student表信息):

//dbproc.c

/*************************************************************       
    FileName : dbproc.c   
    FileFunc : MySQL数据库事务操作     
    Version  : V0.1       
    Author   : Sunrier       
    Date     : 2012-06-19 
    Descp    : Linux下使用C语言访问MySQL函数        
*************************************************************/   
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>

static MYSQL s_my_connection;
static int s_iDbconnected = 0;//数据库连接标志 连接时为1,断开时为0

int mysql_login(char* pServer,char *pUser,char *pPassword,char *pDataBase)
{
	MYSQL *conn_ptr = NULL;
	int iRetCode = -1;
	unsigned int uiTimeOut = 7;

	if( s_iDbconnected )
		return 0;
		
	conn_ptr = mysql_init(&s_my_connection);
	if( !conn_ptr )
	{
		fprintf(stderr,"mysql_init failed ! \n");
		return EXIT_FAILURE;
	}

	iRetCode = mysql_options(&s_my_connection,MYSQL_OPT_CONNECT_TIMEOUT,(const char *)&uiTimeOut);
	if( iRetCode  )
	{
		fprintf(stderr,"MySQL Connection is timeout! \n");
		return EXIT_FAILURE;
	}
	
	conn_ptr = NULL;
	conn_ptr = mysql_real_connect(&s_my_connection,pServer,pUser,pPassword,pDataBase,0,NULL,0);
	if( conn_ptr )
	{
		printf("MySQL Connection success!\n");
		s_iDbconnected = 1;		
	}
	else
	{
		fprintf(stderr,"MySQL Connection failed!\n");
		if( mysql_errno(&s_my_connection) )
		{
			fprintf(stderr,"Connection error %d: %s!\n",mysql_errno(&s_my_connection),mysql_error(&s_my_connection));
			return EXIT_FAILURE;
		}
	}
	
	return EXIT_SUCCESS;
}


void mysql_logout( void )
{
	if( s_iDbconnected )
		mysql_close(&s_my_connection);//关闭连接  
	s_iDbconnected = 0 ;
}

//ucMode = 1启动自动模式,一般为默认模式
//ucMode = 0禁止autocommit模式
int mysql_commitmode(unsigned char ucMode)
{
	int iRetCode = -1;
	
	iRetCode = mysql_autocommit(&s_my_connection,ucMode);
	if( iRetCode )
	{
		fprintf(stderr,"Set autocommit %d-mode error ,sqlcode=[%d] : %s ",ucMode,mysql_errno(&s_my_connection),mysql_error(&s_my_connection));
		return EXIT_FAILURE;
	}
	else
	{
		return EXIT_SUCCESS;
	}
}
	

int mysql_proc( void )
{
	MYSQL *conn_ptr = NULL;
	MYSQL_RES *res_ptr = NULL;
	MYSQL_ROW sqlrow;
	int iTableRow = 0;
	int iRetCode = 1;
	char szSql[256];
	
	memset(szSql,0,sizeof(szSql));
	sprintf(szSql,"insert into student values(9,'Marry',23)");
	
	iRetCode = mysql_query(&s_my_connection,szSql);
	if( iRetCode )
	{
		fprintf(stderr,"insert error ,sqlcode=[%d] : %s ",mysql_errno(&s_my_connection),mysql_error(&s_my_connection));
		mysql_rollback(&s_my_connection);//回滚操作
		return EXIT_FAILURE;
	}
	
	mysql_commit(&s_my_connection);//提交操作(即手动提交)
	return EXIT_SUCCESS;
}




 

//demo.c

/*************************************************************       
    FileName : demo.c   
    FileFunc : MySQL数据库事务的测试     
    Version  : V0.1       
    Author   : Sunrier       
    Date     : 2012-06-19  
    Descp    : Linux下使用C语言访问MySQL函数        
*************************************************************/   
#include <stdio.h>

int main(int argc,char *argv[])
{
	int iRetCode = -1;
	char szServer[20] = "localhost";
	char szUser[20] = "Sunrier";
	char szPassword[20] = "redhat"
	char szDatabase[20] = "test";
	
	iRetCode = mysql_login(szServer,szUser,szPassword,szDatabase);
	
	if( iRetCode )
	{	
		system("service mysqld start");
		iRetCode = mysql_login(szServer,szUser,szPassword,szDatabase);
	}
	
	mysql_commitmode(0);//禁止autocommit模式
	
	iRetCode = mysql_proc();
	if( iRetCode )
	{
		printf("MySQL proc error !\n");
	}	
	 
	mysql_logout();
	
	return 0;
}


 

 

//makefile

#makefile
all:demo
demo:demo.c dbproc.c
	@gcc -I/usr/include/mysql $?  -L/usr/lib/mysql -lmysqlclient  -lz -lm -o demo
clean:
	@ls | grep -v ^makefile$$ | grep -v [.]c$$ | grep -v [.]h$$ | grep -v [.]sql$$ | xargs rm -rf
#makefile


 

[Sunrier@localhost MySql]$ ls
dbproc.c  demo.c  makefile
[Sunrier@localhost MySql]$ make
[Sunrier@localhost MySql]$ ls
dbproc.c  demo  demo.c  makefile
[Sunrier@localhost MySql]$ ./demo
MySQL Connection success!
[Sunrier@localhost MySql]$

执行前后查看数据库:

由于程序中设置了禁止autocommit模式,如想插入记录成功则需要提交函数,撤消操作则要回滚函数.

 

执行前数据库:

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   23 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
|      8 | Jerry   |   21 |
+--------+---------+------+
8 rows in set (0.00 sec)

 

执行后数据库:

mysql> select * from student;
+--------+---------+------+
| studno | fname   | age  |
+--------+---------+------+
|      1 | Jack    |   67 |
|      2 | Tim     |   22 |
|      3 | Sunrier |   23 |
|      4 | Helen   |   26 |
|      5 | Tony    |   29 |
|      6 | Cherry  |   30 |
|      7 | Nicky   |   22 |
|      8 | Jerry   |   21 |
|      9 | Marry   |   23 |
+--------+---------+------+
9 rows in set (0.00 sec)

mysql>

 

 

 

 

 

 

 

 //student.sql


drop database if exists test;
create database test;
use test;
create table student
(
	studno integer auto_increment not null primary key,
	fname varchar(30),
	age integer
);

-- )engine=innodb charset=gb2312;
--insert into student values ('',"Sunrier",22);
--insert into student values ('',"Tom",23);
--insert into student values ('',"Jerry",21);


 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章