点击>>MySQL下的存储引擎查看MySQL下的几种存储引擎。在几种存储引擎中,可以看到只有InnoDB存储引擎支持事务,那么本篇就来介绍InnoDB下支持的事务。
本篇目录
**************************************************************
* 事务是什么? *
* 事务遵循的四个特性 (AICD) *
* 事务中的基本操作 *
* 事务的四中隔离级别 *
* 通过设置隔离级别来保证事务的隔离性基本操作 *
**************************************************************
一、事务(transaction)
事务指的就是一种SQL语句的集合。
二、事务的四个特性
事务的原子性通过Undo log来保证。(Undo日志记录数据修改前的状态) 事务的持久性通过Redo log来保证。(Redo日志记录某数据块被修改后的值) 事务的隔离性通过设置隔离级别来保证。 事务的一直性通过Redo log来保证。 |
三、事务中的基本操作
(1)回滚:撤销指定SQL语句的功能。
mysql>rollback;
(2)提交:将未存储的SQL语句结果写到数据库表中。
mysql>commit;
(3)保留点:事务处理中设置的临时占位符。
mysql>savepoint XXX;
注意点:
1、不能回退select、create和drop语句。
2、事务提交是默认提交。每执行一条语句就把该语句当成一个事务进行提交。
3、当出现start transaction;语句时,隐式提交会关闭。
4、当rollback或者commit语句出现,事务自动关闭,隐式提交自动恢复。
5、通过设置autocommit=0可以取消自动提交,直到看到autocommit=1才会提交。
6、如果没有设置保留点,rollback会回滚到start transaction处;如果设置了,并且在rollback指定了该保留点,则回滚到保留点(rollback to XXX)。
四、事务的四中隔离级别
在MySQL中有四中隔离级别。每一种隔离级别的作用也不同,下面通过一张表来看一下:
事务的隔离级别 / 问题 | 脏读 | 不可重复读 | 幻读 |
未提交读(read uncommitted) | 没有避免 | 没有避免 | 没有避免 |
已提交读(read committed) | 已避免 | 没有避免 | 没有避免 |
可重复读(repeatable read) | 已避免 | 已避免 | 没有避免 |
可串行化/可序列化(serializable) | 已避免 | 已避免 | 已避免 |
在MySQL中默认的隔离级别是可重复读
五、设置隔离级来保证事务的隔离性
该部分结合并发中出现的脏读、不可重复读和幻读来操作。
(1)
什么是脏读?
案例一:未提交隔离级别无法避免脏读。
a.客户端A开启事务,查询账户余额。
b.在事务A未提交之前,开启客户端B,更新LIMing的账户余额。
c.在事务B未提交时,在客户端A查询表中数据,看到了事务B更新的数据。
d.此时,如果事务B因某些原因需要进行回滚,则所有操作被撤销,A中读到的数据就是脏数据。
二、
什么是不可重复读?
案例二:已提交读避免了脏读,无法避免不可重复读。
a.客户端A开启事务,查询表中数据。
b.在事务A还没有提交,开启事务B,更新表中ShangGuan的账户余额。
c.在事务A中查看ShangGuan的账户余额。余额未该变,说明杜绝了脏读。
d.事务B提交。
在事务A中查询账户余额,发生该变。对于开发者来说保证了数据的一致性。但是对于用户来说,两次的读取结果不一样,发生了不可重复读。
三、
案例三:可重复读隔离级别避免了不可重复读,但是数据任然保持一致性。
a.设置隔离级别为可重复读,开启事务A,查询最初的账户余额。
b.在事务A未提交时,开启事务B,更新表中LiHong的账户余额。
c.事务B未提交时,在事务A中查询表。发现没有发生变化,避免了不可重复读。
d.紧接着,在事务A中对LiHong的账户余额做计算,会发现把在事务B中的结果拿来用,在开发人员看来保证了事务的一致性。
四、
什么是幻读?
案例四、可重复读隔离级别下的幻读
a.在客户端A中开启事务,查询表中数据。
b.A事务为提交,在客户端B中开启事务,向表中插入一条数据。
c.在客户端A中计算表中账户余额总和。
经过操作发现在RPEATABLE-READ隔离级别下并没有发生幻读现象?????
问号脸,什么原因。
我查了一下表的存储引擎,如下,是InnoDB存储引擎:
再查一下,数据库存储引擎
我忘记了在Linux下的MySQL存储引擎默认是MyISAM存储引擎,它对于非索引项会加表锁。所以查询没出现幻读可能就是这个原因吧。
在网上查了一下,设置默认存储引擎为InnoDB步骤有:在/etc/my.cnf中,在mysqld后面增加default-storage-engine=INNODB即可。在这儿偷个懒就不验证了。
五、
可串行化隔离级别:
a.在客户端A下设置隔离级别,开启事务。
b.在A事务未提交时,开启B事务,设置隔离级别,进行插入数据,发现不允许
************************************************************************************************************
总结:
1、以上操作版本是:
2、事务的隔离性可通过设置隔离级别来保证。
3、事务隔离级别越高,越能保证数据的完整性,但是对并发性能影响大,就比如隔离级别为串行化时,读取数据会锁住整张表。
4、不可重复读和幻读很相似,两者整体上都是两次读的数据不相同,但是不可重复读一般时更新引起的;幻读是插入和删除引起的。
***************************************************************************************************************