首页 数据库 mysql教程 简单介绍MySQL中的事务机制_MySQL

简单介绍MySQL中的事务机制_MySQL

Jun 01, 2016 pm 01:00 PM
mysql

从一个问题开始

最近银行这个事情闹的比较厉害啊,很多储户的钱放在银行,就不翼而飞了,而银行还不管不问,说是用户的责任,打官司,用户还能输了,这就是“社会主义”。咱还是少发牢骚,多种树,莫谈国事。

说到银行存钱,就不得不说一下从银行取钱这件事情,从ATM机取钱这件简单的事情,实际上主要分为以下几个步骤:

  1.     登陆ATM机,输入密码;
  2.     连接数据库,验证密码;
  3.     验证成功,获得用户信息,比如存款余额等;
  4.     用户输入需要取款的金额,按下确认键;
  5.     从后台数据库中减掉用户账户上的对应金额;
  6.     ATM吐出钱;
  7.     用户把钱拿走。

一个简单的取钱,主要分为以上几步。不知道大家有没有“天真”的想过,如果在第5步中,后台数据库中已经把钱减掉了,但是ATM还就是没有吐出钱(虽然实际也发生过,但是毕竟是低概率事件),这该怎么办?

关于这个问题,银行系统的开发人员早就想过了,那么他们是怎么来搞定这个问题的呢?这就要说到今天总结的事务这个概念了。
简单说说事务

对于上面的取钱这个事情,如果有一步出现了错误,那么就取消整个取钱的动作;简单来说,就是取钱这7步,要么都完成,要么就啥也不做。在数据库中,事务也是这个道理。

事务由一条或者多条sql语句组成,在事务中的操作,这些sql语句要么都执行,要么都不执行,这就是事务的目的。

对于事务而言,它需要满足ACID特性,下面就简要的说说事务的ACID特性。

    A,表示原子性;原子性指整个数据库事务是不可分割的工作单位。只有使事务中所有的数据库操作都执行成功,整个事务的执行才算成功。事务中任何一个sql语句执行失败,那么已经执行成功的sql语句也必须撤销,数据库状态应该退回到执行事务前的状态;
    C,表示一致性;也就是说一致性指事务将数据库从一种状态转变为另一种一致的状态,在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏;
    I,表示隔离性;隔离性也叫做并发控制、可串行化或者锁。事务的隔离性要求每个读写事务的对象与其它事务的操作对象能相互分离,即该事务提交前对其它事务都不可见,这通常使用锁来实现;
    D,持久性,表示事务一旦提交了,其结果就是永久性的,也就是数据就已经写入到数据库了,如果发生了宕机等事故,数据库也能将数据恢复。

总结了一些事务的基本概念,在MySQL中,事务还是分为很多中的,下面就来看看到底有哪些事务。
有哪些事务

你能想象到吗?就这么个破事务还会分以下这么多种:

  1.     扁平事务;
  2.     带有保存点的扁平事务;
  3.     链事务;
  4.     嵌套事务;
  5.     分布式事务。

现在就来对这些事务从概念的层面上进行简单的总结一下。

    扁平事务
    扁平事务是最简单的一种,也是实际开发中使用的最多的一种事务。在这种事务中,所有操作都处于同一层次,最常见的方式如下:

   BEGIN WORK
     Operation 1
     Operation 2
     Operation 3
     ...
     Operation N
   COMMIT WORK

登录后复制

或者是这种:

   BEGIN WORK
     Operation 1
     Operation 2
     Operation 3
     ...
     Operation N
     (Error Occured)
   ROLLBACK WORK

登录后复制

扁平事务的主要缺点是不能提交或回滚事务的某一部分,或者分几个独立的步骤去提交。比如有这样的一个例子,我从呼和浩特去深圳,为了便宜,我可能这么干:

   BEGIN WORK
     Operation1:呼和浩特---火车--->北京
     Operation2:北京---飞机--->深圳
   ROLLBACK WORK

登录后复制

