MySQL - 事务

在学习事务这一概念前,我们需要需要构思一个场景

场景构思

假设该场景发生于一个银行转账背景下,月中,又到了发工资的日子。学校打算给A老师发放一个月的工资。(此处,我们假设转账都是由人工操作的),整个过程本应该如下:

  1. 学校财务核对A老师工资单

  2. 确认学校账上还有这么多钱

  3. 向银行提出转账申请,银行扣除学校财务卡上的指定金额

  4. 银行向A老师工资卡打入指定金额

  5. 银行汇报双方交易完成

    但是,当这个过程执行完第3步的时候,突然大断电!整个电力系统进入瘫痪。待电力系统回复之后,银行并不会继续执行4、5步甚至连1,2,3步的操作记录都丢失了。此时出现了如下的问题:

  • 学校认为,工资已经发出

  • A老师认为,学校还没有发工资

  • 银行认为,从来就没有发生过转账的事情

    其实整个过程可以用一个词来描述:数据库中的数据产生了“不一致性”

一致性

上述背景中设计到了一个概念,叫做不一致性,这是和一致性相对的概念。那么,什么是一致性呢?

一致性的意思是,在一系列数据库行为的前后两个时间点上,数据是正确对应的。放在上面的例子来看,就是操作前后,两个账户的总金额是一样的,这样就保证不会凭空的丢失掉不该丢失掉的金钱。

原子操作

为了保证数据的一致性,我们可以将一系列会破坏一致性的操作声明为原子操作。被声明为原子操作的那些操作要么一起完成,要么一起失败,这样我们就避免了类似断电这类情况导致的数据不一致性。

事务

那么如何才能实现MySQL中的原子操作呢?

MySQL以及大多数关系型数据库都提供了一个叫做事务的技术。我们可以声明一个事务的开始,在确认提交或者指明放弃前的所有操作,都先在一个叫做事务日志的临时环境中进行操作。待操作完成,确保了数据一致性之后,那么我们可以手动确认提交,也可以选择放弃以上操作。

注意: 一旦选择了提交,那么便不能再利用放弃操作来撤销更改了。

案例分析

​ 我们首先创建我们本次案例需要使用的表,并给一些测试数据

 
mysql> SHOW DATABASES;#查看有多少数据库
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| python             |
| sys                |
+--------------------+
5 rows in set (0.00 sec)
mysql> USE `python`;#切换数据库
Database changed
mysql> SELECT DATABASE();#查看当前使用的数据库
+------------+
| DATABASE() |
+------------+
| python     |
+------------+
1 row in set (0.00 sec)
mysql> CREATE TABLE `account` (
    ->   `id` int PRIMARY KEY AUTO_INCREMENT,
    ->   `name` VARCHAR(20) NOT NULL,
    ->   `balance` DECIMAL(12,2)
    -> );
Query OK, 0 rows affected (0.04 sec)
mysql> INSERT INTO `account`(`name`, `balance`)
    ->   VALUES ('TanzhouEDU', 10000000),('Tuple', 10000)
    -> ;
Query OK, 2 rows affected (0.70 sec)
Records: 2  Duplicates: 0  Warnings: 0

断电案例(非原子操作)

首先,查看现有的账户情况

 
mysql> SELECT * FROM `account`;
+----+------------+-------------+
| id | user       | balance     |
+----+------------+-------------+
|  1 | TanzhouEDU | 10000000.00 |
|  2 | Tuple      |    10000.00 |
+----+------------+-------------+
2 rows in set (0.00 sec)

现在,学校财务开始向A老师发工资

mysql> UPDATE `account`
    ->   SET `balance` = `balance` - 10000
    ->   WHERE `user` = 'TanzhouEDU'
    -> ;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> SELECT * FROM `account`;
+----+------------+------------+
| id | user       | balance    |
+----+------------+------------+
|  1 | TanzhouEDU | 9990000.00 |
|  2 | Tuple      |   10000.00 |
+----+------------+------------+
2 rows in set (0.00 sec)

此时,发生了断电,再登录数据库以后,钱已经消失了。

事务案例(原子操作)

