vlambda博客
学习文章列表

Mysql引擎、事务和隔离级别

一、mysql引擎

在讲mysql事务之前,需要对mysql的存储引擎做一些了解,我们可以使用

show engines;

来查看mysql有哪些引擎。

目前mysql支持的引擎大概有Aria、CSV、InnoDB、MEMORY、MRG_MyISAM、MyISAM、PERFORMANCE_SCHEMA和SEQUENCE,日常工作中最常用的可能就是InnoDB和MyISAM。

引擎

说明

是否支持事务

(Transactions)

是否支持分布式事务(XA) 是否支持设置存储点(Savepoints)

CSV

将表格存储为 CSV 文件 不支持 不支持 不支持
InnoDB Percona-XtraDB(一种高可用性和可扩展性的解决方案),支持事务、行级锁定、外键和表加密 支持 支持 支持
MEMORY 基于哈希,存储在内存中,对临时表有用 不支持 不支持 不支持
MyISAM 具有良好性能和小数据占用的非事务性引擎 不支持 不支持 不支持
MRG_MyISAM 是一组MyISAM的组合 不支持 不支持 不支持
Aria 具有 MyISAM 传统的防碰撞表 不支持 不支持 不支持
PERFORMANCE_SCHEMA 一个数据库性能方案 不支持 不支持 不支持
SEQUENCE 生成表的序列值 支持 不支持 支持

说明:

1.XA(eXtended Architecture)是指由X/Open 组织提出的分布式交易处理的规范。XA 是一个分布式事务协议,由Tuxedo 提出,所以分布式事务也称为XA 事务。

2.Savepoints是事务过程中的一个逻辑点,用于取消部分事务,当结束事务时,会自动的删除该事务中所定义的所有保存点。当执行rollback时,通过指定保存点可以回退到指定的点。

3.MySQL5.5版本开始Innodb已经成为Mysql的默认引擎,之前是MyISAM。

4.关于InnoDB和MyISAM的自增ID重启后会不会重置的问题。

InnoDB

8.0 版本之前, 自增 id 保存在内存中, 重启后会丢失, 下次自增 id 会取表中最大 id + 1。

8.0 版本之后, 自增 id 保存在 redo log 中, 重启后不会丢失。

MyISAM

自增 id 总是保存在内存中, 不区分数据库版本, 重启后不会丢失。

Mysql引擎、事务和隔离级别

二、Mysql事务

从上面的mysql引擎的类型可以支持只有InnoDBSEQUENCE是支持事务

(1) 事务的四大特性(ACID)

  • 原子性(Atomicity)

事务的最小工作单元,指事务包含的所有操作要么全部成功,要么全部失败。

  • 一致性(Consistency)

事务前后数据的完整性必须保持一致。

  • 隔离性(Isolation)

多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,不同事务之间互不影响。

  • 持久性(Durability)

一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

2)事务的隔离类型

隔离级别 说明
脏读
不可重复读 幻读
Serializable 串行化,可避免脏读、不可重复读、幻读读情况的发生
Repeatable read 可重复读,可避免脏读、不可重复读情况的发生,会出现幻读的情况
Read committed 读已提交,可避免脏读情况发生,会出现不可重复读的情况
Read uncommitted 读未提交,最低级别,会出现脏读的情况


  • 脏读

脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。

  • 不可重复读(指数据更新的情况下)

不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。

  • 幻读(指数据新增删除的情况下)

幻读是指一个事务进行读取,分别读取到了不同的数据。需要注意的是这里针对的是数据条数,InnoDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题(条数不一致的问题)。

(1) 怎么查看和设置事务隔离级别

  • 查看事务隔离级别

SELECT @@global.tx_isolation,@@tx_isolation;

 

Mysql引擎、事务和隔离级别


global.tx_isolation为系统隔离级别

tx_isolation当前会话的隔离级别

  • 设置当前会话隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;(当前会话设置为读未提交)

设置完之后的结果(只对设置的会话有效)

 

Mysql引擎、事务和隔离级别


另一个会话的结果

 

Mysql引擎、事务和隔离级别


  • 设置系统当前隔离级别

SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;(当前系统设置为读未提交)


设置完之后的结果

 

Mysql引擎、事务和隔离级别


另一个会话的结果

 

Mysql引擎、事务和隔离级别


 

(3)演示

  • 脏读演示

会话窗口一

 

Mysql引擎、事务和隔离级别


会话窗口二

 

Mysql引擎、事务和隔离级别


说明:

Ps:将事务隔离级别设置为读未提交

窗口一对id5weight进行了更新,但并未进行commit,但窗口二已经读到了窗口一更新之后的值,如果窗口一的更新操作进行回滚,此时窗口二读到的数据就是错误的结果。

 

  • 不可重复读演示

commit

会话窗口一

 

Mysql引擎、事务和隔离级别


会话窗口二

 

Mysql引擎、事务和隔离级别


 

Commit之后

会话窗口一

 

Mysql引擎、事务和隔离级别


会话窗口二

 

Mysql引擎、事务和隔离级别


说明:

Ps:将事务隔离级别调整为读提交

窗口一对id5weight进行了更新,但并未进行commit,可以看到窗口二读到的结果还是63,当窗口一事务提交之后,窗口二就读到了commit之后更新的值,解决了脏读问题,但此时就出现了一个不可重复读的问题,就是窗口二同一个事务两次读取的结果是不一样的,一次ID5weight值为63,一次为64

 

  • 可重复读演示

会话窗口一

 

Mysql引擎、事务和隔离级别


会话窗口二

 


说明:

Ps:将事务隔离级别调整为可重复读

窗口一对id5weight进行了更新,但并未进行commit,可以看到窗口二读到的结果还是63,当窗口一事务提交之后,此时窗口二读到的结果还是64,可以看到窗口一commit前后,窗口二读到的结果是一样的,即解决了不可重复读的问题。

 

三、总结

  • 安全性

Serializable > Repeatable Read > Read Committed > Read Uncommitted

  • 性能

Rerializable < Repeatable Read < Read Committed < Read Uncommitted

实际开发中,通常不会选择 Serializable Read Uncommitted MySQL默认隔离级别是Repeatable Read Oracle默认隔离级别是Read Committed

关于多版本并发控制(MVCC)后面有时间再补充,另外如有错误之处还望指正。