共计 1503 个字符,预计需要花费 4 分钟才能阅读完成。
文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号。
上一篇着重谈到了 MySQL 锁的概念,里面谈到了事务的概念,其实大部分开发者对于事务肯定不陌生,事务的概念其实就是一组 SQL 语句组成一个执行单元,如果单元中的某个 SQL 语句执行出现异常,则需要将整个事务进行回滚到未修改的状态。只有单元中全部 SQL 语句都成功执行,才会提交数据代表事务执行成功。而 Mysql 其实前几篇我们都已经知道是支持多种存储引擎的,其实正是因为 MyISAM 引擎不支持事务被 InnoDB 取代的原因。所以本篇文章主要是针对 InnoDB 引擎详细了解下事务这个概念。
事务特性
- 原子性: 事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
- 一致性:事务中包含的处理要满足数据库提前设置的约束,如主键约束或者 NOT NULL 约束等。
- 隔离性:事务处理过程中的中间状态对外部是不可见的。
- 持久性:事务完成之后,它对于数据的修改是永久性的。
隔离性的四种隔离级别
InnoDB 引擎支持的 4 种事务隔离级别分别是:读未提交、读已提交、可重复读、串行读。
- 读未提交:允许脏读,可以读取其他 session 中未提交的脏数据。
- 读已提交:不可读取其他 session 尚未提交的数据,只有其他 session 数据已提交才能读取到,为不重复读。
- 可重复读:该级别下可重复读,InnoDB 引擎默认采用可重复读,不允许读取还未提交的脏数据,但是可能存在 InnoDB 独有的幻读。
- 串行读:该级别下隔离程度最高,事务只能一个接着一个串行执行,无法并发执行。每次串行读都需要获得表级共享锁,读写操作都会阻塞。
幻读
事务在插入一条已经经过检查不存在的记录,但是插入结果是数据已经存在,之前的检查操作如同幻影。Mysql 默认采用可重复读级别,所以只可能出现幻读的情况。
设置事务隔离级别
可以在 my.ini 文件中 [mysqld] 下配置 transaction-isolation 属性,隔离性的四个值为:READ-UNCOMMITTED、READ-COMMITIED、REPEATABLE-READ、SERIALIZABLE,分别对应读未提交、读已提交、可重复读、串行读四种隔离级别。
事务分类
事务一般分为两种:隐式事务和显示事务。在 Mysql 中,事务默认是自动提交的,所以说每个 DML 语句实际上就是一次事务的过程。
隐式事务:没有开启和结束的标志,默认执行完 SQL 语句就自动提交,比如我们经常使用的 INSERT、UPDATE、DELETE 语句就属于隐式事务。
显示事务:需要显示的开启关闭,然后执行一系列操作,最后如果全部操作都成功执行,则提交事务释放连接,如果操作有异常,则回滚事务中的所有操作。
事务使用步骤
开启事务:关闭自动提交,然后开启事务。
事务操作:一系列 DML 语句执行。
事务结束:根据事务操作成功与否选择提交事务或者回滚事务操作。
接下来我们简单的使用事务实现用户 A 向用户 B 转账的操作:
创建用户表并插入两条用户数据:
配置数据库连接信息:
接下来从连接池中取出一个数据库连接并进行数据库连接:
数据库连接成功,则使用 connection 对象开启事务:
然后查询转账账号与待转账账号是否存在,并进行转账等一系列操作,这里由于魔鬼回调的原因我这里使用 async 库变成链式调用:
最后根据事务操作的成功或失败进行事务提交或者事务回滚,并且释放数据库连接:
然后可以测试转账成功的情况可以发现转账操作成功了
再次测试转账失败的操作可以发现扣除 A 积分和增加 B 积分的操作全部被回滚了,所以 A 和 B 的积分余额都没有发生改变
欢迎关注公众号:程序猿周先森。文章原创于微信公众号,本平台不定时更新。