详解MySQL执行事务的语法和流程
摘要:MySQL 提供了多种存储引擎来支持事务。
MySQL 提供了多种存储引擎来支持事务。支持事务的存储引擎有 InnoDB 和 BDB,其中,InnoDB 存储引擎事务主要通过 UNDO 日志和 REDO 日志实现,MyISAM 存储引擎不支持事务。
拓展:任何一种数据库,都会拥有各种各样的日志,用来记录数据库的运行情况、日常操作、错误信息等,MySQL 也不例外。例如,当用户 root 登录到 MySQL 服务器,就会在日志文件里记录该用户的登录时间、执行操作等。
为了维护 MySQL 服务器,经常需要在 MySQL 数据库中进行日志操作:
- UNDO 日志:复制事务执行前的数据,用于在事务发生异常时回滚数据。
- REDO 日志:记录在事务执行中,每条对数据进行更新的操作,当事务提交时,该内容将被刷新到磁盘。
默认设置下,每条 SQL 语句就是一个事务,即执行 SQL 语句后自动提交。为了达到将几个操作做为一个整体的目的,需要使用 BEGIN 或 START TRANSACTION 开启一个事务,或者禁止当前会话的自动提交。
执行事务的语法和流程
SQL 使用下列语句来管理事务。
1) 开始事务
BEGIN;
或
START TRANSACTION;
这个语句显式地标记一个事务的起始点。
2) 提交事务
MySQL 使用下面的语句来提交事务:
COMMIT;
COMMIT 表示提交事务,即提交事务的所有操作,具体地说,就是将事务中所有对数据库的更新都写到磁盘上的物理数据库中,事务正常结束。
提交事务,意味着将事务开始以来所执行的所有数据都修改成为数据库的永久部分,因此也标志着一个事务的结束。一旦执行了该命令,将不能回滚事务。只有在所有修改都准备好提交给数据库时,才执行这一操作。
3) 回滚(撤销)事务
MySQL 使用以下语句回滚事务:
ROLLBACK;
ROLLBACK 表示撤销事务,即在事务运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始时的状态。这里的操作指对数据库的更新操作。
当事务执行过程中遇到错误时,使用 ROLLBACK 语句使事务回滚到起点或指定的保持点处。同时,系统将清除自事务起点或到某个保存点所做的所有的数据修改,并且释放由事务控制的资源。因此,这条语句也标志着事务的结束。
总结
BEGIN 或 START TRANSACTION 语句后面的 SQL 语句对数据库数据的更新操作都将记录在事务日志中,直至遇到 ROLLBACK 语句或 COMMIT 语句。如果事务中某一操作失败且执行了 ROLLBACK 语句,那么在开启事务语句之后所有更新的数据都能回滚到事务开始前的状态。如果事务中的所有操作都全部正确完成,并且使用了 COMMIT 语句向数据库提交更新数据,则此时的数据又处在新的一致状态。
实例演示
下面通过两个例子来演示一下 MySQL 事务的具体用法。
例1
下面模拟在张三的账户减少 500 元后,李四的账户还未增加 500 时,有其他会话访问数据表的场景。由于代码需要在两个窗口中执行,为了方便阅读,这里我们称为 A 窗口和 B 窗口。
1) 在 A 窗口中开启一个事务,并更新 mybank 数据库中 bank 表的数据,SQL 语句和运行结果如下:
mysql> USE mybank;
Database changed
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> UPDATE bank SET currentMoney = currentMoney-500
-> WHERE customerName='张三';
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0
2) 在 B 窗口中查询 bank 数据表中的数据,SQL 语句和运行结果如下:
mysql> SELECT * FROM mybank.bank;
+--------------+--------------+
| customerName | currentMoney |
+--------------+--------------+
| 张三 | 1000.00 |
| 李四 | 1.00 |
+--------------+--------------+
2 rows in set (0.00 sec)
从结果可以看出,虽然 A 窗口中的事务已经更改了 bank 表中的数据,但没有立即更新数据,这时其他会话读取到的仍然是更新前的数据。
3) 在 A 窗口中继续执行事务并提交事务,SQL 语句和运行结果如下:
mysql> UPDATE bank SET currentMoney = currentMoney+500
-> WHERE customerName='李四';
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> COMMIT;
Query OK, 0 rows affected (0.07 sec)
4) 在 B 窗口中再次查询 bank 数据表的数据,SQL 语句和运行结果如下:
mysql> SELECT * FROM mybank.bank;
+--------------+--------------+
| customerName | currentMoney |
+--------------+--------------+
| 张三 | 500.00 |
| 李四 | 501.00 |
+--------------+--------------+
2 rows in set (0.00 sec)
在 A 窗口中执行 COMMIT 提交事务后,对数据所做的更新将一起提交,其他会话读取到的是更新后的数据。从结果可以看出张三和李四的总账户余额和转账前保持一致,这样数据从一个一致性状态更新到另一个一致性状态。
前面提到,当事务在执行中出现问题,也就是不能按正常的流程执行一个完整的事务时,可以使用 ROLLBACK 语句进行回滚,使用数据恢复到初始状态。
在例 1 中,张三的账户余额已经减少到 500 元,如果再转出 1000 元,将会出现余额为负数,因此需要回滚到原始状态。如例 2 所示。
例2
将张三的账户余额减少 1000 元,并让事务回滚,SQL 语句和运行结果如下所示:
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec) mysql> UPDATE bank SET currentMoney = currentMoney-1000 WHERE customerName='张三';
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> ROLLBACK;
Query OK, 0 rows affected (0.07 sec) mysql> SELECT * FROM mybank.bank;
+--------------+--------------+
| customerName | currentMoney |
+--------------+--------------+
| 张三 | 500.00 |
| 李四 | 501.00 |
+--------------+--------------+
2 rows in set (0.00 sec)
从结果可以看出,执行事务回滚后,账户数据恢复到初始状态,即该事务执行之前的状态。
拓展
在数据库操作中,为了有效保证并发读取数据的正确性,提出了事务的隔离级别。在例 1 和例 2 的演示中,事务的隔离级别为默认隔离级别。在 MySQL 中,事务的默认隔离级别是 REPEATABLE-READ (可重读)隔离级别,即事务未结束时(未执行 COMMIT 或 ROLLBACK),其它会话只能读取到未提交数据。
注意事项
MySQL 事务是一项非常消耗资源的功能,大家在使用过程中要注意以下几点。
1) 事务尽可能简短
事务的开启到结束会在数据库管理系统中保留大量资源,以保证事务的原子性、一致性、隔离性和持久性。如果在多用户系统中,较大的事务将会占用系统的大量资源,使得系统不堪重负,会影响软件的运行性能,甚至导致系统崩溃。
2) 事务中访问的数据量尽量最少
当并发执行事务处理时,事务操作的数据量越少,事务之间对相同数据的操作就越少。
3) 查询数据时尽量不要使用事务
对数据进行浏览查询操作并不会更新数据库的数据,因此应尽量不使用事务查询数据,避免占用过量的系统资源。
4) 在事务处理过程中尽量不要出现等待用户输入的操作
在处理事务的过程中,如果需要等待用户输入数据,那么事务会长时间地占用资源,有可能造成系统阻塞。
本文分享自华为云社区《MySQL执行事务的语法和流程》,原文作者:运气男孩。
详解MySQL执行事务的语法和流程的更多相关文章
- 详解Mysql分布式事务XA(跨数据库事务)
详解Mysql分布式事务XA(跨数据库事务) 学习了:http://blog.csdn.net/soonfly/article/details/70677138 mysql执行XA事物的时候,mysq ...
- 详解MySQL索引
原文链接详解MySQL索引 索引介绍 索引是帮助MySQL高效获取数据的数据结构.在数据之外,数据库系统还维护着一个用来查找数据的数据结构,这些数据结构指向着特定的数据,可以实现高级的查找算法. 本文 ...
- [深入学习Web安全](5)详解MySQL注射
[深入学习Web安全](5)详解MySQL注射 0x00 目录 0x00 目录 0x01 MySQL注射的简单介绍 0x02 对于information_schema库的研究 0x03 注射第一步—— ...
- Mysql常用show命令,show variables like xxx 详解,mysql运行时参数
MySQL中有很多的基本命令,show命令也是其中之一,在很多使用者中对show命令的使用还容易产生混淆,本文汇集了show命令的众多用法. 详细: http://dev.mysql.com/doc/ ...
- MySQL存储过程详解 mysql 存储过程
原文地址:MySQL存储过程详解 mysql 存储过程作者:王者佳暮 mysql存储过程详解 1. 存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储 ...
- MySQL数据类型 int(M) 表示什么意思?详解mysql int类型的长度值问题
MySQL 数据类型中的 integer types 有点奇怪.你可能会见到诸如:int(3).int(4).int(8) 之类的 int 数据类型.刚接触 MySQL 的时候,我还以为 int(3) ...
- 【文章阅读】详解MySQL数据类型
详解MySQL数据类型 - 五月的仓颉 - 博客园 http://www.cnblogs.com/xrq730/p/8446246.html 注:对于MySQL的数据类型做了详细的讲解,这是我看过的最 ...
- 《Android游戏开发详解》一1.7 控制流程第1部分——if和else语句
本节书摘来异步社区<Android游戏开发详解>一书中的第1章,第1.7节,译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区"异步社区"公众号查看. 1.7 ...
- 详解Mysql事务隔离级别与锁机制
一.概述 我们的数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能 就会导致我们说的脏写. 胀读和不可重复读.幻读这些问题. 这些问题的本质都是数据库的多事务并 ...
随机推荐
- pyhon 自动化 logger
#!/Users/windows8.1/PycharmProjects/pythonapi# @Software: PyCharm Community Edition# -*- coding: utf ...
- IOS实现自动定位和手动选择城市功能
IOS自动定位使用的是高德地图SDK 在高德开放平台http://lbs.amap.com/api/ios-sdk/down/ 下载2D地图SDK和搜索SDK 将SDK导入工程内 按照高德的配置说明进 ...
- npm的下载与安装
1.Node (1)什么是Node.js Node.js 就是运行在服务端的 JavaScript.Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台. (2)Node ...
- 30道 有趣的 的 JVM 面试题
目录 1.JVN内存结构 2.对象分配规则 3.解释内存中的栈(stack).堆(heap)和静态区(static area)的用法 4.Perm Space中保存什么数据?会引起OutOfMemor ...
- openstack高可用集群17-openstack集成Ceph准备
Openstack集成Ceph准备 Openstack环境中,数据存储可分为临时性存储与永久性存储. 临时性存储:主要由本地文件系统提供,并主要用于nova虚拟机的本地系统与临时数据盘,以及存储gla ...
- [MVC] - Asynchronous操作
最近在项目里遇到个问题,是在MVC的项目里处理异步操作的,操作流程是这样的: 1.从MVC的一个controller调用一个异步方法: public ActionResult CreateOrUpda ...
- 解决Vue-router 报NavigationDuplicated的三种方法
控制台会报[NavigationDuplicated {_name: "NavigationDuplicated", name: "NavigationDuplicate ...
- [leetcode349]Intersection of Two Arrays
设计的很烂的一道题 List<Integer> res = new ArrayList<>(); // int l1 = nums1.length; // int l2 = n ...
- [leetcode]205. Isomorphic Strings同构字符串
哈希表可以用ASCII码数组来实现,可以更快 public boolean isIsomorphic(String s, String t) { /* 思路是记录下每个字符出现的位置,当有重复时,检查 ...
- golang unsafe.Pointer与uintptr
原文地址:https://blog.fanscore.cn/p/33/ 先说结论 uintptr 是一个地址数值,它不是指针,与地址上的对象没有引用关系,垃圾回收器不会因为有一个uintptr类型的值 ...