响应式网站建设服务商,做网站要用写接口,平台推广,wordpress主题源码事务 本章从了解为什么需要事务到讲述事务的四大特性和概念#xff0c;最后讲述MySQL中的事务使用语法以及一些需要注意的性质。 再额外讲述一点Springboot中Transactional注解的使用。 1.为什么需要事务#xff1f;
我们以用户转账为例#xff0c;假设用户A和用户B的银行账…事务 本章从了解为什么需要事务到讲述事务的四大特性和概念最后讲述MySQL中的事务使用语法以及一些需要注意的性质。 再额外讲述一点Springboot中Transactional注解的使用。 1.为什么需要事务
我们以用户转账为例假设用户A和用户B的银行账户中都有余额500元用户A向用户B转账200元在数据库中可以分解为如下操作
序号操作1用户A的余额-2002用户B的余额200
如果服务器在执行完第一条操作后服务器断电了那么用户A的余额就是300用户B的余额还是500为了不出现这种情况我们就需要用到事务来解决。 2.事务的四大特性(ACID) 事务四大特性的英文开头分别为AICD为了方便记忆调整顺序后为ACID酸的意思。 2.1 原子性(Atomicity)
顾名思义原子在某种意义上意味着不可分割事务的原子性将一个事务看作一个原子中间不能被分割。
以用户A向用户B的转账为例用户A余额-200用户B的余额200这个过程被看作一个事务要么这两个操作全都执行成功要么这两个操作全部执行失败不能出现其中一个执行成功另一个没有被执行的情况。
2.2 隔离性(Isolation)
隔离性指的是多个事务之间的隔离性事务之间不能相互干扰一个事务的运行不影响另一个事务的运行。
这里可能会有疑问什么情况下事务之间会相互影响我们同样以转账为例举例一种破坏隔离性的情况用户A、用户B和用户C都拥有500元的余额用户A向用户B转账200元的同时用户C向用户B转账200元。这里我们令事务T1用户A向用户B转账200元T2用户C向用户B转账200元。如果让A转账完再让C去转账这样不会出现问题但是如果A和C的转账过程是同时的可能就会出现问题下面以表格来说明从上到下为时间线同一行表示在同一个时间点执行的语句。
T1说明T2说明Aread(A)读取用户A的余额,当前A余额为500Cread©读取用户C的余额当前C的余额为500AA-200A的余额减少200当前A的余额为300CC-200C的余额减少200当前C的余额为300Write(A)将A的变化写回数据库Write©将C的变化写回数据库BRead(B)读取用户B的余额,当前B余额为500BRead(B)读取用户B的余额,当前B余额为500BB200B的余额增加200当前B的余额为700BB200B的余额增加200当前B的余额为700Write(B)将B的变化写回数据库Write(B)将A的变化写回数据库
这里我们会发现最终B的余额为700正确的应该为900才对这种就是两个事务之间相互影响了。
2.3 一致性(Consistency)
一致性表示数据库处理前后结果应与其所表示的客观世界中真实状况保持一致。
这怎么理解呢我们以隔离性中的例子来举例用户A和用户C同时向用户B转账隔离性出错后数据库中错误的状态下用户A的余额为300用户C的余额为300用户B的余额为700客观世界真实状态下应表示为用户A的余额为300用户C的余额为300用户B的余额为900这种状况下就出现了数据库前后处理结果与其所表示的客观世界的真实状况不一致。一致性就是要保证数据库中的结果和客观世界中的情况保持一致。
2.4 持久性(Durability)
持久化这个词可能都有听过就是让数据能够永久保存下来事务的持久性表示事务提交之后必须对数据库进行修改并且这个结果是永久保存的除非后来经过了更改。 3.事务的概念
把需要保证事务四大特性的一个或多个数据库操作称为事务。一个事务可能会经理的状态如下
活动的事务对应的数据库操作正在执行中。部分提交的事务对应的最后一个数据库操作执行完成后当前数据都还在内存中还没有刷盘这个状态下叫部分提交的。失败的由于停电、服务器死机或手动停止事务导致事务对应的数据库操作执行到一半就没办法继续执行了这种状态下成为失败的状态。中止的失败的状态下将已经执行过的数据库操作回滚后完成后也就是恢复到当前事务处理之前的状态后称为中止状态。提交的事务执行成功并且数据都刷盘成功。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7KWrZq2I-1677825883583)(D:\desktop\work\笔记\笔记图片素材\image-20230303124357290.png)]
只有当事务的状态处于中止的或者提交的时事务的生命周期才结束。 4.MySQL中事务的语法
4.1 开启事务 BEGIN [WORK] 开启一个事务WORK可有可无。 START TRANSACTION 开启一个事务后面可以跟几个修饰符 #修饰符
# READ ONLY表示只读READ WRITE可读写WITH CONSISTENT SNAPSHOT一致性读修饰符直接加在START TRANSACTION后面多个修饰符用逗号分隔READ ONLY和READ WRITE不能同时使用#只读
START TRANSACTION READ ONLY;
#可读写
START TRANSACTION READ WRITE;
#一致性读
START TRANSACTION WITH CONSISTENT SNAPSHOT;
#多个修饰符
START TRANSACTION READ ONLY,WITH CONSISTENT SNAPSHOT;4.2 提交事务 COMMIT [WORK] 提交事务WORK可有可无。 BEGIN;#一系列数据库操作#提交事务
COMMIT;4.3 手动中止事务 ROLLBACK [WORK] 回滚一个事务WORK可有可无。 BEGIN;#一系列数据库操作#回滚
ROLLBACK;4.4 支持事务的存储引擎
目前只有InnoDB和NDB支持事务。
4.5 自动提交
MySQL中的一个系统变量autocommit用来自动提交事务。
SHOW VARIABLES LIKE autocommit;----------------------
| Variable_name | Value |
----------------------
| autocommit | ON |
----------------------可以看到autocommit默认为ON开启状态如果不显示的使用BEGIN或START TRANSACTION开启事务那么每一条语句都会算作一个单独的事务进行提交。
如果设置autocommit为off那么运行的所有语句必须COMMIT后才能成功更新数据库。
4.6 隐式提交
当使用START TRANSACTION或BEGIN开启事务后在COMMIT之前使用某些语句可能会导致事务偷偷被提交了这就叫隐式提交。会导致事务隐式提交的语句有如下 DDL语句 CREATE、ALTER、DROP等语句修改数据库对象时就会隐式提交前面语句所属的事务。 隐式的使用或修改了mysql数据表。 比如ALTER USER、CREATE USER、DROP USER、GRANT、RENAME USER、REVOKE、SET PASSWORD等。 事务控制或关于锁定的语句 在事务COMMIT之前又使用了一次START TRANSACTION或BEGIN会隐式提交。使用LOCK TABLES、UNLOCK TABLES也会隐式提交。 关于MySQL复制的一些语句 SRART SLAVE、STOP SLAVE、RESET SLAVE、CHANGE MASTER TO等语句也会隐式提交前面语句所属的事务。 其他语句 ALALYZY TABLE、CHANGE INDEX、CHECK TABLE、FLUSH、LOAD INDEX INTO CHANGE、OPTIMIZE TABLE、REPAIR TABLE、RESET等语句。
4.7 保存点
MySQL事务支持在事务的执行过程中设置保存点可以使用ROLLBACK语句回滚到事务的某个特定保存点的状态。 SAVEPOINT 保存点名称 设置保存点。 ROLLBACK [WORK] TO [SAVEPOINT] 保存点名称 回滚到对应的保存点的状态。 RELEASE SAVEPOINT 保存点名称 释放对应的保存点。
示例
#开启事务
BEGIN;#更新日志表里的所有用户名为123
UPDATE log_tbl SET user_name 123;#设置保存点
SAVEPOINT s1;#更新日志表里的所有用户名为124
UPDATE log_tbl SET user_name 1234;#回滚到保存点s1时的状态
ROLLBACK TO s1;#释放保存点
RELEASE SAVEPOINT s1;#回滚整个事务
ROLLBACK;5.Transactional
再SpringbootMyBatis中使用事务非常简单只需要再需要以事务方式运行的函数上加Transactional注解即可下面以一个Controller接口为例
RequestMapping(/getToken)
ResponseBody
Transactional
public String reloadTokenByAppIdAndAppSecret(AccessApiConfirm data){return apiAccessConfirmService.reloadTokenByAppIdAndAppSecret(data);
}该注解可以加在接口、接口方法、类和类的方法上加在类上相当于给类的所有public方法加上了Transactional注解默认情况下加了Transactional注解的方法在抛出RuntimeException()异常后会回滚所有的数据库操作。
还可以进行参数配置
参数名称功能描述readOnly设置当前事务只读例Transactional(readOnlytrue)rollbackFor当抛出对应的异常的时候进行回滚操作例Transactional(rollbackFor{RuntimeException.class, Exception.class})指定抛出RuntimeException()和Exception()异常时回滚。rollbackForClassName当抛出对应的异常的时候进行回滚操作例Transactional(rollbackForClassName{“RuntimeException”,”Exception”})指定抛出RuntimeException()和Exception()异常时回滚。noRollbackFor该属性指定对应的异常抛出时不进行回滚例Transactional(noRollbackFor{RuntimeException.class, Exception.class})表示抛出RuntimeException()和Exception()异常时不进行回滚。Exception该属性指定对应的异常抛出时不进行回滚例Transactional(noRollbackForClassName{“RuntimeException”,”Exception”})表示抛出RuntimeException()和Exception()异常时不进行回滚。