理解mysql的事务隔离级别

前言 考研分数落定,今年无缘,着手准备春招。说到今年考研,分数可谓水涨船高,去年本校专硕270就能进,今年一舍友考了270,排名排到了140名(报的专业要70个),进复试基本无望,估计考本校分数线能到290。
走校招的话公司一般面试问题方方面面,重点离不开算法和语言的基础知识。大厂非常重视校招生的算法能力,因为校招生项目经验少,而大厂项目用户量大。算法这个就是在力扣上多做题,多了解答案思路。
语言基础知识这块,就得多看书,有些东西是我们平常开发接触不到的,面试官又爱问。面试就是这样,面试造火箭,工作拧螺丝。喜硕学长推荐了两本书,一本《深入浅出mysql》,翟振兴著,一本《深入理解jvm虚拟机》,周志明著。粗略看了一下《深入浅出mysql》更像是一本mysql的字典,里面从基本sql语句到sql优化维护都有涉及,心学数据库没有教材买本这个书看也可以,肯定比学校发的教材强,学校发的大多都是学校老师自己写的。并且里面举例比较多,好理解。《深入理解jvm虚拟机》可以当扩展读物看,里面讲了一些java底层一些知识,比如new一个对象具体发生了什么,jvm如何进行内存回收,jvm调优,我们不知道这些东西也不影响我们用java开发。并且举例较少,建议有一定java基础和操作系统知识基础再来看这本书。
mysql锁概述 锁是协调各个进程或者线程并发访问一个资源的重要机制。一个好的锁机制,不仅保证了数据并发访问的一致性、有效性。并且也尽量减少并发性能的影响。
我们知道InnoDB引擎相对于其他来说支持事务。事务是一组SQL语句组成的逻辑处理单元,具有4个特性,通常简称为事务ACID属性。

  • 原子性:事务是一个原子操作单元,要么全部执行,要么全部不执行。
  • 一致性:在事务开始和完成时,数据要保持一致状态。就是说在事务开始和完成时,数据保持一个正确的状态。
  • 隔离性:数据库提供一定的隔离机制,保证事务在不受外部事务影响的环境运行。这意味着事务处理过程中的中间状态对其他事务来说是不可见的。
  • 持久性:事务完成后,对于数据的修改时永久性的。
    我们拿经典的银行转帐来理解事务。
    比如说张三账户上想往李四账户上转1000块钱。
    那么用sql语句就是这样的
    update bank set balance = balance - 1000 where name = '张三'; update bank set balanc = balance + 1000 where name = '李四';

    如果我们将其中的一个字段打错,那么其中一条语句无法正确执行。
    update bank set balance = balance - 1000 where name = '张三'; update bank set balance = balance + 1000 where name = '李四';

    那么会照成张三少了1000块钱而李四没有多1000块钱情况。
    如果加入事务则不会发生这种情况。
    原子性保证要么两条语句都执行,要么都不执行。
    一致性保证钱转帐过程的开始和完成时总数保持不变,且余额都不会少于0。
    隔离性保证这个事务执行完之前,不会对其他事务造成影响。
    持久性保证事务完成后对钱的修改时永久的。
    并发事务带来的问题并发事务增加了数据库利用率,提高吞吐量,也带来了一些问题。
  • 【理解mysql的事务隔离级别】更新丢失:
    事务A 事务B
    开启一个事务 开启一个事务
    将张三账户余额加200 将张三账户余额加500
    提交 /
    / 提交
    这造成了两个人同时给张三存钱,一个人存200,一个人存500,结果账户只多了500,200没了。
  • 脏读:
    事务A 事务B
    开启一个事务 开启一个事务
    查询张三余额为1000
    如果查询的结果大于等于1000则将张三账户余额减1000 查询张三余额为1000
    / 如果查询的结果大于等于1000则将张三账户余额减1000
    / 提交
    提交 /
  • 不可重复读:
    事务A 事务B
    开启一个事务 开启一个事务
    查询张三余额为1000 /
    / 将张三账户余额加500
    / 提交
    查询张三余额为1500 /
    提交 /
    这造成事务A两次查询结果不一致,不知道已哪个为准。
  • 幻读:
    事务A 事务B
    开启一个事务 开启一个事务
    查询姓张的人的余额,查到张三余额为1000 /
    / 新建个账户叫张四,余额为0
    / 提交
    查询姓张的人的余额,查到张三余额为1000,张四余额为0 /
    提交 /
    更新丢失只要保证一个事务在对数据更新提交之前,另一个事务不能更改数据。这个主要靠应用层面来解决。
    脏读,不可重复读,幻读,需要靠数据库提供的一定的事务隔离机制来解决。数据库实现数据隔离方式,基本分以下两种:
  • 一种是在读取数据前,对其加锁,阻止其他事务对数据进行更改。
  • 一种是不加任何锁,通过一定机制生成一个数据请求时间点的数据快照,并用这个快照来提供一定级别的数据读取。从用户角度看,好想数据库可以提供统一数据不同版本,这种技术叫做数据多版本并发控制,也就是MVCC。关于MVCC可以看这篇文章这篇文章
    数据库事务隔离越严格,并发副作用越小,但付出代价越大。这是一个权衡的过程。未来解决隔离与并发矛盾,sql定义了4个事务隔离级别,应用根据自己业务逻辑要求,选择不同隔离级别来平衡隔离与并发的矛盾。
    脏读 不可重复读 幻读
    未提交读 READ-UNCOMMITTED
    已提交读 READ-COMMITTED
    可重复读 REPEATABLE-READ
    可序列化 SERIALIZABLE

    推荐阅读