深入了解MySQL中的事务、4大特性、隔离级别

本篇文章是mysql的进阶学习,给大家详细介绍一下mysql中的事务、4大特性(acid)以及事务的隔离级别,希望对大家有所帮助!

深入了解MySQL中的事务、4大特性、隔离级别

【相关推荐:mysql视频教程】

本文操作和测试所用的环境版本是5.7.21

mysql> select version();+-----------+| version() |+-----------+| 5.7.21    |+-----------+1 row in set (0.00 sec)

记住:我们常见的MySQL存储引擎中只有InnoDB是支持事务的。所以下面的操作也都是在InnoDB下做的。

一. 什么是事务

事务就是现实中抽象出来一种逻辑操作,要么都执行,要么都不执行,不能存在部分执行的情况。

比较经典的案例就是银行转账:小A向小B转账100元

正常的情况:小A的账户扣减100元,小B的账户增加100元。

非正常情况: 小A的账户扣减100元,小B账户金额不变。

非正常情况下,小A账户扣减100之后银行系统出现问题,小B账户增加100元的操作并没有执行。也就是两边金额对不上了,小A不愿意,小B不愿意,银行也不愿意啊。事务的出现就是为了避免非正常情况的出现,让大家都满意。

二. 事务的4大特性(ACID)

1. 原子性(Atomicity)

事务的操作是不可分割的,要么都操作,要么都不操作,就像转账一样,不存在中间状态。而且这个原子性不是说只有一个动作,可能会有很多的操作,但是从结果上看是不可分割的,也就是说原子性是一个结果状态。

2. 一致性(Consistency)

执行事务的前后,数据保持一致,就像银行账户系统一样无论事务是否成功,两者的账户总额应该是一样的。

3. 隔离性(Isolation)

多个事务同时操作数据的时候,多个事务直接互相隔离,不会互相影响。

4. 持久性(Durability)

一个事务在提交后对数据的影响是永久的,写入磁盘中不会丢失。

三. 显式事务、隐式事务

mysql的事务分为显式事务和隐式事务,默认的事务是隐式事务,由变量autocommit 在操作的时候会自动开启,提交,回滚。

控制的关键命令如下

set autocommit=0; -- 关闭自动提交事务(显式)set autocommit=1; -- 开启自动提交事务(隐式)  -- 当autocommit=0的时候手动控制事务rollback; -- 回滚事务commit;  -- 提交事务-- 当autocommit=1 自动提交事务,但是可以控制手动提交start transaction; -- 开启事务(或者用begin开启事务)commit; -- 提交事务rollback; -- 回滚事务SAVEPOINT 保存点名称;  -- 保存点(相当于存档,可以不用回滚全部操作)rollback to  保存点;  -- 回滚到某个保存点 (这个后面就不测试,知道有这个操作就行)

先建一张表ajisun

mysql> create table ajisun(id int(5), name varchar(20) character set utf8  COLLATE utf8_bin ) engine=innodb character set= utf8mb4 COLLATE = utf8mb4_bin;Query OK, 0 rows affected (0.03 sec)

1. 隐式事务

-- 看下当前autocommit的状态是,默认是on状态mysql> show variables like 'autocommit'; +---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit    | ON    |+---------------+-------+1 row in set (0.01 sec)--  插入一条数据mysql> insert into ajisun values(1,'阿纪');Query OK, 1 row affected (0.00 sec)mysql> rollback;-- 执行rollback 也是没有效果的,还是能够查询到插入的数据(不需要我们手动控制commit)mysql> select * from ajisun;+------+--------+| id   | name   |+------+--------+|    1 | 阿纪   |+------+--------+1 row in set (0.00 sec)

2. 显式事务方式1

显式事务由我们自己控制事务的开启,提交,回滚等操作

-- 开启显式事务-回滚mysql> set autocommit=0;Query OK, 0 rows affected (0.00 sec)mysql> select * from ajisun;+------+--------+| id   | name   |+------+--------+|    1 | 阿纪   |+------+--------+1 row in set (0.00 sec)mysql> insert into ajisun values(2,'纪先生');Query OK, 1 row affected (0.00 sec)-- 插入后可以看见2条数据mysql> select * from ajisun;+------+-----------+| id   | name      |+------+-----------+|    1 | 阿纪      ||    2 | 纪先生    |+------+-----------+2 rows in set (0.00 sec)-- 回滚之后上面插入的数据就没了mysql> rollback;Query OK, 0 rows affected (0.00 sec)mysql> select * from ajisun;+------+--------+| id   | name   |+------+--------+|    1 | 阿纪   |+------+--------+1 row in set (0.00 sec)
-- 插入一条数据mysql> insert into ajisun values(2,'ajisun');Query OK, 1 row affected (0.01 sec)-- 提交mysql> commit;Query OK, 0 rows affected (0.00 sec)-- 回滚mysql> rollback;Query OK, 0 rows affected (0.00 sec)-- 先提交commit,在rollback 数据依然存在,说明commit生效,事务已提交,回滚就不生效了。mysql> select * from ajisun;+------+--------+| id   | name   |+------+--------+|    1 | 阿纪   ||    2 | ajisun |+------+--------+2 rows in set (0.00 sec)

