共计 2960 个字符,预计需要花费 8 分钟才能阅读完成。
前言:
我一直想不到一个好的标题应该怎么写。我想 MySQL 的一些重要的内容。我在两次面试中都遇到过的,但直接用 MySQL 标题好像又不太贴切。干脆就是所写的内容吧。
MySQL 事务:
transaction
Transactions are atomic units of work that can be committed or rolled back. When a transaction makes multiple changes to the database, either all the changes succeed when the transaction is committed, or all the changes are undone when the transaction is rolled back.
Database transactions, as implemented by
InnoDB
, have properties that are collectively known by the acronym ACID, for atomicity, consistency, isolation, and durability.See Also ACID, commit, isolation level, lock, rollback.
MySQL 官网对事务的解释。(提醒还在大一大二的师弟师妹,学号英语真的很重要,很重要,超级重要)
四种隔离级别:
isolation level
One of the foundations of database processing. Isolation is the I in the acronym ACID; the isolation level is the setting that fine-tunes the balance between performance and reliability, consistency, and reproducibility of results when multiple transactions are making changes and performing queries at the same time.
From highest amount of consistency and protection to the least, the isolation levels supported by InnoDB are: SERIALIZABLE, REPEATABLE READ, READ COMMITTED, and READ UNCOMMITTED.
With
InnoDB
tables, many users can keep the default isolation level (REPEATABLE READ) for all operations. Expert users might choose the READ COMMITTED level as they push the boundaries of scalability with OLTP processing, or during data warehousing operations where minor inconsistencies do not affect the aggregate results of large amounts of data. The levels on the edges (SERIALIZABLE and READ UNCOMMITTED) change the processing behavior to such an extent that they are rarely used.See Also ACID, OLTP, READ COMMITTED, READ UNCOMMITTED, REPEATABLE READ, SERIALIZABLE, transaction.
Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的 commit,所以同一 select 可能返回不同结果。
Repeatable Read(可重读)
这是 MySQL 的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影”行。InnoDB 和 Falcon 存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
我这里解释一下 “读写提交内容”和“可重读” 的区别。
假设有两个事务 T1,T2
读写提交内容:
T1 insert 了一条数据,T2 此时看不到,等 T1commit 了以后,T2 才看到了。这就造成了 T2 前后两次 select 的内容不一致,也就造成了不可重读的原因。
可重读:
T1 insert 了一条数据,T2 此时看不到,等 T1 commit 了以后,T2 还是看不到。等 T2 事务进行提交了以后,在进行 select,发觉,卧槽,数据怎么多了一条出来,感觉出现了幻觉,即“幻读”;
MVCC 机制:
多版本并发控制 (Multiversion Concurrency Control)。MySQL 默认隔离级别为Repeatable Read(可重读)。 那么 MySQL 如何解决幻读的。
就是利用 MVCC 机制。
什么是多版本并发控制呢?其实就是在每一行记录的后面增加两个隐藏列,记录创建版本号和删除版本号,而每一个事务在启动的时候,都有一个唯一的递增的版本号。
只有 read-committed 和 repeatable-read 两种事务隔离级别才能使用 MVCC
read-uncommited 由于是读到未提交的,所以不存在版本的问题
而 serializable 则会对所有读取的行加锁。