但是,如果Operation1,从呼和浩特到北京的火车晚点了,错过了航班,怎么办?感觉扁平事务的特性,那我就需要回滚,我再回到呼和浩特,那么这样成本是不是也太高了啊,所以就有了下面的第二种事务——带有保存点的扁平事务。
带有保存点的扁平事务
这种事务除了支持扁平事务支持的操作外,允许在事务执行过程中回滚到同一事务中较早的一个状态,这是因为可能某些事务在执行过程中出现的错误并不会对所有的操作都无效,放弃整个事务不合乎要求,开销也太大。保存点用来通知系统应该记住事务当前的状态,以便以后发生错误时,事务能回到该状态。
链事务
链事务,就是指回滚时,只能恢复到最近一个保存点;而带有保存点的扁平事务则可以回滚到任意正确的保存点。
嵌套事务
看下面这个,你就能明白了,啥是嵌套事务:

   BEGIN WORK
     SubTransaction1:
         BEGIN WORK
           SubOperationX
         COMMIT WORK
     SubTransaction2:
         BEGIN WORK
           SubOperationY
         COMMIT WORK
     ...
     SubTransactionN:
         BEGIN WORK
           SubOperationN
         COMMIT WORK
   COMMIT WORK

登录后复制

这就是嵌套事务,在事务中再嵌套事务,位于根节点的事务称为顶层事务。事务的前驱称为父事务,其它事务称为子事务。事务的前驱称为父事务,事务的下一层称为子事务。

子事务既可以提交也可以回滚,但是它的提交操作并不马上生效,除非由其父事务提交。因此就可以确定,任何子事务都在顶层事务提交后才真正的被提交了。同理,任意一个事务的回滚都会引起它的所有子事务一同回滚。
分布式事务
分布式事务通常是指在一个分布式环境下运行的扁平事务,因此需要根据数据所在位置访问网络中的不同节点,比如:通过建设银行向招商银行转账,建设银行和招商银行肯定用的不是同一个数据库,同时二者的数据库也不在一个网络节点上,那么当用户跨行转账,就是通过分布式事务来保证数据的ACID的。

MySQL中使用事务

理论总结的再好,终归都要通过实践来进行理解。下面就来说说MySQL中是如何使用事务的。

在MySQL命令行的默认设置下,事务都是自动提交的,即执行SQL语句后就会马上执行COMMIT操作。因此要显示地开启一个事务须使用命令BEGIN或START TRANSACTION,或者执行命令SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

来看看我们可以使用哪些事务控制语句。

  1. BEGIN或START TRANSACTION;显示地开启一个事务;
  2. COMMIT;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改称为永久性的;
  3. ROLLBACK;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
  4. SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;
  5. RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
  6. ROLLBACK TO identifier;把事务回滚到标记点;
  7. SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。

这些不用你“管”

有的时候有些SQL语句会产生一个隐式的提交操作,即执行完成这些语句后,会有一个隐式的COMMIT操作。有以下SQL语句,不用你去“管”:

  • DDL语句,ALTER DATABASE、ALTER EVENT、ALTER PROCEDURE、ALTER TABLE、ALTER VIEW、CREATE TABLE、DROP TABLE、RENAME TABLE、TRUNCATE TABLE等;
  • 修改MYSQL架构的语句,CREATE USER、DROP USER、GRANT、RENAME USER、REVOKE、SET PASSWORD;
  • 管理语句,ANALYZE TABLE、CACHE INDEX、CHECK TABLE、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE等。

以上的这些SQL操作都是隐式的提交操作,不需要手动显式提交。
事务的隔离级别

上面也说到了SET TRANSACTION用来设置事务的隔离级别。那事务的隔离级别是什么东东?

在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。

InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。这些隔离级别之间的区别如下:

2015413170207554.jpg (782×217)

  • 脏读:一个事务读取到了另外一个事务没有提交的数据;
  • 比如:事务T1更新了一行记录的内容,但是并没有提交所做的修改。事务T2读取到了T1更新后的行,然后T1执行回滚操作,取消了刚才所做的修改。现在T2所读取的行就无效了;
  • 不可重复读:在同一事务中,两次读取同一数据,得到内容不同;
  • 比如:事务T1读取一行记录,紧接着事务T2修改了T1刚才读取的那一行记录。然后T1又再次读取这行记录,发现与刚才读取的结果不同。这就称为“不可重复”读,因为T1原来读取的那行记录已经发生了变化;
  • 幻读:同一事务中,用同样的操作读取两次,得到的记录数不相同;
  • 比如:事务T1读取一条指定的WHERE子句所返回的结果集。然后事务T2新插入 一行记录,这行记录恰好可以满足T1所使用的查询条件中的WHERE子句的条件。然后T1又使用相同的查询再次对表进行检索,但是此时却看到了事务T2刚才插入的新行。这个新行就称为“幻像”,因为对T1来说这一行就像突然出现的一样。

隔离级别越低,事务请求的锁越少或保持锁的时间就越短。InnoDB存储引擎默认的支持隔离级别是REPEATABLE READ;在这种默认的事务隔离级别下已经能完全保证事务的隔离性要求,即达到SQL标准的SERIALIZABLE级别隔离。

