MySQL事务定义、起源、版本支持与提交方式全面解析

 更新时间:2026年04月28日 09:52:17   作者:小林熬夜学编程  
数据库处理并发事务时,事务隔离级别是保证数据一致性的关键机制,下面这篇文章主要介绍了MySQL事务定义、起源、版本支持与提交方式的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

先抛出一个问题:CURD不加控制,会有什么问题?

从上面的图我们可以看到,如果单纯的CURD操作可能导致数据不一致的问题(线程并发问题)

CURD满足什么属性,怎么解决上面的问题呢?

  • 1. 买票的过程得是原子(要么买要么不买)的吧
  • 2. 买票互相应该不能影响
  • 3. 买完票应该要永久有效
  • 4. 买前,和买后都要是确定的状态吧 

1、什么是事务

  • 事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。MySQL提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的
  • 事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。假设一种场景:你毕业了,学校的教务系统后台 MySQL 中,不在需要你的数据,要删除你的所有信息(一般不会:) ), 那么要删除你的基本信息(姓名,电话,籍贯等)的同时,也删除和你有关的其他信息,比如:你的各科成绩,你在校表现,甚至你在论坛发过的文章等。这样,就需要多条 MySQL 语句构成,那么所有这些操作合起来,就构成了一个事务。

正如我们上面所说,一个 MySQL 数据库,可不止你一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,在向 MySQL 服务器发起事务处理请求。而每条事务至少一条 SQL ,最多很多 SQL ,这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现问题。甚至,因为事务由多条 SQL 构成,那么,也会存在执行到一半出错或者不想再执行的情况,那么已经执行的怎么办呢?

所有,一个完整的事务,绝对不是简单的 sql 集合,还需要满足如下四个属性

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。 
  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Readuncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化( Serializable )
  • 持久性事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

上面四个属性,可以简称为 ACID

  • 原子性(Atomicity,或称不可分割性)
  • 一致性(Consistency)
  • 隔离性(Isolation,又称独立性)
  • 持久性(Durability)。

2、为什么会出现事务

事务被 MySQL 编写者设计出来,本质是为了当应用程序访问数据库的时候,事务能够简化我们的编程模型,不需要我们去考虑各种各样的潜在错误和并发问题.可以想一下当我们使用事务时,要么提交,要么回滚,我们不会去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?因此事务本质上是为了应用层服务的.而不是伴随着数据库系统天生就有的.

  • 备注:我们后面把 MySQL 中的一行信息,称为一行记录 

3、事务的版本支持

在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务 MyISAM 不支持

查看数据库引擎

show engines; -- 表格显示

show engines \G; -- 行显示

4、事务提交方式

事务的提交方式常见的有两种:

  • 自动提交
  • 手动提交

查看事务提交方式

show variables like 'autocommit';

用 SET 来改变 MySQL 的自动提交模式: 

set autocommit = 0; -- 禁止自动提交

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

事务常见操作方式 

  • 使用netstat查看链接情况,可知:mysql本质是一个客户端进程 

为了便于演示,我们将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

结论:

  • 只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是否设置set autocommit无关。
  • 事务可以手动回滚,同时,当操作异常,MySQL会自动回滚
  • 对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交。(select有特殊情况,因为MySQL 有 MVCC )
  • 从上面的例子,我们能看到事务本身的原子性(回滚),持久性(commit)
  • 那么隔离性?一致性?

事务操作注意事项

  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)
  • 如果一个事务被提交了(commit),则不可以回退(rollback)
  • 可以选择回退到哪个保存点
  • InnoDB 支持事务, MyISAM 不支持事务
  • 开始事务可以使 start transaction 或者 begin 

总结 

到此这篇关于MySQL事务定义、起源、版本支持与提交方式的文章就介绍到这了,更多相关MySQL事务详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql数据库超过最大连接数的解决方法

    mysql数据库超过最大连接数的解决方法

    当mysql超过最大连接数时,会报错”Too many connections”,本文主要介绍了mysql数据库超过最大连接数的解决方法,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • MySQL中由load data语句引起死锁的解决案例

    MySQL中由load data语句引起死锁的解决案例

    这篇文章主要介绍了MySQL中由load data语句引起死锁的解决案例,文中讲到了InnoDB引擎的数据表中一些锁的机制,需要的朋友可以参考下
    2016-01-01
  • 关于mysql的时区问题

    关于mysql的时区问题

    这篇文章主要介绍了关于mysql的时区问题,具有很好的参考价值,希望对大家有所帮助,以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家,
    2023-11-11
  • mysql 从一个表中查数据并插入另一个表实现方法

    mysql 从一个表中查数据并插入另一个表实现方法

    这篇文章主要介绍了mysql 从一个表中查数据并插入另一个表实现方法的相关资料,需要的朋友可以参考下
    2017-05-05
  • 如何恢复MySQL主从数据一致性

    如何恢复MySQL主从数据一致性

    MySQL主从数据一致性怎么恢复,MySQL主从数据库的数据不一致,猜测备库在同步过程中出现了问题,现在的问题很明确,就是如何恢复主从库数据的一致性,下文为大家分享解决方法,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • mysql数据库常见的优化操作总结(经验分享)

    mysql数据库常见的优化操作总结(经验分享)

    这篇文章主要给大家介绍了关于mysql数据库常见的优化操作,文章总结的都是个人日常开发使用mysql数据库的经验所得,其中包括Index索引、少用SELECT*、EXPLAIN SELECT以及开启查询缓存等相关资料,相信会对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
    2017-04-04
  • 解决mysql登录报错:mysql:[Warning] Using a password on the command line interface can be insecure.ERROR 10

    解决mysql登录报错:mysql:[Warning] Using a password&

    MySQL root登录失败多因密码错误,解决方法包括:检查密码是否正确,确认对localhost的访问权限,启用并配置密码验证机制,修改my.cnf文件后重启服务,若问题持续,需联系技术支持
    2025-07-07
  • win7下MySql 5.7安装配置方法图文教程

    win7下MySql 5.7安装配置方法图文教程

    这篇文章主要为大家分享了win7下MySql 5.7安装配置方法图文教程,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • 修改MySQL所有表的编码或修改某个字段的编码步骤详解

    修改MySQL所有表的编码或修改某个字段的编码步骤详解

    这篇文章主要给大家介绍了关于修改MySQL所有表的编码或修改某个字段编码的相关资料,在进行数据库编码更改之前,需要先确定目标编码格式,常见的编码格式有UTF-8、GBK等,需要的朋友可以参考下
    2023-12-12
  • 浅析mysql union和union all

    浅析mysql union和union all

    union 是对数据进行并集操作,不包括重复行,同时进行默认排序而Union all 是对数据进行并集操作,包括重复行,不进行排序,下面给大家详细介绍mysql union和union all,感兴趣的朋友一起看看吧
    2017-10-10

最新评论