:第九节#事务,并发事务问题以及事物的隔离)
大家好本篇文章为不了解数据库或者将要学数据库却不知道它具体是什么的伙伴们介绍数据库的基础知识同时小编也会用每一小节学到的新知识一步一步搭建出一个完整的大一新生数据库系统小编争取每天都会更新一节零基础的小伙伴也可以跟着小编一起搭建自己的一个数据库系统学习到这里大家基学会了在数据库系统里面创建修改以及查询数据。不过这天我们史莱克新生唐三在学校吃饭发现自己饭卡里面没有钱了于是他用自己账户向学校饭卡充值了100元这时他账户确实是转出了100元但是他饭卡里面却依旧没有钱转入。这是什么原因呢让我们在系统层面来分析一下可以看见我在数据库系统里面新建了两个表格一个是饭卡金额管理表还有一个是学生个人余额表现在我们来模拟一下刚刚唐三充值的操作我们先把唐三余额扣除100然后给唐三饭卡余额增加100可以看到正常情况下直接这样写也是可以完成我们需求的唐三那里的100就转移到饭卡里面了但是如果系统因为网络啊或者啥原因刚好在第二步给饭卡增加100元时出现了问题就会出现下面这种情况可以看到这样的话就出现唐三的钱扣除了但是饭卡余额却并没有增加成功的状况了。所以如果我们日常生活中用这种方法来转账或者其他类似的事就有可能出现我钱花了对方却没收到钱的尴尬场景。那么为了解决这个情况我们就需要使用事务功能# 事务事务一组操作的集合是不可分割的工作单位这一组操作会作为一个整体像系统提交或撤销操作申请这些操作只能同时成功或失败。事务四大特性ACID原子性Atomicity事务是不可分割的最小操作单元一组事务要么全部成功要么全部失败一致性(Consistency)事务完成A前后事务的完整性约束不变-- 一致性是事务目标需要其他特性共同实现隔离性(Isolation)多个事务并发执行事物之间相互隔离互不影响持久性(DDurability)事务一旦提交成功数据永久保存CMySQL里面是默认自动提交事务I的我们可以去查看和设置事务提交方式select autocommit; --查看事务提交方式 set autocommit0; --设置事务提交方式可以看到显示为1就说明是自动提交事务模式这里我们需要修改事务提交方式为0既然我们设置手动提交事务了就需要一个语句来控制提交已经事务的回滚commit; --提交事务 rollback; --回滚事务现在我们再来转账看看效果可以看到现在就算中间那一步出现故障也只会整个事务都报错然后我们点击回滚事务恢复正常就行了数据也不会有异常了。## 并发事务引发的问题问题英文定义发生场景脏读Dirty Read一个事务读到了另一个事务未提交的数据事务 A 修改数据但未提交事务 B 读到了这个修改不可重复读Non-repeatable Read同一事务内两次读同一行结果不同事务 A 读了一次事务 B 修改并提交事务 A 再读结果变了幻读Phantom Read同一事务内两次范围查询结果集行数不同事务 A 查WHERE age 20事务 B 插入一条并提交事务 A 再查多了一行丢失更新Lost Update两个事务同时修改同一数据后提交的覆盖了先提交的事务 A、B 都读balance100都改成200最终只加了一次前三个是 SQL 标准定义的丢失更新是实际业务中最常见的问题。隔离级别脏读不可重复读幻读丢失更新READ UNCOMMITTED可能可能可能可能READ COMMITTED不可能可能可能可能REPEATABLE READ不可能不可能标准允许MySQL 实际避免可能需加锁SERIALIZABLE不可能不可能不可能不可能注意丢失更新在任何隔离级别下都可能发生除了 SERIALIZABLE需要通过SELECT ... FOR UPDATE或乐观锁版本号来解决。设置事务隔离级别set [session/globle] transacyion isolation lever {read uncommitted/read committed/repeatable read/serializable};常见数据库默认隔离级别数据库默认隔离级别备注MySQL InnoDBREPEATABLE READ通过 MVCC Next-Key Lock 很大程度避免幻读OracleREAD COMMITTED支持 SERIALIZABLE也提供只读事务PostgreSQLREAD COMMITTED支持 REPEATABLE READ、SERIALIZABLESQL ServerREAD COMMITTED默认使用行版本控制时可减少阻塞DB2CURSOR STABILITY类似 READ COMMITTED 的增强级别SQLiteSERIALIZABLE默认串行化但实际并发行为受锁模式影响### 完结恭喜你走到这里数据库初识篇的内容已经全部学完了。从最初的“什么是数据库”到写出第一句SELECT再到能独立设计表、写多表查询、控制事务、理解隔离级别……这一路你啃下了不少硬骨头。可能中间因为一个语法错误卡了半天也可能因为一个死锁排查到深夜但你还是一步步走到了这里。你在这段旅程里掌握了什么基础操作数据库、表、字段、记录这些基本概念CREATE/DROP/ALTER等 DDL 语句INSERT/UPDATE/DELETE等 DML 语句SELECT单表查询、条件过滤、排序、分页进阶查询聚合函数与分组查询多表查询内连接、外连接、自连接子查询标量子查询、列子查询、行子查询、表子查询窗口函数与 CTE如果课程涉及约束与设计主键、外键、唯一、非空、默认值三大范式与表结构设计索引的基本原理与使用事务与并发事务的 ACID 特性事务的提交与回滚四种隔离级别脏读、不可重复读、幻读、丢失更新一些想对你说的话1. 语法可以查思路最重要。写 SQL 最怕的不是记不住关键字而是不知道“我要的数据该怎么一步步取出来”。多问自己数据在哪几张表它们怎么关联我要的是明细还是聚合想清楚了SQL 自然就出来了。2. 报错是常态读错误信息是能力。1064是语法错误1452是外键约束失败1213是死锁……每一个错误码背后都是数据库在告诉你“哪里不对”。学会看错误信息比盲目搜索更高效。3.初识篇只是起点。数据库的世界远不止这些索引底层结构B 树、执行计划、锁机制、主从复制、分库分表、读写分离、Redis 缓存……基础打牢了后面才能走得更稳。下一步可以往哪走MySQL 进阶索引优化、执行计划、锁、日志、主从复制数据库设计实战从需求到表结构从表结构到 SQL性能优化慢查询分析、索引调优、分页优化其他数据库Redis、MongoDB、PostgreSQL后端开发框架MyBatis、JPA、Spring Data小编也会在一段时间后继续更新数据库第二篇寻他篇讲解更深入的数据库知识最后一句话数据库基础篇的完结只是你真正开始“用数据思考”的起点。以后你写的每一行 SQL背后都是对业务的理解、对数据的敬畏、对性能的权衡。愿你的查询永远走索引愿你的事务永远不冲突愿你的表永远没有脏数据。我们进阶篇见。—— 致敬每一位认真学完数据库初识篇的你D