24人参与 • 2026-04-28 • Mysql
先抛出一个问题:curd不加控制,会有什么问题?

从上面的图我们可以看到,如果单纯的curd操作可能导致数据不一致的问题(线程并发问题)!
curd满足什么属性,怎么解决上面的问题呢?
- 事务就是一组dml语句组成,这些语句在逻辑上存在相关性,这一组dml语句要么全部成功,要么全部失败,是一个整体。mysql提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。
- 事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。假设一种场景:你毕业了,学校的教务系统后台 mysql 中,不在需要你的数据,要删除你的所有信息(一般不会:) ), 那么要删除你的基本信息(姓名,电话,籍贯等)的同时,也删除和你有关的其他信息,比如:你的各科成绩,你在校表现,甚至你在论坛发过的文章等。这样,就需要多条 mysql 语句构成,那么所有这些操作合起来,就构成了一个事务。
正如我们上面所说,一个 mysql 数据库,可不止你一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,在向 mysql 服务器发起事务处理请求。而每条事务至少一条 sql ,最多很多 sql ,这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现问题。甚至,因为事务由多条 sql 构成,那么,也会存在执行到一半出错或者不想再执行的情况,那么已经执行的怎么办呢?
所有,一个完整的事务,绝对不是简单的 sql 集合,还需要满足如下四个属性:
上面四个属性,可以简称为 acid 。
事务被 mysql 编写者设计出来,本质是为了当应用程序访问数据库的时候,事务能够简化我们的编程模型,不需要我们去考虑各种各样的潜在错误和并发问题.可以想一下当我们使用事务时,要么提交,要么回滚,我们不会去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?因此事务本质上是为了应用层服务的.而不是伴随着数据库系统天生就有的.
在 mysql 中只有使用了 innodb 数据库引擎的数据库或表才支持事务, myisam 不支持。
查看数据库引擎
show engines; -- 表格显示

show engines \g; -- 行显示

事务的提交方式常见的有两种:
查看事务提交方式
show variables like 'autocommit';

用 set 来改变 mysql 的自动提交模式:
set autocommit = 0; -- 禁止自动提交

set autocommit = 1; -- 开启自动提交

事务常见操作方式

为了便于演示,我们将mysql的默认隔离级别设置成读未提交
set global transaction isolation level read uncommitted;

创建测试表
create table if not exists account(
id int primary key,
name varchar(50) not null default ' ',
balance decimal(10,2) not null default 0.0
)engine=innodb default charset=utf8;正常演示 - 证明事务的开始与回滚
show variables like 'autocommit'; -- 查看事务是否自动提交。我们故意设置成自动提交,看看该选项是否影响begin start transaction; -- 开始一个事务begin也可以,推荐begin savepoint s1; -- 创建一个保存点s1 insert into account values(1,'张三',1263.4); -- 插入一条记录 savepoint s2; -- 创建一个保存点s2 insert into account values(2,'李四',6521.9); -- 再插入一条记录 select * from account; -- 两条记录都在了 +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 1263.40 | | 2 | 李四 | 6521.90 | +----+--------+---------+ 2 rows in set (0.00 sec) rollback to s2; -- 回滚到保存点save2 select * from account; -- id为2的一条记录没有了 +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 1263.40 | +----+--------+---------+ 1 row in set (0.00 sec) rollback; -- 直接rollback,回滚在最开始 select * from account; -- 所有刚刚的记录没有了 empty set (0.00 sec)
非正常演示1 - 证明未commit,客户端崩溃,mysql自动会回滚(隔离级别设置为读未提交)
-- 终端a select * from account; -- 当前表内无数据 show variables like 'autocommit'; -- 依旧自动提交 begin; --开启事务 insert into account values(1,'张三',1566.7); -- 插入记录 -- 终端b select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 1566.70 | +----+--------+---------+ 1 row in set (0.00 sec) -- 终端a mysql> aborted -- ctrl + \ 异常终止mysql -- 终端b select * from account; empty set (0.00 sec)

非正常演示2 - 证明commit了,客户端崩溃,mysql数据不会在受影响,已经持久化
show variables like 'autocommit'; -- 依旧自动提交 +---------------+-------+ | variable_name | value | +---------------+-------+ | autocommit | on | +---------------+-------+ 1 row in set (0.00 sec) select * from account; -- 当前表内无数据 empty set (0.00 sec) begin; -- 开启事务 insert into account values (1, '张三', 1234.4); -- 插入记录 commit; --提交事务 aborted -- ctrl + \ 异常终止mysql --终端 b select * from account; --数据存在了,所以commit的作用是将数据持久化到mysql中

非正常演示3 - 对比试验。证明begin操作会自动更改提交方式,不会受mysql是否自动提交影响
mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 1234.40 | +----+--------+---------+ 1 row in set (0.00 sec) mysql> show variables like 'autocommit'; +---------------+-------+ | variable_name | value | +---------------+-------+ | autocommit | on | +---------------+-------+ 1 row in set (0.01 sec) mysql> set autocommit=0; query ok, 0 rows affected (0.00 sec) mysql> show variables like 'autocommit'; +---------------+-------+ | variable_name | value | +---------------+-------+ | autocommit | off | +---------------+-------+ 1 row in set (0.01 sec) mysql> begin; query ok, 0 rows affected (0.00 sec) mysql> insert into account values(2,'李四',6543.2); query ok, 1 row affected (0.00 sec) mysql> aborted

非正常演示4 - 证明单条 sql 与事务的关系
实验一
mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 1234.40 | +----+--------+---------+ 1 row in set (0.00 sec) mysql> system clear mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 1234.40 | +----+--------+---------+ 1 row in set (0.00 sec) mysql> set autocommit=0; query ok, 0 rows affected (0.00 sec) mysql> show variables like 'autocommit'; +---------------+-------+ | variable_name | value | +---------------+-------+ | autocommit | off | +---------------+-------+ 1 row in set (0.00 sec) mysql> insert into account values(2,'李四',6532.4); query ok, 1 row affected (0.00 sec) mysql> aborted

实验二
mysql> show variables like 'autocommit'; +---------------+-------+ | variable_name | value | +---------------+-------+ | autocommit | on | +---------------+-------+ 1 row in set (0.01 sec) mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 1234.40 | +----+--------+---------+ 1 row in set (0.00 sec) mysql> insert into account values(2,'李四',3526.4); query ok, 1 row affected (0.01 sec) mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 张三 | 1234.40 | | 2 | 李四 | 3526.40 | +----+--------+---------+ 2 rows in set (0.01 sec) mysql> aborted

结论:
事务操作注意事项
到此这篇关于mysql事务定义、起源、版本支持与提交方式的文章就介绍到这了,更多相关mysql事务详解内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论