四、MySQL 事务

1、 数据库事务的概念

  • 在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。
  • 为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。
  • 事务的操作:先定义开始一个事务,然后对数据作修改操作,这时如果提交(COMMIT),这些修改就永久地保存下来,如果回退(ROLLBACK),数据库管理系统将放弃您所作的所有修改而回到开始事务时的状态。

2、事务的ACID

    1. 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
    1. 一致性(Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
    1. 隔离性(Isolation)事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
    1. 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
  • 数据库的事务由下列语句组成:
    • 一组DML语句,修改的数据在他们中保持一致

    • 一个 DDL (Data Define Language) 语句

    • 一个 DCL (Data Control Language)语句

    • DCL(Grant(赋于权限 ) / Revoke(回收权限 ))

    • 1、开始于第一个执行的语句

    • 2、结束于:

      • 用户执行COMMIT 或 ROLLBACK。
      • 单个的DDL or DCL 语句。
      • 用户连接异常错误,或者用户断开连接 。
      • 系统崩溃。

3、事务控制语句

  • COMMIT和 ROLLBACK可以显式的控制事务。
  • 好处:
    • 1、保证数据一致性,修改过的数据在没有提交之前是不能被其他用户看到的。
    • 2、在数据永久性生效前重新查看修改的数据
    • 3、将相关操作组织在一起,一个事务中相关的数据改变或者都成功,或者都失败。

4、事务的隔离级别

  • SQL 中定义了四种隔离级别, 每种级别都规定了一个事务所做的修改,哪些在事务内和事务间是可见的, 哪些是不可见的. 较低的隔离通常可以执行更高的并发, 系统的开销也更低.

  • SQL 标准中的四种隔离有:

    • READ UNCOMMITED(未提交读)
      在 READ UNCOMMITED 级别中, 事务的修改, 即使没有提交, 对其他事务也是可见的. 其他事务可以读取此事务中的未提交的数据, 这也被称为脏读(Dirty Read). 此事务隔离级别会导致很多问题, 并且性能也不会比其他事务隔离级别好多少, 因此在实际环境中很少使用.
    • READ COMMITED(提交读)
      大多数的数据库默认隔离级别都是 READ COMMITED, 但是 MySQL 并不是. 在 READ COMMITED 级别中, 一个事务从开始到提交之前, 所做的任何修改对其他事务都是不可见的.

    这个级别有时候也叫做不可重复读(nonrepeatable read), 因为两次执行相同的查询, 可能会得到不一样的结果.

    • REPEATABLE READ(可重复读),可重复读是 MySQL 的默认事务隔离级别.
      REPEATABLE READ 解决了脏读的问题. 该级别保证了在同一个事务中多次读取同样记录的结果时一致的. 但是理论上, 可重复读隔离级别还是无法解决另一个幻读(Phantom Read)的问题. 所谓幻读, 指的是当某个事务在读取某个范围内的记录时, 另外一个事务又在该范围内插入了新的记录, 当之前的事务再次读取该范围的记录时, 会产生幻行(Phantom Row).

    • SERIALIZABLE(可串行化)
      SERIALIZABLE 是最高的隔离级别. 他通过强制事务串行执行, 避免了前面说的幻读的问题. 简单来说, SERIALIZABLE 会在读取的每一行数据上都加上锁, 所以可能导致大量的超时和锁争用的问题. 实际应用中也很少用到这个隔离级别, 只有在非常需要确保数据的一致性而且可以接受没有并发的情况下, 才考虑采用该级别.

5、死锁

  • 死锁是指两个或多个事务在同一个资源上相互占用, 并请求锁定对方占用的资源, 从而导致恶性循环的现象. 当多个事务试图以不同顺序锁定资源时, 就可能产生死锁.
  • 死锁发生以后, 只有部分或者完全回滚其中一个事务, 才能打破死锁.

6、MySQL 中的事务

  • 在 MySQL 提供的众多存储引擎中, 只有 InnoDB 和 NDB Cluster 支持事务.

  • 关于自动提交(AUTOCOMMIT)

    • MySQL 默认采用自动提交(AUTOCOMMIT) 模式. 即如果不显示地开始一个事务, 则每个操作都被当做一个事务执行提交操作.
      我们可以通过 SHOW VARIABLES LIKE 'autocommit';
  • 查询当前是否已经开启了字段提交事务, 例如:

  • 如果是 ON, 则表示已经开启了, 0 或 OFF 表示禁用.
  • 可以通过 set autocommit=0; 来禁用自动提交:

7、自动提交和非自动提交的区别

  • 下面以一个例子来展示 autocommit 启动和非启动时的区别.首先建立一个测试用的表:
  • 接着关闭自动提交功能: mysql> set autocommit=0;

  • 然后插入一个数据: mysql> INSERT INTO user (id,name,age) VALUES (1, 'xys', 18);

  • 接着查看数据:

  • 数据库中可以查询到这条数据了.

  • 但是我们通过 SHOW BINLOG EVENTS 查看操作日志:

  • 会发现上面的输出中, 并没有插入数据相关的记录, 并且此时如果我们退出 MySQL 的话, 那么我们插入的数据并没有被保存:

  • 如果我们不退出, 而是输入COMMIT; 时, 那么此时数据才真正保存到 MySQL 中:
  • 从上面的操作中我们可以看到, 当禁用了 AUTOCOMMIT 后, 我们对数据库的写入操作并不会实际落地到数据库中, 除非我们显示地提交事务.

  • 接下来, 我们使能 AUTOCOMMIT, 再次进行相同的操作.

  • 然后插入一个数据: mysql> INSERT INTO user (id,name,age) VALUES (1, 'xys', 18);

  • 接着查看数据:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容