展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

事务概述

  • 登录mysql后使用如下命令,查看存储引擎对事务的支持情况
SHOW ENGINES
# 只有InnoDB 是支持事务
  • 简介
事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态
事务处理的原则:保证所有事务都作为 一个工作单元 来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交( commit ),
那么这些修改就 永久 地保存下来;要么数据库管理系统将 放弃 所作的所有 修改 ,整个事务回滚( rollback )到最初状态。
  • 事务的ACID特性
原子性(atomicity):
原子性是指事务是一个不可分割的工作单位,要么全部提交,要么全部失败回滚。
一致性(consistency):
根据定义,一致性是指事务执行前后,数据从一个 合法性状态 变换到另外一个 合法性状态 。这种状态是 语义上 的而不是语法上的,跟具体的业务有关。
那什么是合法的数据状态呢?满足 预定的约束 的状态就叫做合法的状态。通俗一点,这状态是由你自己来定义的(比如满足现实世界中的约束)。满足这个状态,数据就是一致的,
不满足这个状态,数据就是不一致的!如果事务中的某个操作失败了,系统就会自动撤销当前正在执行的事务,返回到事务操作之前的状态。
隔离型(isolation):
事务的隔离性是指一个事务的执行 不能被其他事务干扰 ,即一个事务内部的操作及使用的数据对 并发 的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability):
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是 永久性的 ,接下来的其他操作和数据库故障不应该对其有任何影响。
持久性是通过 事务日志 来保证的。日志包括了 重做日志 和 回滚日志 。当我们通过事务对数据进行修改的时候,首先会将数据库的变化信息记录到重做日志中,
然后再对数据库中对应的行进行修改。这样做的好处是,即使数据库系统崩溃,数据库重启后也能找到没有更新到数据库系统中的重做日志,重新执行,从而使事务具有持久性
  • 事务状态