3. 显式事务方式2

使用start transaction

先改成默认的事务 set autocommit=1;

-- 开启事务mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> delete from ajisun where id=1;Query OK, 1 row affected (0.00 sec)-- 提交事务mysql> commit;Query OK, 0 rows affected (0.01 sec)mysql> select * from ajisun;+------+--------+| id   | name   |+------+--------+|    2 | ajisun |+------+--------+1 row in set (0.00 sec)
-- 开启事务mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> delete from ajisun where id =2;Query OK, 1 row affected (0.01 sec)-- 回滚事务mysql> rollback;Query OK, 0 rows affected (0.01 sec)-- 删除操作失效了mysql> select * from ajisun;+------+--------+| id   | name   |+------+--------+|    2 | ajisun |+------+--------+1 row in set (0.00 sec)

四. 并发事务中的问题

如果对表的操作同一时间只有一个事务就不会有问题,但是这是不可能的。现实中都是尽可能的利用,多个事务同时操作。多个事务就会带来不少的问题,例如脏读,脏写,`不可重复读,幻读

1. 脏读

一个事务读取到另一个未提交事务修改后的数据 这就是脏读。

例如两个事务a,b: 同时操作一条记录

a事务修改记录后还没有正式提交到数据库,这时b事务去读取,然后用读取到的数据进行后续操作。

如果a事务回滚了,这个修改后的数据就不存在了,那么b事务就是在使用一个不存在的数据。这种就是脏数据。

2. 脏写(数据丢失)

一个事务修改了另一个未提交事务修改过的数据

例如两个事务a,b: 同时操作一条记录

a事务修改后没有提交, 接着b事务也修改同一条数据,然后b事务提交数据。

如果a事务回滚自己的修改,同时也把b事务的修改也回滚了,造成的问题就是:b事务修改了 也提交了,但是数据库并没有改变,这种情况就是脏写。

3. 不可重复读

一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事务都能查询得到最新值。

也就是在同一个事务中多次读取同一条记录,得到的内容都不一样(在每次读取之前都有其他事务完成修改并提交),这就是不可重复读。

天工大模型 天工大模型

中国首个对标ChatGPT的双千亿级大语言模型

天工大模型 115 查看详情 天工大模型

4. 幻读

在一个事务内 相同条件查询数据,先后查询到的记录数不一样

也就是一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来,那就意味着发生了幻读

不可重复读和幻读的区别:不可重复读重点在于同一条记录前后数据值不一样(内容的变化),而幻读重点在于相同查询条件前后所获取的记录数不一样(条数的变化)

五. 事务的隔离级别

上面说的事务的并发问题,在不同的场景下要求不一样,能接受的问题也不一样。他们之间的严重性排序如下:

脏写 > 脏读 > 不可重复读 > 幻读

MySQL中提供了4种隔离级别来处理这几个问题,如下

隔离级别 脏读 不可重复读 幻影读

READ- UNCOMMITTED√√√READ-COMMITTED×√√REPEATABLE-READ××√SERIALIZABLE×××

SQL 标准定义了四个隔离级别:

READ-UNCOMMITTED(读未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、不可重复读和幻读。但是并发度最高READ-COMMITTED(读已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读和不可重复读仍有可能发生。REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,该级别可以防止脏读、不可重复读以及幻读。并发度也是最低的

MySQL默认采用的 REPEATABLE_READ 隔离级别 Oracle默认采用的 READ_COMMITTED 隔离级别

1. 如何设置隔离级别

可以通过变量参数transaction_isolation 查看隔离级别

mysql> SELECT @@transaction_isolation;+-------------------------+| @@transaction_isolation |+-------------------------+| REPEATABLE-READ         |+-------------------------+1 row in set (0.00 sec)mysql> show variables like '%transaction_isolation%';+-----------------------+-----------------+| Variable_name         | Value           |+-----------------------+-----------------+| transaction_isolation | REPEATABLE-READ |+-----------------------+-----------------+1 row in set (0.02 sec)

修改的命令:SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL $[level];

level的值就是4中隔离级别READ-UNCOMMITTED READ-COMMITTED REPEATABLE-READ SERIALIZABLE

设置全局隔离级别

只对执行完该语句之后产生的会话起作用。

当前已经存在的会话无效。

set global transaction_isolation='read-uncommitted';set global transaction_isolation='read-committed';set global transaction_isolation='repeatable-read';set global transaction_isolation='serializable';

例如:

会话A

mysql> set global transaction_isolation='serializable';Query OK, 0 rows affected (0.01 sec)mysql> select @@global.transaction_isolation;+--------------------------------+| @@global.transaction_isolation |+--------------------------------+| SERIALIZABLE                   |+--------------------------------+1 row in set (0.00 sec)-- 当前会话(设置之前就已经存在的会,级别是默认的)mysql> select @@transaction_isolation;+-------------------------+| @@transaction_isolation |+-------------------------+| REPEATABLE-READ         |+-------------------------+1 row in set (0.00 sec)

会话B(set之后新建的会话)

mysql> select @@global.transaction_isolation;+--------------------------------+| @@global.transaction_isolation |+--------------------------------+| SERIALIZABLE                   |+--------------------------------+1 row in set (0.00 sec)mysql> select @@transaction_isolation;+-------------------------+| @@transaction_isolation |+-------------------------+| SERIALIZABLE            |+-------------------------+1 row in set (0.00 sec)

设置会话的隔离级别

对当前会话的所有后续的事务有效

该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务。

如果在事务之间执行,则对后续的事务有效。

set session transaction_isolation='read-uncommitted';set session transaction_isolation='read-committed';set session transaction_isolation='repeatable-read';set session transaction_isolation='serializable';

比如:

会话A

mysql> set session transaction_isolation='read-uncommitted';Query OK, 0 rows affected (0.00 sec)mysql> select @@transaction_isolation;+-------------------------+| @@transaction_isolation |+-------------------------+| READ-UNCOMMITTED        |+-------------------------+1 row in set (0.00 sec)

新建会话B(依然是默认的级别:可重复读)

mysql> select @@transaction_isolation;+-------------------------+| @@transaction_isolation |+-------------------------+| REPEATABLE-READ         |+-------------------------+1 row in set (0.00 sec)

2. 怎么选择隔离级别

一般情况下默认的可重复读就好了,一般很少改这个,除非业务场景特殊

记住一点:隔离级别越高,并发问题就越少,但并发性也就越低,所以还是要根据业务选择来。

六. 总结

事务的四大特性:原子性,一致性,隔离性,持久性

事务的常见命令:

set autocommit=0/1; -- 关闭/开启自动提交事务start transaction; -- 开启事务(或者用begin)rollback; -- 回滚事务commit; -- 提交事务

并发事务的问题:脏写 > 脏读 > 不可重复读 > 幻读

需要熟悉事务的4种隔离级别以及MySQL默认级别

怎么设置隔离级别(global,session)

更多编程相关知识,请访问:编程入门!!

以上就是深入了解MySQL中的事务、4大特性、隔离级别的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/289166.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
VSCode代码片段创建和使用教程
上一篇 2026年10月20日 15:57:07
AnimaTensor— 吐司AI等推出的二次元图像生成模型
下一篇 2026年10月2日 09:01:17

相关推荐

  • MySQL中备份与恢复 数据库备份策略及实际操作指南

    备份与恢复需选对方式、定策略、验可用、自动化。mysql备份分物理(如percona xtrabackup)与逻辑(如mysqldump),前者适合大库,后者适合小库或迁移;建议生产环境用“每周全量+每日增量”组合,并启用binlog;恢复时要定期测试备份有效性,验证完整性、导入性、一致性及时间;最…

    2026年10月20日
    000
  • Mysql索引失效怎么办?失效原因浅析

    Mysql索引失效怎么办?失效原因浅析Mysql索引失效怎么办?失效原因浅析Mysql索引失效怎么办?失效原因浅析Mysql索引失效怎么办?失效原因浅析

    本篇文章给大家记录一次mysql索引失效,分析一下mysql索引失效原因,希望对大家有所帮助! 此文章包含Mysql的Where条件查询执行过程、范围查询使联合索引停止匹配、回表操作分析、常见索引失效场景、Extra分析等知识。【相关推荐:mysql视频教程】 背景 6千万数据量的数据表出现了一个满…

    2026年10月20日 • 用户投稿
    100
  • Kubernetes是什么?如何基于它部署MySQL数据库

    Kubernetes是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便对应用请求进行负载均衡。在Kubernetes中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通过内置的负载均衡策略,实…

    2026年10月20日
    000
  • 深入了解MySQL中的组合索引,看看与单列索引的区别

    深入了解MySQL中的组合索引,看看与单列索引的区别深入了解MySQL中的组合索引,看看与单列索引的区别深入了解MySQL中的组合索引,看看与单列索引的区别深入了解MySQL中的组合索引,看看与单列索引的区别

    本篇文章带大家了解一下mysql中的组合索引,介绍一下创建、删除组合索引的方法,聊聊组合索引陷阱、组合索引与单列索引的区别、组合索引使用场景,希望对大家有所帮助! 什么是组合索引 两个或更多个列上的索引被称作联合索引,联合索引又叫组合索引。【相关推荐:mysql视频教程】 例如索引是 key ind…

    2026年10月20日 • 用户投稿
    000
  • 聊聊mysql-connector-java怎么连接驱动

    本篇文章给大家介绍关于mysql-connector-java连接驱动问题,希望对大家有所帮助! mysql-connector-java连接驱动问题 mysql-connector-java 5中的驱动是com.mysql.jdbc.Driver , mysql-connector-java 6中…

    2026年10月20日
    100
  • 分析Macosx下使用docker/mysql的问题

    本篇文章给大家介绍关于macosx 下如何使用docker/mysql的问题,希望对大家有所帮助! 问题描述 在macosx下如果指定本地目录替换/var/lib/mysql,运行时会出现文件权限的错误,导致mysqld无法正常运行 Creating mysql_test-mysql_1Attach…

    2026年10月20日
    100
  • mysql 怎么查询月份

    mysql 怎么查询月份mysql 怎么查询月份mysql 怎么查询月份mysql 怎么查询月份

    mysql查询月份的方法:1、通过“select date_format(DATE_SUB(curdate(), INTERVAL 0 MONTH), ‘%m’)”查询当前月份;2、通过“INTERVAL 1 MONTH”查询上个月份。 本文操作环境:Windows7系统、m…

    2026年10月20日 • 用户投稿
    000
  • debian 怎么安装mysql

    debian 怎么安装mysqldebian 怎么安装mysqldebian 怎么安装mysqldebian 怎么安装mysql

    debian安装mysql的方法:1、下载安装Mysql APT Repository;2、直接通过命令“apt-get install mysql-server”安装即可。 本文操作环境:debian10系统、mysql8.0、Dell G3。 debian 怎么安装mysql? Debian10…

    2026年10月20日 • 用户投稿
    100
  • brew怎么安装mysql

    brew怎么安装mysqlbrew怎么安装mysqlbrew怎么安装mysqlbrew怎么安装mysql

    brew安装mysql的方法:1、执行“brew install mysql@5.7”命令;2、启动mysql;3、登录mysql并修改默认密码即可。 本文操作环境:macOS10.15系统、mysql5.7版、macbook pro 2020电脑。 brew怎么安装mysql? Mac使用brew…

    2026年10月20日 • 用户投稿
    300
  • 使用VSCode进行数据库操作

    使用VSCode进行数据库操作使用VSCode进行数据库操作使用VSCode进行数据库操作使用VSCode进行数据库操作

    VSCode通过安装SQLTools等扩展可连接MySQL、PostgreSQL等数据库,配置连接后能执行查询、浏览表数据及管理结构,适合轻量级数据库操作。 Visual Studio Code(VSCode)本身不是数据库管理工具,但通过安装扩展插件,可以方便地连接和操作多种数据库,如 MySQL…

    2026年10月20日 • 用户投稿
    100
  • postgresql和mysql的区别是什么

    postgresql和mysql的区别是什么postgresql和mysql的区别是什么postgresql和mysql的区别是什么postgresql和mysql的区别是什么

    区别:1、PGSQL没有CPU核心数限制,而mysql有限制;2、PGSQL的配置文件参数一共有255个,MySQL一共有707个;3、PGSQL支持多字段统计信息,而MySQL不支持;4、PGSQL支持执行计划即时编译,MySQL不支持。 本教程操作环境:windows7系统、PostgreSQL…

    2026年10月20日 • 用户投稿
    000
  • 什么是mysql索引

    什么是mysql索引什么是mysql索引什么是mysql索引什么是mysql索引

    在mysql中,索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录。通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列即可。 本教程操作环境:windows7系统、mysql8版本、Dell G3电脑。 索引是一种特殊的数据库结构,由数据…

    2026年10月20日 • 用户投稿
    200
  • 利用Fetch API在Canvas点击事件中实现JS到PHP的数据传递

    本文详细阐述了如何在同一页面中实现JavaScript与PHP之间的数据传递,特别是在处理Canvas点击事件时。通过利用现代Web API中的Fetch API,前端JavaScript可以异步地将用户点击的坐标和像素颜色等信息发送至后端PHP脚本进行处理,从而实现动态的数据查询和响应,避免页面刷…

    2026年10月20日
    500
  • mysql怎么进行索引修改

    mysql怎么进行索引修改mysql怎么进行索引修改mysql怎么进行索引修改mysql怎么进行索引修改

    mysql修改索引的方法:1、使用“DROP INDEX 索引名 ON 表名”语句删除原索引;2、使用“ALTER TABLE 表名 ADD INDEX 索引名 [索引类型] (列名,…)”语句根据需要创建一个同名的索引即可。 本教程操作环境:windows7系统、mysql8版本、Dell G3电…

    2026年10月20日 • 用户投稿
    400
  • mysql与sql的区别是什么

    mysql与sql的区别是什么mysql与sql的区别是什么mysql与sql的区别是什么mysql与sql的区别是什么

    mysql与sql的区别是:1、SQL是一种用于操作数据库的语言;MySQL是一个开源的数据库管理系统,一个数据库软件。2、SQL用于访问,更新和操作数据库中的数据;MySQL用于管理数据库中的数据。 本教程操作环境:windows7系统、mysql8.0.22版本、Dell G3电脑。 mysql…

    2026年10月20日 • 用户投稿
    200
  • mysql怎么给字段增加自增属性

    mysql怎么给字段增加自增属性mysql怎么给字段增加自增属性mysql怎么给字段增加自增属性mysql怎么给字段增加自增属性

    在mysql中,可以通过给字段添加“AUTO_INCREMENT”属性来给字段增加自增属性,语法“alter table 表名 add column 字段名 数据类型 AUTO_INCREMENT;”。 本教程操作环境:windows7系统、mysql8版本、Dell G3电脑。 通过给字段添加 A…

    2026年10月20日 • 用户投稿
    100
  • mysql是什么数据库

    mysql是什么数据库mysql是什么数据库mysql是什么数据库mysql是什么数据库

    mysql是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,属于Oracle旗下产品;MySQL软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,一般中小型网站的开发都选择MySQL作为网站数据库。 本文操作环境:Windows7系统、mysql8.0版、De…

    2026年10月20日 • 用户投稿
    100
  • mysql求和语句是什么

    mysql求和语句是什么mysql求和语句是什么mysql求和语句是什么mysql求和语句是什么

    mysql求和语句是“select sum(money) from record t where t.name = ?”,其中参数t表示一个表的别名。 本文操作环境:Windows7系统、Mysql5.7.14版、Dell G3电脑。 mysql求和语句是什么? 示例:查询在record表中 nam…

    2026年10月20日 • 用户投稿
    100
  • 在Java中如何实现内部类封装与访问控制_OOP内部类访问实践经验

    在Java中如何实现内部类封装与访问控制_OOP内部类访问实践经验在Java中如何实现内部类封装与访问控制_OOP内部类访问实践经验在Java中如何实现内部类封装与访问控制_OOP内部类访问实践经验在Java中如何实现内部类封装与访问控制_OOP内部类访问实践经验

    内部类提升封装与组织,成员内部类可访问外部私有成员并支持私有化,静态内部类降低耦合与内存开销,局部及匿名内部类适用于临时逻辑与回调,合理使用可增强安全性与可维护性。 在Java中,内部类是面向对象编程的重要特性之一,它允许将一个类的定义嵌套在另一个类内部,从而实现更紧密的封装和逻辑组织。合理使用内部…

    2026年10月20日 • 用户投稿
    100
  • mysql是开源的吗

    mysql是开源的吗mysql是开源的吗mysql是开源的吗mysql是开源的吗

    mysql原本是开源的,也就是一个开放源码的关系数据库管理系统,但是MySQL的license现在分为免费的社区版与收费的标准版、企业版等。 本文操作环境:Windows7系统、Mysql5.7.14版、Dell G3电脑。 mysql是开源的吗? mysql原本是开源的。 MySQL(官方发音为/…

    2026年10月20日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信