MySQL中,事务操作包括4个:

  • START TRANSACTION:开始一个新的事务

  • COMMIT:提交当前事务,做出永久改变

  • ROLLBACK:回滚当前事务,放弃修改

  • SET autocommit = {0 | 1}:对当前会话禁用(0)或启用(1)自动提交模式

    我们利用事务机制来重复上述断电的情况。看看是否能够有所帮助。

mysql> SELECT * FROM `account`;
+----+------------+------------+
| id | user       | balance    |
+----+------------+------------+
|  1 | TanzhouEDU | 9990000.00 |
|  2 | Tuple      |   10000.00 |
+----+------------+------------+
2 rows in set (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> UPDATE `account`
    ->   SET `balance` = `balance`-1000
    ->   WHERE `user` = 'TanzhouEDU'
    -> ;
Query OK, 1 row affected (0.01 sec)
mysql> SELECT * FROM `account`;
+----+------------+------------+
| id | user       | balance    |
+----+------------+------------+
|  1 | TanzhouEDU | 9989000.00 |
|  2 | Tuple      |   10000.00 |
+----+------------+------------+
2 rows in set (0.00 sec)
mysql> exit
Bye
tuple@MyVM:~$ mysql -utuple -p123456
mysql> USE `python`;
Database changed
mysql> SELECT * FROM `account`;
+----+------------+------------+
| id | user       | balance    |
+----+------------+------------+
|  1 | TanzhouEDU | 9990000.00 |
|  2 | Tuple      |   10000.00 |
+----+------------+------------+
2 rows in set (0.00 sec)

我们可以看到,数据在断电后,自动恢复到了数据修改前的样子,它相当于如下一个操作过程。

 
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> UPDATE `account`
    ->   SET `balance`=`balance`-1000
    ->   WHERE `user`='TanzhouEDU'
    -> ;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> SELECT * FROM `account`;
+----+------------+------------+
| id | user       | balance    |
+----+------------+------------+
|  1 | TanzhouEDU | 9989000.00 |
|  2 | Tuple      |   10000.00 |
+----+------------+------------+
2 rows in set (0.00 sec)
mysql> ROLLBACK;
Query OK, 0 rows affected (0.02 sec)
mysql> SELECT * FROM `account`;
+----+------------+------------+
| id | user       | balance    |
+----+------------+------------+
|  1 | TanzhouEDU | 9990000.00 |
|  2 | Tuple      |   10000.00 |
+----+------------+------------+
2 rows in set (0.00 sec)

接着,我们来做一次正确的操作,真正的给A老师发一次工资。

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> UPDATE `account`
    ->   SET `balance` = `balance`-10000
    ->   WHERE `user` = 'TanzhouEDU'
    -> ;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> UPDATE `account`
    ->   SET `balance` = `balance`+10000
    ->   WHERE `user`= 'Tuple'
    -> ;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> SELECT * FROM `account`;
+----+------------+------------+
| id | user       | balance    |
+----+------------+------------+
|  1 | TanzhouEDU | 9980000.00 |
|  2 | Tuple      |   20000.00 |
+----+------------+------------+
2 rows in set (0.00 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)
mysql> ROLLBACK;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM `account`;
+----+------------+------------+
| id | user       | balance    |
+----+------------+------------+
|  1 | TanzhouEDU | 9980000.00 |
|  2 | Tuple      |   20000.00 |
+----+------------+------------+
2 rows in set (0.00 sec)

通过上面的例子可以看出,一旦commit了,那么rollback还是断电都不能反悔了。

MySQL---事务知识,你搞明白没有?的更多相关文章

  1. 【转】MYSQL DBA知识了解-面试准备

    http://www.itpub.net/forum.php?mod=viewthread&tid=1825849 公司招聘MySQL DBA,也面试了10个2年MySQL DBA工作经验的朋 ...

  2. MYSQL事务之Yii2.0商户提现

    我是一个半路出家的PHP程序员,到目前为止,不算在培训班学习的时间,已经写代码整整两年了.可能由于工作业务的原因,在这两年中我没有用到过MySQL事务.就在昨天有个关于支付宝转账的业务不得不使用MyS ...

  3. mysql事务隔离级别、脏读、幻读

    Mysql事务隔离级别本身很重要,再加上可能是因为各大公司面试必问的缘故,在博客中出现的概率非常高,但不幸的是,中国的技术博客要么是转载,要么是照抄,质量参差不齐,好多结论都是错的,对于心怀好奇之心想 ...

  4. Mysql 事务及其原理

    Mysql 事务及其原理 什么是事务 什么是事务?事务是作为单个逻辑工作单元执行的一系列操作,通俗易懂的说就是一组原子性的 SQL 查询.Mysql 中事务的支持在存储引擎层,MyISAM 存储引擎不 ...

  5. MySQL 基础知识梳理

    MySQL 的安装方式有多种,但是对于不同场景,会有最适合该场景的 MySQL 安装方式,下面就介绍一下 MySQL 常见的安装方法,包括 rpm 安装,yum 安装,通用二进制安装以及源码编译安装, ...

  6. 一文彻底读懂MySQL事务的四大隔离级别

    前言 之前分析一个死锁问题,发现自己对数据库隔离级别理解还不够清楚,所以趁着这几天假期,整理一下MySQL事务的四大隔离级别相关知识,希望对大家有帮助~ 事务 什么是事务? 事务,由一个有限的数据库操 ...

  7. MySQL 事务常见面试题总结 | JavaGuide 审核中

    <Java 面试指北>来啦!这是一份教你如何更高效地准备面试的小册,涵盖常见八股文(系统设计.常见框架.分布式.高并发 ......).优质面经等内容. 本文原发于 MySQL知识点&am ...

  8. mysql事务和并发控制

    谈到事务,首先想到的问题是并发控制.比如两个用户同时操作数据库里面的一张表,一个正在读数据,一个正在删除数据,那么读数据的读出的结果究竟是多少?并发可以提高系统的性能,让多个用户同时操作一份数据,但为 ...

  9. Mysql数据库知识-Mysql索引总结 mysql mysql数据库 mysql函数

    mysql数据库知识-Mysql索引总结: 索引(Index)是帮助MySQL高效获取数据的数据结构. 下边是自己整理的资料与自己的学习总结,,做一个汇总. 一.真的有必要使用索引吗? 不是每一个性能 ...

随机推荐

  1. Python2和Python3中除法操作/的不同

    X/Y 在3.0版本之前的Python中 >>>1/2 0 即一个整数(无小数部分的数)被另外一个整数除,计算结果的小数部分被截除了,只留下了整数部分 有时候,这个功能比较有用,譬如 ...

  2. svg学习之旅(2)

    基本图形 circle 圆     cx基于X轴的坐标位置 cy基于y轴的坐标位置 r圆的半径 fill 填充 transparent透明 stroke 边框 stroke-width 边框宽度 st ...

  3. 特性Attribute 的使用

    [IdentityAuthorize]           public ActionResult Index()        {             return View("~/V ...

  4. ubuntu下包管理器apt-get常用命令

    apt-cache search package 搜索包 apt-cache show package 获取包的相关信息,如说明.大小.版本等 sudo apt-get install package ...

  5. Odd Numbers of Divisors

    给出一个正奇数K,两个正整数low,high. 有多少整数属于[low, high],且包含K个因子. 数据 C(0 < C < 1e5),测试样例数. (1 < K < 10 ...

  6. 解析令人费解的java泛型

    对于我们java中的泛型,可能很多人知道怎么使用并且使用的还不错,但是我认为想要恰到好处的使用泛型,还是需要深入的了解一下它的各种概念和内部原理.本文将尽可能的囊括java泛型中的重要的概念.主要内容 ...

  7. Professional C# 6 and .NET Core 1.0 - Chapter 41 ASP.NET MVC

    What's In This Chapter? Features of ASP.NET MVC 6 Routing Creating Controllers Creating Views Valida ...

  8. MAC软件下载链接地址

    博客开启,今天向大家推荐一款MAC软件大全地址. 下载地址:http://www.pc6.com/mac/111949.html

  9. python的解释器spython介绍

    Python解释器spython介绍 简介 出于个人爱好和某种需求,我再16年对python的解释器产生了浓厚兴趣,并且下定决心重新实现一个版本.我个人再游戏服务器开发中,对c++嵌入lua和pyth ...

  10. web前端页面性能

    前段性能的意义 对于访问一个网站,最花费时间的并不是后端应用程序处理以及数据库等消耗的时间,而是前端花费的时间(包括请求.网络传输.页面加载.渲染等).根据web优化的黄金法则:80%的最终用户响应时 ...