DB四个隔离级别
数据库隔离允许事务执行,就像没有其他并发运行的事务一样。
下面的图说明了四个隔离级别。
Serializalble: 这是最高的隔离级别。并发交易保证按顺序执行。
Repeatable Read: 事务开始时读取的数据保持不变。
Read Committed: 只有事务提交后,数据修改才能被其他事务读取。
Read Uncommitted: 数据修改可以在事务提交前被其他事务读取。
MVCC如何工作的 ?
隔离性是通过MVCC(多版本一致性控制)和锁来保证的。
下图以Repeatable Read为例,演示MVCC如何工作:
每行有两个隐藏列:transaction_id和roll_pointer。
当事务A开始时,创建一个新的读视图,transaction_id=201。
一会儿过后事务B开始后,创建一个新的读视图,transaction_id=202。
现在,事务A将余额修改为200,创建日志的新行,并且roll_pointer指向旧行。
在事务A提交之前,事务B读取余额数据。事务B发现transaction_id 201尚未提交,它读取下一个已提交的记录(transaction_id=200)。
即使事务A提交,事务B仍然基于事务B开始时创建的读视图读取数据。所以事务B总是读取余额=100的数据。
MVCC通过为每行记录创建多个版本,并且为每个事务生成一个时间点快照(Read View),实现非阻塞读和隔离性。 这种机制允许并发事务同时读取数据,而不会堵塞其他事务
小结
MySQL 的 MVCC(多版本并发控制)机制主要包含以下几个方面:
行版本(Version):MySQL 为每行记录维护多个版本,每个版本都有唯一的版本号(Version Number)。
事务ID(Trx ID):每个事务开始时,会分配一个唯一的事务ID,用于标识事务在时间轴上的位置。
快照(Snapshot):当事务开始时,MySQL 会为其创建一个快照,快照中包含此时数据页中所有版本和对应事务ID。事务执行期间,所有读请求都在此快照中查找版本。
时间轴位置判断:事务需要判断其他版本的事务ID是否早于自己,以判断其是否可见。如果早于自己,说明其已提交,自己可见;否则,不可见。
行版本生成:事务更新数据时,会生成行的新版本,并把新版本的事务ID设置为自己的ID。其他事务只有在此事务提交后,新版本才对其可见。
事务回滚:如果事务回滚,其生成的所有新行版本都会被移除,不会对其他事务产生影响。
MVCC自更新问题:事务A读取一行,事务B也读取并修改了此行,此时事务A再修改此行。为避免覆盖,事务A生成新版本,并阻塞事务B的修改,等待其提交或回滚。
通过版本判断和控制,MVCC可以实现不同隔离级别下的并发控制:
- Repeatable Read:利用快照实现
- Read Committed:通过时间轴判断可见版本实现
- Read Uncommitted:所有版本都可见
所以,MySQL MVCC 通过行版本和时间轴判断来控制并发事务间的隔离和一致性,这是MySQL并发控制的基石。