首页 > 代码库 > MySQL基础——事务隔离级别

MySQL基础——事务隔离级别

事务是DBMS得执行单位。它由有限得数据库操作序列组成得。但不是任意得数据库操作序列都能成为事务。一般来说,事务是必须满足4个条件(ACID)

 ①:原子性(Autmic):事务在执行性,要做到“要么不做,要么全做!”,就是说不允许事务部分得执行。即使因为故障而使事务不能完成,在rollback时也要消除对数据库得影响!

 ②:一致性(Consistency):事务操作之后,数据库所处的状态和业务规则是一致的;比如a,b账户相互转账之后,总金额不变!

 ③:隔离性(Isolation):如果多个事务并发执行,应像各个事务独立执行一样!

 ④:持久性(Durability):事务提交后被持久化到数据库.


1、MYSQL的事务处理主要有两种方法。

①:用BEGIN,ROLLBACK,COMMIT来实现

   开始:START TRANSACTION或BEGIN语句可以开始一项新的事务

   提交:COMMIT可以提交当前事务,是变更成为永久变更

   回滚:ROLLBACK可以回滚当前事务,取消其变更


②:直接用set来改变mysql的自动提交模式

    MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!


2、事务的隔离级别:

   SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。


①:Read Uncommitted(读取未提交内容)

  在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。


②:Read Committed(读取提交内容)

  这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。


③:Repeatable Read(可重读)

  这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。


④:Serializable(可串行化) 

  这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。


---注意:这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:


    ①:脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。


    ②:不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。


    ③:幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。  SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。


3、修改MySQL的默认事务隔离级别:

   -----注意:MySQL默认的事务隔离级别: REPEATABLE-READ(可重读)


①:修改事务隔离级别的语法:

 SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}


注意:默认的行为(不带session和global)是为下一个(未开始)事务设置隔离级别。如果你使用GLOBAL关键字,语句在全局对从那点开始创建的所有新连接(除了不存在的连接)设置默认事务级别。你需要SUPER权限来做这个。使用SESSION 关键字为将来在当前连接上执行的事务设置默认事务级别。 任何客户端都能自由改变会话隔离级别(甚至在事务的中间),或者为下一个事务设置隔离级别。


②:用下列语句查询全局和会话事务隔离级别:


SELECT @@global.tx_isolation; 

SELECT @@session.tx_isolation; 

SELECT @@tx_isolation; 


③:设置事务隔离级别:

-----在my.cnf配置文件修改:

  [mysqld]

 transaction-isolation = READ-COMMITTED


-----使用命令修改:

mysql> set global transaction isolation level read committed;

mysql> set session transaction isolation level read committed;


start transaction; //打开事务 


扩展知识:

“两条不同的插入语句导致的死锁:”

如果没有特别的需求,可以设置MySQL的默认隔离级别设置为read-committed级别,这样可以避免很多不必要的问题;也是解决死锁的一种方法;


本文出自 “笨小孩的dba之路” 博客,请务必保留此出处http://fengfeng688.blog.51cto.com/4896812/1944041

MySQL基础——事务隔离级别