说说 Mysql 事务的隔离级别,以及乐观锁和悲观锁

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

什么是隔离级别?

所谓隔离级别,就是在数据库事务中,为保证并发数据读写的正确性而提出的定义,其实,隔离级别也并不是 mysql 专有的概念,而是源于 ANSI/IOS 制定的 SQL-92 标准。

实际上每种关系型数据库都有着各自特色的隔离级别实现,它们底层通常都是以锁为实现单元,但是实际上的实现也是千差万别的。我们拿 Mysql InnoDB 引擎为例,它是基于 MVCC 和锁的复合实现来完成的。

回到正题,按照隔离级别的从低到高,分为以下几个级别:

  • 1.读未提交,就是说一个事务能够看到其他事务尚未提交的修改,这是最低的隔离级别,容易出现脏读的情况。

  • 2.读已提交,事务能够看到的数据,都是其他事务已经提交的修改数据,也就是说不会看到处于中间状态的数据,脏读自然不会出现。但是,读已提交仍然是比较低级别的隔离,并不能保证再次读取的时候能够拿到同样的数据,也就是允许其他事务并发的修改数据,容易出现不可重复读和幻像读的情况出现。

  • 3.可重复读,保证同一个事务中多次读取的数据是一致的,也是 Mysql InnoDB 引擎默认的隔离级别, 与其他关系型数据实现不同的是,你可以认为 MySQL 这种级别不会出现幻像读的情况。

  • 4.串行化,并发事务之间是同步的,这就意味着读取需要获取共享读锁,更新需要获取排它写锁,如果 SQL 语句中有 where 条件还需要获取区间锁,这也是最高级别的隔离。

再说说乐观锁和悲观锁

乐观锁和悲观锁不是数据库中独有的概念,它属于并发编程中的基本概念。

  • 1.乐观锁:乐观的认为共享数据在多线程的情况下,发生冲突很少。实现上,一般是在数据库中另加一个版本号或者时间戳的字段,更新时 where 条件加上该字段判断,而不是通过加锁的方式,这样可以很大的提高服务的 TPS.

  • 2.悲观锁:悲观的认为,共享数据在多线程的情况下,发生冲突很大。实现上,通过 mysql 的行级锁,或者逻辑层加锁等等。