我们可以可以用SET TRANSACTION语句改变单个会话或者所有新进连接的隔离级别。它的语法如下:

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

登录后复制

注意:默认的行为(不带session和global)是为下一个(未开始)事务设置隔离级别。如果使用GLOBAL关键字,语句在全局对从那点开始创建的所有新连接(除了不存在的连接)设置默认事务级别。你需要SUPER权限来做这个。使用SESSION 关键字为将来在当前连接上执行的事务设置默认事务级别。 任何客户端都能自由改变会话隔离级别(甚至在事务的中间),或者为下一个事务设置隔离级别。

mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)

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

登录后复制

总结

这篇文章,基本上都是理论概念的堆积,实战的东西基本没有。但是,这些都不是问题,这也无法阻挡这篇文章成为一篇读者喜欢的文章,是吧。好了,这篇关于MySQL中事务的文章就到此结束,以后如果有新的东西,就接着总结。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP 的大数据结构处理技巧 PHP 的大数据结构处理技巧 May 08, 2024 am 10:24 AM

大数据结构处理技巧:分块:分解数据集并分块处理,减少内存消耗。生成器:逐个产生数据项,无需加载整个数据集,适用于无限数据集。流:逐行读取文件或查询结果,适用于大文件或远程数据。外部存储:对于超大数据集,将数据存储在数据库或NoSQL中。

如何优化 PHP 中的 MySQL 查询性能? 如何优化 PHP 中的 MySQL 查询性能? Jun 03, 2024 pm 08:11 PM

可以通过以下方式优化MySQL查询性能:建立索引,将查找时间从线性复杂度降至对数复杂度。使用PreparedStatements,防止SQL注入并提高查询性能。限制查询结果,减少服务器处理的数据量。优化连接查询,包括使用适当的连接类型、创建索引和考虑使用子查询。分析查询,识别瓶颈;使用缓存,减少数据库负载;优化PHP代码,尽量减少开销。

如何在 PHP 中使用 MySQL 备份和还原? 如何在 PHP 中使用 MySQL 备份和还原? Jun 03, 2024 pm 12:19 PM

在PHP中备份和还原MySQL数据库可通过以下步骤实现:备份数据库:使用mysqldump命令转储数据库为SQL文件。还原数据库:使用mysql命令从SQL文件还原数据库。

如何使用 PHP 插入数据到 MySQL 表中? 如何使用 PHP 插入数据到 MySQL 表中? Jun 02, 2024 pm 02:26 PM

如何将数据插入MySQL表中?连接到数据库:使用mysqli建立与数据库的连接。准备SQL查询:编写一个INSERT语句以指定要插入的列和值。执行查询:使用query()方法执行插入查询,如果成功,将输出一条确认消息。

如何修复 MySQL 8.4 上的 mysql_native_password 未加载错误 如何修复 MySQL 8.4 上的 mysql_native_password 未加载错误 Dec 09, 2024 am 11:42 AM

MySQL 8.4(截至 2024 年的最新 LTS 版本)中引入的主要变化之一是默认情况下不再启用“MySQL 本机密码”插件。此外,MySQL 9.0完全删除了这个插件。 此更改会影响 PHP 和其他应用程序

如何在 PHP 中使用 MySQL 存储过程? 如何在 PHP 中使用 MySQL 存储过程? Jun 02, 2024 pm 02:13 PM

要在PHP中使用MySQL存储过程:使用PDO或MySQLi扩展连接到MySQL数据库。准备调用存储过程的语句。执行存储过程。处理结果集(如果存储过程返回结果)。关闭数据库连接。

如何使用 PHP 创建 MySQL 表? 如何使用 PHP 创建 MySQL 表? Jun 04, 2024 pm 01:57 PM

使用PHP创建MySQL表需要以下步骤:连接到数据库。创建数据库(如果不存在)。选择数据库。创建表。执行查询。关闭连接。

oracle数据库和mysql的区别 oracle数据库和mysql的区别 May 10, 2024 am 01:54 AM

Oracle数据库和MySQL都是基于关系模型的数据库,但Oracle在兼容性、可扩展性、数据类型和安全性方面更胜一筹;而MySQL则侧重速度和灵活性,更适合小到中等规模的数据集。①Oracle提供广泛的数据类型,②提供高级安全功能,③适合企业级应用程序;①MySQL支持NoSQL数据类型,②安全性措施较少,③适合小型到中等规模应用程序。

See all articles