事务隔离级别的作用
在并发事务执行时,如何控制它们之间的相互影响和数据一致性的问题。
- 读未提交(Read Uncommitted):最低的隔离级别。在这个级别下,一个事务可以读取另一个事务未提交的数据。这可能会导致脏读(Dirty Read),即一个事务读取到另一个事务修改但尚未提交的数据。
- 读已提交(Read Committed):在这个级别下,一个事务只能读取另一个事务已经提交的数据。这可以避免脏读,但可能会导致不可重复读(Non-Repeatable Read),即在同一个事务中,多次读取同一个数据可能会得到不同的结果。
- 可重复读(Repeatable Read):在这个级别下,一个事务在读取数据时会锁定该数据,以防止其他事务对其进行修改。这可以避免脏读和不可重复读,但可能会导致幻读(Phantom Read),即在同一个事务中,多次读取同一个范围的数据可能会得到不同的结果。
- 串行化(Serializable):这是最高的隔离级别。在这个级别下,事务会按照顺序执行,并且在执行期间会锁定所有相关的数据,以确保数据的一致性。这可以避免脏读、不可重复读和幻读,但会导致较高的并发性能下降。
MySQL 中默认的隔离级别是可重复读、它能够提供较好的数据一致性和并发性能之间的平衡。
在实际应用中,通常会根据具体的业务需求和并发性能来选择合适的事务隔离级别。如果需要更高的一致性,可以选择串行化隔离级别,但要注意可能会对并发性能产生较大影响,更高的隔离级别通常伴随着更多的锁和性能开销。
脏读,不可重复读,幻读
设置不同的隔离级别,可能会带来 脏读,不可重复读,幻读 三个不同的问题,这三个问题都是并发事务执行时数据一致性相关的问题。
脏读(Dirty Read):脏读是指一个事务读取到另一个事务未提交的数据。在脏读情况下,一个事务可以读取到另一个事务修改但尚未提交的数据,这可能会导致数据不一致。
假设有两个事务 T1 和 T2,T1 正在修改某条记录,但还没有提交。此时,T2 读取了这条记录,获取到了 T1 未提交的修改结果。如果 T1 随后回滚了其修改,那么 T2 读取到的数据就是无效的,即脏读。
不可重复读(Non-Repeatable Read):不可重复读是指在同一个事务中,多次读取同一个数据可能会得到不同的结果。这是由于其他事务在读取数据后进行了修改并提交,导致事务中的后续读取操作获取到不同的结果。
假设事务 T1 读取了某条记录,然后另一个事务 T2 修改并提交了该记录。如果 T1 再次读取该记录,它将获取到 T2 提交后的修改结果,而不是最初读取到的值。这导致 T1 在同一个事务中多次读取同一个数据时得到了不同的结果,即不可重复读。
幻读(Phantom Read):幻读是指在同一个事务中,多次读取同一个范围的数据可能会得到不同的结果。这是由于其他事务在读取数据后插入或删除了新的记录,导致事务中的后续读取操作获取到不同的结果。
假设事务 T1 执行了一个范围查询,获取到了一个结果集。然后另一个事务 T2 在 T1 读取结果集后插入或删除了一些记录。如果 T1 再次执行相同的范围查询,它将获取到不同的结果集,即包含了 T2 插入或删除的记录。这导致 T1 在同一个事务中多次读取同一个范围的数据时得到了不同的结果,即幻读。
MySQL 查看隔离级别
# 查看当前会话隔离级别
select @@transaction_isolation;
# 查看系统当前隔离级别
select @@global.transaction_isolation;
# 查看当前会话隔离级别
select @@tx_isolation;
# 查看系统当前隔离级别
select @@global.tx_isolation;