目录
什么是事务的隔离级别?
常见的四种事务隔离级别
读未提交
读已提交
为什么没有解决幻读问题,是怎么导致的?
可重复读
串行化
事务的隔离级别(Isolation Level)指的是在并发环境中,不同事务之间相互隔离的程度。事务隔离级别定义了一个事务在读取和修改数据时,对其他事务的可见性和影响范围。
通俗来讲就是:你在做一件事的时候,别人能够否看你做的事情!你做事情做到什么程度的时候,才能够确切的让别人所看到!
读未提交(Read Uncommitted)是最低的事务隔离级别(可以说是最不严谨的),在这个级别下,一个事务可以读取到其他事务尚未提交的数据。
具体来说,当一个事务在读未提交隔离级别下运行时,它可以读取到其他事务已经修改但尚未提交的数据。这意味着一个事务可以看到其他事务的中间结果,即脏数据。这种隔离级别提供了最低的并发控制,没有任何锁定机制或多版本并发控制(MVCC)。
通俗来讲:将读未提交类比到显示就是——“能看见别人所写的草稿”
读未提交隔离级别存在以下问题和风险:
脏读(Dirty Read):一个事务读取到了另一个事务尚未提交的数据,如果另一个事务在后续操作中回滚,则当前事务读取到的数据实际上是无效的。
不可重复读(Non-repeatable Read):在同一事务内,多次读取相同的数据可能会得到不一致的结果,因为其他事务可能在同时修改该数据。
幻读(Phantom Read):在同一事务内,多次执行相同的查询可能返回不同的结果集,这是因为其他事务可能在同时插入、删除或修改符合查询条件的数据。
读已提交(Read Committed)是一种标准的事务隔离级别,在这个级别下,一个事务只能读取到已经提交的数据。这意味着对于未提交的数据修改,其他事务是不可见的。
具体来说,当一个事务在读已提交隔离级别下运行时,它只能看到已经被其他事务提交的数据。其他事务对数据的修改在提交之前对当前事务是不可见的,从而避免了脏读(Dirty Read)的问题。
通俗来讲:类比到现实生活中就是—— "只读取已经发布的信息"。
读已提交隔离级别提供了较好的并发控制机制,它使用锁定和多版本并发控制(MVCC)等技术来确保事务之间的隔离性和一致性。
读已提交隔离级别的特点包括:
无脏读:事务只能读取到其他事务已经提交的数据,不会读取到未提交的数据。
避免脏写:其他事务对于当前事务已经提交的数据是只读的,不能进行修改,从而避免了数据的脏写(Dirty Write)问题。
可重复读:在同一事务内,多次读取相同的数据会得到一致的结果,因为其他事务对数据的修改只有在提交后才对当前事务可见。
没有解决幻读的问题
对于读已提交(Read Committed)隔离级别来说,虽然可以解决脏读的问题,但并不能完全解决幻读(Phantom Read)的问题。
幻读是指在同一事务内,多次执行相同的查询可能返回不同的结果集,这是因为其他事务在同时插入、删除或修改符合查询条件的数据。读已提交隔离级别无法阻止其他事务在查询过程中插入新的数据,从而导致出现幻读问题。
简单的例子来说明幻读问题:
假设有两个并发的事务:事务A和事务B。
事务A执行如下语句:
SELECT COUNT(*) FROM orders WHERE status = 'unpaid';
此时事务B同时执行如下语句:
INSERT INTO orders (order_id, status) VALUES (12345, 'unpaid');
COMMIT;
然后事务A再次执行相同的查询语句:
SELECT COUNT(*) FROM orders WHERE status = 'unpaid';
在读已提交隔离级别下,事务A第一次查询得到的结果可能是3,因为此时还没有插入新的订单。但在第二次查询时,事务B已经插入了一个新的未付款订单,所以结果可能变成4。这就是典型的幻读问题:同一事务内,相同的查询语句得到了不同的结果集。
可重复读(Repeatable Read)是一种事务隔离级别,相对于读已提交隔离级别来说,在并发环境下提供了更高的数据一致性和稳定性。在可重复读隔离级别下,事务在执行过程中看到的数据保持一致,即使其他事务对数据进行了修改或插入操作。
通俗来讲:类比于现实生活中就是—— "在读取过程中,即使数据发生了变化,我的结果也不会变"。
可重复读隔离级别的主要特点包括:
读取锁(Read Locks):事务在读取数据时会对所读取的数据加上读取锁,其他事务可以读取同样的数据,但不能对该数据进行修改。
写入锁(Write Locks):事务在对数据进行修改时会对所修改的数据加上写入锁,其他事务无法读取或修改该数据,直到持有写入锁的事务释放锁。
一致性快照(Consistent Snapshot):在事务开始执行时,会创建一个一致性快照,该快照用于保持读取的数据的一致性。事务在整个执行过程中都会使用这个一致性快照,即使其他事务对数据进行了修改也不会影响当前事务的结果。
具体来说,可重复读隔离级别通过使用锁定和多版本并发控制(MVCC)等技术来实现数据一致性和防止脏读、不可重复读以及幻读的问题。
缺点——可重复读隔离级别相对于其他隔离级别来说,更严格地使用锁机制来保证数据的一致性和隔离性。这种锁的使用可能会导致更多的锁竞争情况。
串行化隔离级别是最严格的隔离级别,它确保事务之间完全串行执行,避免了并发带来的任何问题。在串行化隔离级别下,每个事务都会获得独占锁,并且其他事务无法同时读取或修改被锁定的数据,从而保证了数据的一致性和隔离性。
当一个事务开始执行时,它会对要读取或修改的数据加上共享锁或独占锁。其他事务如果需要访问相同的数据,就必须等待当前事务释放锁。这样可以避免幻读、不可重复读和脏读等问题的发生,因为每个事务都是在其他事务完全执行完毕后再开始执行,序列化地执行。
通俗来说,类比到现实生活中就是 "排队等候一个接一个完成任务"。
与可重复读隔离级别相比,串行化隔离级别的区别主要在于锁的使用方式和范围:
锁级别:可重复读隔离级别下使用的是行级锁,即对单个数据行进行锁定。而串行化隔离级别则使用表级锁,对整张表进行锁定。这意味着在串行化隔离级别下,一个事务对某个表进行读取或修改时,其他事务无法同时读取或修改该表的任何数据。
锁冲突:在可重复读隔离级别下,多个事务可以同时对不同的数据行进行读取或写入,只有在涉及相同数据行时才存在锁冲突。而在串行化隔离级别下,任何两个事务之间都会存在锁冲突,因为它们无法同时读取或修改同一张表。
并发性能:由于串行化隔离级别严格限制了事务的并发执行,因此在高并发环境下可能会导致性能下降。相比之下,可重复读隔离级别允许事务并发执行,只需在读取和写入时使用适当的锁机制,因此并发性能更高。