🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
> # 事务特征和隔离级别 - 隔离级别:Read Uncommitted、Read Committed、Repeatable Read、Serializable - 读未提交(Read uncommitted) :一个事务可以读取另一个未提交事务的数据(没有视图概念, 返回最新结果) - 读提交(Read committed) :一个事务要等另一个事务提交后才能读取数据。(这个视图是每个SQL语句开始执行的时候创建的) - 可重复读(Repeatable read):在开始读取数据(事务开启)时,不再允许修改操作 (这个视图是在事务启动时创建的, 整个事务期间都用这个视图) - 串行化(serializable) :Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能。(没有视图, 通过加锁方式来避免并行访问, 读和写都加锁了) - 并发下事务会产生的问题 - 脏读 : 事务A读到了事务B还没有提交的数据(读未提交 会出现) - 不可重复度读: 在一个事务里面读取了两次某个数据,读出来的数据不一致(对数据进行修改)(读未提交、读提交 会出现) - 幻读: 事务在相同范围内查询多次, 返回的结果集不一样(对范围的数据进行新增或删除)(读未提交、读提交、可重复读 会出现) - MySQL 默认隔离级别是可重复读(Repeatable read), 该级别存在幻读问题 - 幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行, 幻读仅专指"新插入的行"。怎么解决呢?有两种方式, 分别如下: - 当前读:通过next-key锁实现(Record Lock行记录锁+Gap间隙锁), 如下图数据会分成 (-∞,3],(3,5],(5,8],(8,14],(14,20],(20,+∞)区间, 事务的快照时间是从第一个select开始,对涉及的区间加锁。 ![在这里插入图片描述](https://images.gitbook.cn/6b07da00-be71-11ea-bfba-6fcc0154bbf2) ``` select ... lock in share mode (读锁) select ... for update (写锁) update ... (更新操作) delete ... (删除操作) insert ... (插入操作) ``` - 上锁的时候, 不仅仅是对想要的数据加锁, 数据与数据之间的缝隙也会上锁 ![![](images/up-33f6e8ebe3f06a77961cd648334f283b319.png)](images/screenshot_1722490585311.png) - 快照读: 通过 UndoLog多版本并发控制实现(MVCC) ``` select ... (普通查询) ``` -- 1. **READ UNCOMMITTED(读未提交)**:这是最低的隔离级别。在该级别下,一个事务可以看到其他未提交事务的修改。这可能导致脏读、不可重复读和幻影读的问题。 2. **READ COMMITTED(读已提交)**:在该级别下,事务只能看到已经提交的其他事务所做的修改。这可以防止脏读,但仍然可能发生不可重复读和幻影读。 3. **REPEATABLE READ(可重复读)**:在该级别下,事务在整个事务期间看到的数据保持一致,不会受到其他事务的影响。这可以防止脏读和不可重复读,但仍然可能发生幻影读。 4. **SERIALIZABLE(串行化)**:这是最高的隔离级别。在该级别下,所有事务都像是按顺序执行的,不会发生并发问题。它可以防止脏读、不可重复读和幻影读,但可能导致性能下降,因为它会锁定大量数据。 > 相关阅读 - [MySQL 分布式事务的“路”与“坑”](https://my.oschina.net/u/4273516/blog/5459037)