MySQL事务与事务隔离级别(START TRANSACRION、COMMIT、ROLLBACK、SAVEPOINT、autocommit)
发布日期:2021-06-29 22:33:16 浏览次数:2 分类:技术文章

本文共 4174 字,大约阅读时间需要 13 分钟。

一、事务概述

  • 事务处理可以用来维护数据库的完整性,它保证成批的MySQL操作要么全部执行,要么全部不执行。
  • 事务处理是一种机制,用来管理必须成批执行的MySQL操作,以保证数据库不包含不完整的操作结果。利用事务处理,可以保证一组操作不会中途停止,它们或者作为整体执行,或者完全不执行(除非明确指示)。如果没有错误发生,整租语句提交给数据库。如果发生错误,则进行回退(撤销)以恢复数据库到某个已知且安全的状态。

并非所有引擎都支持事务处理

  • 只有InnoDB存储引擎才支持事务处理。

几个关键词

  • 事务(TRANSACTION):指一组SQL语句。
  • 回退(ROLLBACK):指撤销指定SQL语句的过程。
  • 提交(COMMIT):指将未存储的SQL语句结果写入数据库表。
  • 保留点(SAVEPOINT):指事务处理中设置的临时占位符(place-holder),你可以对它发布回退(与回退整个事务处理不同)。

