0
点赞
收藏
分享

微信扫一扫

MySQL是怎样运行的——第十八章

这一章主要讲事务的基本概念、特点以及基本使用的语法。

18.1

数据库诞生很大一部分程度是为了解决银行的金融系统问题,换句话说就是存钱的。事务一词在英文里是transaction,在金融语境下通常指交易。

在用计算机去对现实世界建模的过程中,会涉及到一些现实世界没有的问题。比如A给B转账,在现实世界纯纸质操作的年代,这应该不会出太大问题。

但在计算机世界不是这样的。比如,计算机程序在转账的过程中崩溃了怎么办?电脑断电了怎么办?等等。为了让计算机程序能更好的描绘、勾勒现实场景,科学家们为数据库的操作定义了一些应该被满足的特性

  1. 原子性:要么不做,要么全做。原子一词意味着最小、不可分割。这主要是讲数据库在执行操作的过程中如果出现了错误,要能回到操作之前的状态。
  2. 隔离性:因为很多操作是并发的,我们要保证一个事务不影响其他的事务,也要保证其他的事务不会影响到自身
  3. 持久性:事务对数据库的影响应该是永久的。
  4. 一致性:很多人对一致性有误解,以银行转账为例,很多人认为一致性就是A给B转账之后,A和B的金额加起来不变。这其实只是一方面。一致性其实包含两个语意。一是数据库中的数据要满足约束,这是由数据库进行支持的。比如你定义了主键,那主键列的数据是不能重复的,如果有人要插入重复数据,数据库必须阻止这种行为。二才是数据的一致性,这是建立在第一点之上的。要想满足这种一致性,不光靠数据库,还要靠程序员自己去把关。就像转账,如果你程序员自己写的程序错了,那数据库再好也没用。数据库也不应该为程序员自己的逻辑错误埋单。

18.2

这一节说事务的概念。事务就是满足ACID特性的一个或多个数据库操作的集合。
事务是操作集合,因此它是有状态的。MySQL设计者把事务的状态做如下分类:

  • 活动的:某个操作正在进行。
  • 部分提交的:操作都做完了,但是没有刷到磁盘里。
  • 失败的:当事务处于活动/部分提交状态时,遇到某些错误,会导致事务的状态变为失败的。比如电脑死机了。
  • 中止的:为了撤销失败的事务对数据库系统造成的影响,需要回滚。回滚操作执行完事务的状态是中止的。
  • 提交的:从部分提交的状态起步,顺利的刷盘了,状态变为提交的。

在这里插入图片描述

18.3

这一节主要是事务的语法。

开启事务

BEGIN;
START TRANSACTION;

这两种写法都可以,第二种后面可以指定修饰符。
修饰符有:

  • READ ONLY:只读,不能修改普通的表,但是可以修改临时表。因为临时表只在当前会话里可见。和READ WRITE冲突,只能选一种。
  • READ WRITE:和上一个冲突,也是不指定修饰符时的默认值。可以修改数据。
  • WITH CONSISTENT SNAPSHOT:启动一致性读,后面会说是什么。

提交事务

COMMIT;

手动终止事务

ROLLBACK;

主要给程序员手动回滚事务用。如果事务执行过程中遇到错误无法继续执行,大部分情况下数据库会回滚语句,少部分情况下会回滚事务(比如发生死锁),后面细说。

自动提交

MySQL有个系统变量autocommit,用于自动提交事务。默认打开,也就是每个操作都是独立的事务。

SHOW VARIABLES LIKE 'autocommit';

如果想关闭自动提交功能,一是可以

SET autocommit = OFF:

这样修改变量。二是可以手动打开事务,在手动打开事务的时候会暂时的把自动提交功能关闭。

隐式提交

在手动开启事务后,输入一些语句会导致当前事务被偷偷的提交了。好像你自己写了commit一样。这类情况有:

  • DDL语句:比如你CREATE 表啊,DROP啊, ALTER啊,等等。
  • 修改MySQL自带的表:比如你ALTER USER、CREATE USER、DROP USER、GRANT、RENAME USER、REVOKE、SET PASSWORD等。
  • 嵌套事务:你在一个事务里又一次begin,会导致旧事务提交。或者你在事务里打开autocommit,也会导致旧的事务自动提交。
  • 加载数据:使用LOAD DATA向数据库里批量导入数据会导致之前的事务偷偷提交。
  • 复制语句:使用START SLAVE、STOP SLAVE、RESET SLAVE、CHANGE MASTER TO等语句会导致之前的事务偷偷提交。
  • 其他语句:ANALYZE TABLE、CHECK INDEX、CHECK TABLE、FLUSH、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIT TABLE、RESET等语句。

检查点

一个事务可能有很多操作,你有可能希望只回滚一部分。这时候可以设置检查点。

SAVEPOINT 检查点名称;
ROLLBACK TO 检查点名称;

这样就可以实现回滚一部分了。如果想回滚所有,直接写ROLLBACK,别写后面的就行了。

举报

相关推荐

0 条评论