以前只知道数据库的增删改查,熟用create 、insert into、update、delete from、select等。平常自己一条一条用起来自我感觉良好,根本不会出现什么问题。可是一旦与真实的产品结合起来,就没有想的那么简单了。产品需要保证数据的可靠性和稳定性,得应对并发情况,毕竟产品不是一个人玩。这很容易让人想到”锁“这个东西,编程的人都知道,多线程的时候,会采用“加锁”“解锁”的方式来保证共享数据不会乱,那对于数据库呢?其实数据库也有“锁”,这就涉及到数据库”事务“的概念。



数据库中的“锁”机制。


共享锁:由读表操作加上的锁,其他操作只能读,不能写。


排它锁:由写表操作加上的锁,其他操作既不能读也不能写。


锁的范围,可以针对 表,也可以针对行,这样就有了:


表共享锁、行共享锁、表排它锁,行排它锁。




利用数据库的锁机制,生成了四种隔离策略,它们分别是:


1、未提交读(READUNCOMMITTED)。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)。
2、提交读(READCOMMITTED)。本事务读取到的是最新的数据(其他事务提交后的)。问题是,在同一个事务里,前后两次相同的SELECT会读到不同的结果(不重复读)。
3、可重复读(REPEATABLEREAD)。在同一个事务里,SELECT的结果是事务开始时时间点的状态,因此,同样的SELECT操作读到的结果会是一致的。但是,会有幻读现象。
4、串行化(SERIALIZABLE)。读操作会隐式获取共享锁,可以保证不同事务间的互斥。


InnoDB存储引擎默认是重复读的隔离策略,所以,我个人觉得可以这样理解:我们使用InnoDB存储引擎建表时,我们就已经考虑到了并发操作的情况,而可重复读隔离策略就相当于打包的锁机制,形成的一种策略,当我们把隔离策略设置成它的时候,就相当于在利用此策略解决并发问题。个人一般不自己去定义利用锁定义策略,因为定义不好的话,容易出现死锁等问题。所以,在开发过程中,根据实际情况设置一下隔离策略就行了。



什么是事务?


事务就是逻辑上的一组操作,这一组操作要么都成功,要么都失败,以保证数据库里的数据安全。以数据库插入操作举例,有时候想在某张表中插入一条记录的时候,往往需要在另一张表里要先插入一条记录,这时候,在这两个表里插入记录就组成了一个事务,要么两个表都插入成功,如果这两张表有一张插入出现问题,那么两张表都需要保持插入之前的状态。



MySQL事务处理的方法:


MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!我们可以通过
      set autocommit=0   禁止自动提交
      set autocommit=1 开启自动提交


下面是MySQL API函数:


//连接数据库
	MYSQL *conn;
	conn = mysql_init(NULL);
	
	if(mysql_real_connect(conn,DataBaseIP,  DataBaseUser, DataBasePwd,DataBaseDatabase, 0, NULL, 0))
	{
		mysql_autocommit(conn,0);//禁止自动提交
	}
//..............(执行一系列QUERY语句),每一条执行完之后,判断是否执行成功,如果执行失败,则在那一条语句后面,用mysql_rollback(conn);回滚到之前的状态。
	//如果所有语句都执行成功
	//则mysql_commit(conn);确认提交




但是使用事务管理得有一个前提条件:



表的存储引擎必须是InnoDB(mysql的默认存储引擎)。



查看某个表的存储引擎:show create table 表名;





梳理一下:



我们要处理并发,又懒得自己去设计策略,那就在建表时使用InnoDB,为什么呢?因为它支持事务处理。



为什么需要事务处理呢?因为事务处理可以设置不同的隔离策略解决并发问题,省了我们自己根据锁机制去设计并发控制策略。



mysql建表默认存储引擎InnoDB,默认隔离策略是“可重复读”。



这样,我们只需将事务提交设置为手动提交即可。



什么时候提交?一个事务中的操作都没错的时候我们就提交。