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引擎的类型可以支持只有InnoDB和SEQUENCE是支持事务
(1) 事务的四大特性(ACID)
原子性(Atomicity)
事务的最小工作单元,指事务包含的所有操作要么全部成功,要么全部失败。
一致性(Consistency)
事务前后数据的完整性必须保持一致。
隔离性(Isolation)
多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,不同事务之间互不影响。
持久性(Durability)
一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
(2)事务的隔离类型
隔离级别 | 说明 |
脏读 |
不可重复读 | 幻读 |
Serializable | 串行化,可避免脏读、不可重复读、幻读读情况的发生 | 否 |
否 | 否 |
Repeatable read | 可重复读,可避免脏读、不可重复读情况的发生,会出现幻读的情况 | 否 | 否 | 是 |
Read committed | 读已提交,可避免脏读情况发生,会出现不可重复读的情况 | 否 | 是 | 是 |
Read uncommitted | 读未提交,最低级别,会出现脏读的情况 | 是 | 是 | 是 |
脏读
脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。
不可重复读(指数据更新的情况下)
不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。
幻读(指数据新增删除的情况下)
幻读是指一个事务进行读取,分别读取到了不同的数据。需要注意的是这里针对的是数据条数,InnoDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题(条数不一致的问题)。
(1) 怎么查看和设置事务隔离级别
查看事务隔离级别
SELECT @@global.tx_isolation,@@tx_isolation;
global.tx_isolation为系统隔离级别
tx_isolation当前会话的隔离级别
设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;(当前会话设置为读未提交)
设置完之后的结果(只对设置的会话有效)
另一个会话的结果
设置系统当前隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;(当前系统设置为读未提交)
设置完之后的结果
另一个会话的结果
(3)演示
脏读演示
会话窗口一
会话窗口二
说明:
Ps:将事务隔离级别设置为读未提交
窗口一对id为5的weight进行了更新,但并未进行commit,但窗口二已经读到了窗口一更新之后的值,如果窗口一的更新操作进行回滚,此时窗口二读到的数据就是错误的结果。
不可重复读演示
未commit前
会话窗口一
会话窗口二
Commit之后
会话窗口一
会话窗口二
说明:
Ps:将事务隔离级别调整为读提交
窗口一对id为5的weight进行了更新,但并未进行commit,可以看到窗口二读到的结果还是63,当窗口一事务提交之后,窗口二就读到了commit之后更新的值,解决了脏读问题,但此时就出现了一个不可重复读的问题,就是窗口二同一个事务两次读取的结果是不一样的,一次ID为5的weight值为63,一次为64。
可重复读演示
会话窗口一
会话窗口二
说明:
Ps:将事务隔离级别调整为可重复读
窗口一对id为5的weight进行了更新,但并未进行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)后面有时间再补充,另外如有错误之处还望指正。