事务的ACID性质

  • 事务系统通常具有“ACID”的四种特性,即:
    • 原子性(Atomic。构成事务的所有语句应该是一个独立的逻辑单元。你不能只执行它们当中的一部分。
    • 一致性(Consistent)。数据库在事务的执行前后都必须是一致的。例如,对于在某个表里的各行,其ID必须能在另外一个表里找到,否则,一个事务在试图插入带有无效id的行时会出现失败,然后会执行回滚操作。
    • 独立性(Isolated)。事务之间不应该相互影响,这样事务在并发执行时才会得到与挨个依次执行一样的效果。
    • 持久性(Durable)。当事务执行成功完成时,其影响将被永久性地记录到数据库里。

二、事务的开始(START TRANSACTION)

  • MySQL使用下面的语句来标识事务的开始
START TRANSACTION;

三、事务的回退(ROLLBACK)

  • MySQL使用rollback命令来进行回退(撤销)语句
  • 当使用rollback之后,本次事务会自动关闭

哪些语句可以回退?

  • insert、update、delete语句可以进行回退。
  • 不能回退select语句(这样做也没什么意义)。
  • 不能回退create或drop操作。

演示案例

  • 例如下面执行delete之后,我们将事务进行回退
select * from ordertotals;start transaction;delete from ordertotals;select * from ordertotals;rollback;select * from ordertotals;

四、事务的提交(COMMIT)

  • 事务处理中,当所有的事务处理完成之后,可以使用commit来提交(结束)本次事务
  • 当事务提交之前,如果语句出现了错误,那么本次事务会自动停止

演示案例

start transaction;delete from orderitems where order_num=20010;delete from orders where order_num=20010;commit;

隐含事务关闭

  • 当commit或rollback语句执行后,事务会自动关闭。

五、保留点(SAVEPOINT)

  • 可以使用savepoint设置保留点,当事务进行回退(rollback)时,只需要回退到某个保留点即可

设置保留点

savepoint 保留点名称;

回退到保留点

rollback to 保留点名称;

释放保留点

  • 保留点在事务处理完成(执行一条rollback或commit)会自动释放。但是你也可以使用release savepoint来明确释放保留点。
release savepoint 保留点名称;

六、更改默认的提交行为(autocommit)

  • MySQL语句执行时,默认会提交执行的MySQL语句,但是你也可以更改autocommit标志来指明是否自动提交SQL语句。
  • autocommit是针对单个连接的,而不是只针对整个服务器的。
--设置默认提交(MySQL的默认行为)set autocommit=1;--设置默认不提交, 必须要使用COMMIT提交set autocommit=0;

七、不能成为事务部分的语句

  • 正如刚才所述,无论是调用COMMITROLLBACK语句,还是在自动提交模式处于禁用模式时再次启用它,当前事务都会结束。在其他情形里,事务也会结束。
  • 除了SET autocoiranit、STRAT TRANSACTION、BEGIN、COMMIT和ROLLBACK等语句会显式地对事务产生影响外,还有另外一些语句,因为不能成为事务的一部分,而只会对事务产生隐式的影响。
  • 通常情况下,那些用来创建、更改或删除数据库或其中的对象的数据定义语言(Data Definition Language,DDL)语句,以及那些与锁定有关的语句都不能成为事务的一部分。例如,你在事务处理过程中调用了下列语句当中的某一条,那么服务器在执行这条语句之前将先提交当前事务:
ALTER TABLECREATE INDEXDROP DATABASEDROP INDEXDROP TABLELOCK TABLESRENAME TABLESET autocommit = 1 (if not already set to 1)TRUNCATE TABLEUNLOCK TABLES (if table currently are locked)
  • 具体有哪些语句会隐式地提交当前事务请参考官方文档。

八、事务隔离级别

  • 因为MySQL是一个多用户数据库系统,所以不同的客户端可能会在同一时间试图访问同一个表
    • 诸如MylSAM之类的存储引擎使用了表级的锁定机制,以此保证不同客户端不能同时改同一个表。但这种做法在大量更新时操作时,难以提供很好的并发性能。
    • InnoDB存储引擎采用的是另外一方法,它使用了比较底层的锁定方式,为客户端提供了更细致的表访问控制。在一个客户端修改某个行的同时,另一个客户端可以读取和修改同一个表里的另一个行。如果有两个客户端想要同时修改某个行,那么先锁定该行的那个客户端则可以先修改它。这比表级的锁定方式提供了更好的并发性能。不过,这里还有一个问题,即一个客户端的事务是否应该看到另一个客户端的事务所做的修改。
  • IrnioDB存储引擎实现的事务隔离级别功能,能够让客户端对它们想要看到的由其他事务所做的修改类型进行控制。它提供了多种不同的隔离级别,可以允许或预防在多个事务同时运行时可能出现的各类问题。
    • 脏读(dirty read)。它指的是,在某个事务所做的修改尚未提交时,其他事务就能看到这些修改。其他事务因此认为这些行已被修改;即使那个对行进行修改的事务后来被回滚,从而导致这些行并未真的被修改,其他事务也会那样认为。
    • 不可重复读(nonrepeatable read)。它指的是,同一个事务使用同一条SELECT语句在每次读取时得到的结果都不一样。如果有一个事务两次执行了同一条SELECT语句,但另一个事务在这条语句的两次执行期间修改了某些行,那么就会发生这种情况。
    • 幻影行(phantomrow)。它指的是,一个事务突然看到一个以前没有见过的行。假设某个事务在刚执行完一条SELECT语句之后,接着就有另一个事务插入了一个新的行。如果第一个事务再执行同样的一条SELECT语句,则可能会看到这个新增行,而它其实是一个幻影。
  • 为了解决这些问题,InnoDB存储引擎提供了4种事务隔离级别。这些隔离级别确定了一个事务所做的哪些修改可以被其他与之同时执行的事务所看到。
    • READ UNCOMMITTED。它允许某个事务看到其他事务尚未提交的行修改。
    • READ COMMITTED。它只允许某个事务看到其他事务已经提交的行修改。
    • REPEATABLE READ。如果某个事务两次执行同一条SELECT语句,其结果是可重复的。也就是说,即使有其他事务在同时插入或修改行,这个事务所看到的结果也是一样的。
    • SERIALIZABLE。它与REPEATABLE READ很相似,但对事务的隔离更彻底,主要表现在:对于某个事务正在査看的行,只有等到该事务完成才能被其他事务所修改。也就是说,如果某个事务正在读取某些行,那么在它完成之前,其他事务都将无法对这些行修改。
  • 下图列出了这4种隔离级别与脏读、不可重复读或幻影行这三个问题之间的认可关系。这个表格只适用于InnoDB存储引擎,其中REPEATABLER EAD级别不允许出现幻影行。而有些数据库系统的REPEATABLE READ级别却允许出现幻影行。

  • InnoDB存储引擎默认的隔离级别是REPEATABLE READ。更改它的方式有两种:
    • 在服务器启动时使用--transaction-isolation选项,
    • 或者在服务器运行时使用SET TRANSACTION语句。此语句有以下3种形式:
SET GLOBAL TRANSACTION ISOLATION LEVEL level;SET SESSION TRANSACTION ISOLATION LEVEL level;SET TRANSACTION ISOLATION LEVEL level;
  • 拥有SUPER权限的客户端,可以使用SET TRANSACTION语句来改变全局隔离级别,之后它会作用于后续的所有客户端连接。此外,所有客户端都可以修改其自己的事务隔离级別:
    • 用SET SESSION TRANSACTION语句做出的修改,将会对服务器当前会话里的所有后续事务起作用;
    • 而用SET TRANSACTION语句做出的修改,则只会对下一个事务起作用。客户端在修改其自己的隔离级别时,不需要任何特殊的权限。

事务和非事务表可以混用吗?

  • 在某次事务中可以将事务表和非事务表混合使用,但最终的结果不一定是你所期望的。对非事务表进行操作的语句总是会立刻生效,即便是自动提交模式处于禁用状态也是如此。
  • 事实上,非事务表永远待在自动提交模式下,每条语句都会在执行完毕后立刻提交。因此,如果你在某个事务里修改了一个非事务表,那么这个修改将无法被还原。

转载地址:https://dongshao.blog.csdn.net/article/details/104055508 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:MySQL数据类型——数字类型(整型、浮点型、BIT型)
下一篇:TCP/IP卷一:68---TCP连接管理之(TCP状态转换图、TIME_WAIT状态、静默时间、FIN_WAIT_2状态、同时打开/同时关闭的状态)

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月30日 08时05分54秒