• mysql InnoDB事务


    参考书籍《mysql是怎样运行的》
    以及极客时间《mysql实战45讲》
    本文总结事务相关的概念,事务相关的命令等,具体持久性,原子性,隔离性如何实现,会在后续的学习中进行补充
    

    系列文章目录和关于我

    一丶事务#

    上一篇关于buffer pool的学习中,我们学习Buffer pool相关知识,innodb再对某个页面进行读写访问时,会将这个页面读到buffer pool 中,之后如果修改了某个页面,也不会立即刷新到磁盘,而只是将缓冲页面的控制块添加到flush 链表中,之后某个时间点(后台定时任务线程每隔一定时间将flush 链表中的脏页刷新到磁盘,或者新的页面需要缓冲,将LRU链表中一些脏页刷盘)。那么如果mysql服务突然崩溃,或者服务器突然断电,岂不是已经提交的事务将丢失?

    事务是指是程序中一系列严密的逻辑操作,而且所有操作必须全部成功完成,否则在每个操作中所作的所有更改都会被撤消

    这里保证已经提交事务一定可以持久化到磁盘的就是redo log。如果事务执行到一半需要回滚如何实现昵,这就是undo log实现的版本控制链的作用。

    二丶事务特性#

    1.原子性#

    要么多个操作都执行,要么多个操作都不执行,不可存在中间状态。但是现实世界中一个业务存在多个步骤,这些步骤抽象为数据库操作又存在多个,一个数据库操作又可分为多步(比如先修改缓冲页,再刷新磁盘)任何一个时间点都可能发生意想不到的错误,使操作无法执行下去,所以需要保证:如果再执行过程中发生了错误,就把已经执行的操作恢复为执行前的样子。

    2.隔离性#

    对于现实世界中状态转换对应的某些数据库操作来说,不仅仅需要保证原子性,还需要保证其他数据库操作造成状态转换不会影响到本次状态转换。这便是隔离性

    3.一致性#

    只有符合约束的数据才是有效(年龄再符合规定的范围,房价不能为负数)如果数据中的数据全部符合现实世界的约束,我们就说这些数据具备一致性。如何实现一致性

    • 数据库本身可以保证一定的一致性(主键,唯一索引保证不可重复,申明某些列not null拒绝null值的插入)甚至可以定义一些触发器进行限定
    • 更多一致性操作,需要crud程序员进行限制

    如果数据库操作不符合原子性(转钱扣了转账者,但是收款的人钱数没有增加)或者不符合隔离性(两个操作并发,第二个操作读到第一个操作没有提交的数据,然后第二个操作后写回,发生了脏写)这也是不符合一致性要求——数据库中原子性和隔离性都是保证一致性的一种手段

    4.持久性#

    当现实世界中的一个状态转换完成后,这个转换结果需要永久保留,这称为持久性,现实世界中状态转换映射到数据中时,持久性意味着转换对应的数据需要持久化到磁盘中,无论发生什么事故,本次转换操作的影响都不应该丢失(损坏磁盘除外doge)

    三丶事务的状态#

    1. 活动的:事务对应的数据库操作正在执行过程中时
    2. 部分提交的:当事务中最后一个操作执行完成,但是由于操作都是在内存中执行,造成了影响没用刷新到磁盘时
    3. 失败的:事务处于活动状态或者部分提交时,约到某些错误而无法继续执行,或者任务终止事务的执行,事务就称为失败的
    4. 中止的:事务执行到一半,需要撤销对数据库造成的影响进行撤销,回滚,当回滚操作执行完毕,称为终止的
    5. 提交的:处于部分状态的事务对应操作刷新到磁盘,称为提交的

    四丶mysql中的事务语法#

    1.开启事务#

    • Begin

    • Start Transaction

      该命令可以跟随如下修饰符,多个修饰符使用逗号分隔,如Start Transaction read only,with consistent snapshot

      • read only

        标识当前事务是一个只读事务,属于该事务的数据库操作只能进行读操作(但是可以改当前会话中的临时表)(为什么只读还需要事务,因为需要获得一致性视图,不同的隔离级别会读到不同的数据,比如你想统计流水表中本月每一个顾客的消费信息,先统计了总流水Sum,然后依次统计每一个用户的流水,如果没用事务,第后续的对每一个顾客的统计之和可能读到最新的数据(用户新增了消费),而导致总流水和每一个用户流水之和不等的情况)

      • read write

        标记当前事务是读写事务

      • with consistent snapshot

        启动一致性读

    begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作
    InnoDB 表的语句,事务才真正启动。(一致性视图是在第执行第一个快照读语句时创建的)
    如果你想要马上启动一个事务,可以使用 start transaction with consistent snapshot 这个命令。(一致性视图是在执行 start transaction with consistent snapshot 时创建的)
    

    2.提交事务#

    • commit

    • commit work and chain

      提交当前事务并开启下一个事务,如果执行 commit work and chain,则是提交事务并自动启动下一个事务,这样省去了再次执行 begin 语句的开销

    3.手动中止事务#

    roll back ,程序员可以手段roll back进行回滚事务,如果事务在执行的过程中遇到一些错误,比如发生了死锁,会回滚整个事务

    4.自动提交#

    mysql 有一个系统变量autocommit 来控制是否自动提交事务,如果不显示的使用开启事务的命令,那么每一条语句就视为一个独立的事务。关闭自动提交的方式有:手动开启事务,设置自动提交为OFF,这时候需要手动提交或者进行回滚。

    6.隐式提交#

    mysql中如果输入了一些特定的语句,即便不是commit 命令也会提交事务。如

    • 执行ddl,定义数据库对象的命令,比如建立表,修改表,以及视图,存储过程等

    • 隐式的使用或者修改mysql数据库中的表

      使用alter user,create user,drop user等语句的时候会提交前面语句属于的事务

    • 事务控制or关于锁定的语句

      如果一个事务还没有提交,或者回滚的时候,又开启一个新事务,或者修改autocommit的值从OFF 到ON的时候也会提交事务。使用lock tables,unlock tables等关于锁定的语句也会提交事务

    • 加载数据的语句

      比如使用load data等语句也会提交事务

    • 关于mysql复制的语句

      比如start slave,stop slave也会提交事务

    • 其他语句

      比如optimize table

    7.保存点#

    savepoint 保存点名称,可以开启一个保存点,使用rollback to 保存点名称可以回滚到指定保存点,使用release savepoint 保存点可以释放保存点,保存点如同游戏的存档,避免我们从头开始,心态炸裂

    五丶小心长事务#

    长事务意味着系统里面会存在很老的事务视图。由于这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面它可能用到的回滚记录都必须保留,这就会导致大量占用存储空间(记录回滚信息的undo log,需要一致存储,占用空间)可以在information_schema 库的innodb_trx这个表中查询长事务的信息

  • 相关阅读:
    固定资产可视化智能管理系统
    《spring security in action》读书笔记
    web前端期末大作业 HTML+CSS+JavaScript仿安踏
    企业架构概述及业务架构详解
    vue3 传值
    STM32 JLINK感叹号问题解决
    java毕业生设计助农脱贫系统计算机源码+系统+mysql+调试部署+lw
    Redis 键过期与内存淘汰
    信息系统项目管理师0067:数据建模(5信息系统工程—5.2数据工程—5.2.1数据建模)
    Template serialization - shared_ptr<class T>
  • 原文地址:https://www.cnblogs.com/cuzzz/p/16846237.html