7

mysql InnoDB事务 - Cuzzz

 1 year ago
source link: https://www.cnblogs.com/cuzzz/p/16846237.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
参考书籍《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这个表中查询长事务的信息


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK