1、查看当前会话的 隔离级别:
select @@tx_isolation;
2、查看系统的隔离级别:
select @@global.tx_isolation;
3、设置会话的隔离级别,隔离级别由低到高设置依次为:
set session transacton isolation level read uncommitted;
set session transacton isolation level read committed;
set session transacton isolation level repeatable read;
set session transacton isolation level serializable;
4、设置当前系统的隔离级别,隔离级别由低到高设置依次为:
set global transacton isolation level read uncommitted;
set global transacton isolation level read committed;
set global transacton isolation level repeatable read;
set global transacton isolation level serializable;
注意:mysql默认的事务处理级别是'REPEATABLE-READ',而Oracle和SQL Server是READ_COMMITED
ACID特性
数据库管理系统中事务(transaction)的四个特性(分析时根据首字母缩写依次解释):原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。(执行单个逻辑功能的一组指令或操作称为事务)
详解
1. 原子性
原子性是指事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。
可采用“A向B转账”这个例子来说明解释
在DBMS中,默认情况下一条SQL就是一个单独事务,事务是自动提交的。只有显式的使用start transaction开启一个事务,才能将一个代码块放在事务中执行。
2. 一致性
一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
如A给B转账,不论转账的事务操作是否成功,其两者的存款总额不变(这是业务逻辑的一致性,至于数据库关系约束的完整性就更好理解了)。
保障机制(也从两方面着手):数据库层面会在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,check约束等)和触发器设置;此外,数据库的内部数据结构(如 B 树索引或双向链表)都必须是正确的。业务的一致性一般由开发人员进行保证,亦可转移至数据库层面。
3. 隔离性
多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。
在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
事务最复杂问题都是由事务隔离性引起的。完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能。
关于隔离性中的事务隔离等级(事务之间影响),参见相应博文
4. 持久性
这是最好理解的一个特性:持久性,意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。(完成的事务是系统永久的部分,对系统的影响是永久性的,该修改即使出现致命的系统故障也将一直保持)
MySQL的事务隔离级别
MySQL提供了4种事务隔离级别,其中最常用的InnoDB存储引擎的默认隔离级别为可重复读。
| 事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交(read-uncommitted) | 是 | 是 | 是 |
| 已提交读(read-committed) | 否 | 是 | 是 |
| 可重复读(repeatable-read) | 否 | 否 | 是 |
| 串行化(serializable) | 否 | 否 | 否 |
1、未提交读。
最低的隔离级别(是一种危险的隔离级别,会出现脏读),其含义是允许一个事务读取另外一个事务没有提交的数据。
T2时刻中事务1中扣减了库存,T3时刻中事务2也扣减了库存,但是它也读取到了T2时刻中事务1的操作,因此T3时刻扣减后库存为0,这个时候T5在提交事务后事务1进行回滚,因为第一类丢失更新已经被克服,所以库存最终会出现脏读(库存应该为1才是正确的)。
2、读写提交。
指一个事务只能读取到另外一个事务已经提交的数据。
在T3时刻,因为采用了读写提交的隔离级别,所以事务2不会读取到事务1中未提交的库存1,所以在T3时刻事务2扣除库存后还剩下库存为1,然后提交事务。则库存在T4中就变成了1。在T5时刻,事务1回滚,因为第一类丢失更新已经克服,所以最后的库存结果也变为了1。
3、可重复读。
克服读写提交中出现的不可复读的现象,因为在读写提交的时候,可能出现一些值的变化,影响当前事务的执行。
4、串行化
最高的隔离级别,会要求所有的SQL按照顺序执行,这样就可以克服上述隔离级别出现的问题,所以能够保证数据的一致性。
InnoDB 与 MyISAM
1. InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;
2. InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败;
3. InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
4. InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
5. InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;
如何选择:
1. 是否要支持事务,如果要请选择 InnoDB,如果不需要可以考虑 MyISAM;
2. 如果表中绝大多数都只是读查询,可以考虑 MyISAM,如果既有读写也挺频繁,请使用InnoDB。
3. 系统奔溃后,MyISAM恢复起来更困难,能否接受,不能接受就选 InnoDB;
4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的。如果你不知道用什么存储引擎,那就用InnoDB,至少不会差。