活动的(active)
事务对应的数据库操作正在执行过程中时,我们就说该事务处在 活动的 状态。
部分提交的(partially committed)
当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并 没有刷新到磁盘时,我们就说该事务处在 部分提交的 状态。
失败的(failed)
当事务处在 活动的 或者 部分提交的 状态时,可能遇到了某些错误(数据库自身的错误、操作系统错误或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,
我们就说该事务处在 失败的 状态。
中止的(aborted)
如果事务执行了一部分而变为 失败的 状态,那么就需要把已经修改的事务中的操作还原到事务执行前的状态。换句话说,就是要撤销失败事务对当前数据库造成的影响。
我们把这个撤销的过程称之为 回滚 。当 回滚 操作执行完毕时,也就是数据库恢复到了执行事务之前的状态,我们就说该事务处在了 中止的 状态。
提交的(committed)
当一个处在 部分提交的 状态的事务将修改过的数据都 同步到磁盘 上之后,我们就可以说该事务处在了 提交的 状态。

  • 显示事务
# 开启显示事务方式1
BEGIN;
# 开启显示事务方式2
mysql> START TRANSACTION;
# START TRANSACTION 语句相较于 BEGIN 特别之处在于,后边能跟随几个 修饰符 :
① READ ONLY :标识当前事务是一个 只读事务 ,也就是属于该事务的数据库操作只能读取数据,而不能修改数据。
② READ WRITE :标识当前事务是一个 读写事务 ,也就是属于该事务的数据库操作既可以读取数据,也可以修改数据。
WITH CONSISTENT SNAPSHOT :启动一致性读。
# 开启事务后进行dml操作
# 提交事务
COMMIT;
# 回滚事务
ROLLBACK;
# 将事务回滚到某个保存点。
ROLLBACK TO [SAVEPOINT]
# 设置保存点
savepoint 保存点名称;
# 删除保存点
release savepoint 保存点名称;
  • 隐式事务
# 查看隐式事务是否开启,默认是ON
SHOW VARIABLES LIKE 'autocommit';
# 在隐式事务中,每1条DML操作是一个独立的事务,会自动提交
UPDATE account SET balance = balance - 10 WHERE id = 1;
# 关闭自动提交
# 方式1:针对于DML操作是有效的,对DDL操作是无效的
SET autocommit = FALSE;
# 方式2
SET autocommit = 0;
# 执行dml操作
UPDATE account SET balance = balance - 10 WHERE id = 1;
# 手动提交
COMMIT;
# 回滚
rollback;
# 在autocommit为true的情况下,使用start transaction 或begin开启事务,那么DML操作就不会自动提交数据
# 开启显示事务
START TRANSACTION;
# 执行dml
UPDATE account SET balance = balance - 10 WHERE id = 1;
# 提交
COMMIT;
# 回滚
rollback;
  • 隐式提交数据的情况(即自动提交)
1、数据库定义语言(DDL)
2、隐式使用或修改mysql数据库中的表:
当我们使用ALTER USERCREATE USERDROP USERGRANT、RENAME USERREVOKE、SETPASSWORD等语句时也会隐式的提交前边语句所属于的事务。
3、事务控制或关于锁定的语句
① 当我们在一个事务还没提交或者回滚时就又使用 START TRANSACTION 或者 BEGIN 语句开启了另一个事务时,会 隐式的提交 上一个事务
BEGIN;
#DDL
SELECT ...
UPDATE ...
#没有结束又开始下一条事务,自动隐式提交
BEGIN
②当前的autocommit系统变量的值为OFF,我们手动把它调为ON时,也会隐式的提交前边语句所属的事务。
③使用LOCK TABLES、UNLOCK TABLES等关于锁定的语句也会隐式的提交前边语句所属的事务。
4、加载数据库的语句
使用LOAD DATA语句来批量往数据库中导入数据时,也会隐式的提交前边语句所属的事务。
5、关于MySQL复制的一些语句
使用START SLAVE、STOP SLAVE、RESET SLAVE、CHANGE MASTER TO等语句时会隐式的提交前边语句所属的事务。
6、其他一些语句
使用ANALYZE TABLE、CACHE INDEX、CHECKTABLE、FLUSH、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE、RESET等语句也会隐式的提交前边语句所属的事务。
  • 代码案例
# 默认情况下进行测试,即autocommit = TRUE
SET autocommit = TRUE;
# 举例1commitrollback
USE atguigudb2;
# 情况1:使用BEGIN
# 创建表
CREATE TABLE user3(NAME VARCHAR(15) PRIMARY KEY);
# 查看表,没有数据
SELECT * FROM user3;
# 开启事务
BEGIN;
INSERT INTO user3 VALUES('张三'); #此时不会自动提交数据
COMMIT;
#开启一个新的事务
BEGIN;
INSERT INTO user3 VALUES('李四'); #此时不会自动提交数据
INSERT INTO user3 VALUES('李四'); #受主键的影响,不能添加成功
ROLLBACK;
# 表中只有1条数据“张三”
SELECT * FROM user3;
#情况2:不使用BEGIN
# 清空表中数据
TRUNCATE TABLE user3; #DDL操作会自动提交数据,不受autocommit变量的影响。
# 查看表中没有数据
SELECT * FROM user3;
# 添加1条数据
BEGIN;
INSERT INTO user3 VALUES('张三'); #此时不会自动提交数据
COMMIT;
# 添加2条数据
INSERT INTO user3 VALUES('李四');# 默认情况下(即autocommit为true),DML操作也会自动提交数据。
INSERT INTO user3 VALUES('李四'); #事务的失败的状态
# 回滚
ROLLBACK;
# 表中有2条数据
SELECT * FROM user3;
  • 事务分类
扁平事务(Flat Transactions)
带有保存点的扁平事务(Flat Transactions with Savepoints)
链事务(Chained Transactions)
嵌套事务(Nested Transactions)
分布式事务(Distributed Transactions)
  • completion变量
completion=0,这是默认情况。当我们执行COMMIT的时候会提交事务,在执行下一个事务时,还需要使用START TRANSACTION 或者BEGIN来开启。
completion=1,这种情况下,当我们提交事务后,相当于执行了COMMIT AND CHAIN,也就是开启一个链式事务,即当我们提交事务之后会开启一个
相同隔离级别的事务。
completion=2,这种情况下 COMMIT=COMMIT AND RELEASE,也就是当我们提交后,会自动与服务器断开连接。
  • 使用completion
# 情况3
# 清空表中数据
TRUNCATE TABLE user3;
# 表中没有数据
SELECT * FROM user3;
# 查看变量
SELECT @@completion_type;
# 设置变量
SET @@completion_type = 1;
# 插入数据
BEGIN;
INSERT INTO user3 VALUES('张三');
COMMIT;
# 表中有1条数据
SELECT * FROM user3;
# 插入2条数据
INSERT INTO user3 VALUES('李四');
INSERT INTO user3 VALUES('李四'); # 插入失败
# 回滚
ROLLBACK;
# 表中只有1条数据“张三”
SELECT * FROM user3;
  • 不同存储引擎中测试
#举例2:体会INNODB 和 MyISAM
# 创建2张表,并指定不同存储引擎
CREATE TABLE test1(i INT) ENGINE = INNODB;
CREATE TABLE test2(i INT) ENGINE = MYISAM;
#针对于innodb表
# 插入1条数据,并回滚
BEGIN
INSERT INTO test1 VALUES (1);
ROLLBACK;
# 表中没有数据
SELECT * FROM test1;
#针对于myisam表:不支持事务
# 插入1条数据,并回滚
BEGIN
INSERT INTO test2 VALUES (1);
ROLLBACK;
# 表中有1条数据
SELECT * FROM test2;
  • savepoint使用案例
# 创建表
CREATE TABLE user3(NAME VARCHAR(15),balance DECIMAL(10,2));
# 添加1条数据
BEGIN
INSERT INTO user3(NAME,balance) VALUES('张三',1000);
COMMIT;
# 查看为1000
SELECT * FROM user3;
# 减少200
BEGIN;
UPDATE user3 SET balance = balance - 100 WHERE NAME = '张三';
UPDATE user3 SET balance = balance - 100 WHERE NAME = '张三';
#设置保存点
SAVEPOINT s1;
# 加1
UPDATE user3 SET balance = balance + 1 WHERE NAME = '张三';
#回滚到保存点
ROLLBACK TO s1;
# 查询为800
SELECT * FROM user3;
#回滚操作
ROLLBACK;
# 回滚为1000
SELECT * FROM user3;
posted @   DogLeftover  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
历史上的今天:
2021-06-21 vue3.0入门(五):vite构建vue项目
2021-06-21 vue3.0入门(四):组件
点击右上角即可分享
微信分享提示