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. C# XmlSerializer将对象序列化以及反序列化(Sqlite数据库)

    获取不同数据库表信息将筛选出来的信息序列化以及反序列化 相应类结构: Class Tables: [Serializable] [XmlRoot("Table")] public ...

  2. 1305 Pairwise Sum and Divide

    1305 Pairwise Sum and Divide 题目来源: HackerRank 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 有这样一段程序,fun会对 ...

  3. django-查询语句(一)

    1.model 假设我们的model如下: 某个JobType下有很多Job. class JobType(models.Model): name = models.CharField(max_len ...

  4. axios全攻略

    随着 vuejs 作者尤雨溪发布消息,不再继续维护vue-resource,并推荐大家使用 axios 开始,axios 被越来越多的人所了解.本来想在网上找找详细攻略,突然发现,axios 的官方文 ...

  5. Redis简单配置和使用

    学到Redis中需要整理和配置的东西比较多,资源也是比较分散!这次的主要还是将知识整合一下,开发过程中所需要的资源整合一下,也方便今后涉及到这块地方的知识时,将时间大量浪费在了找这些资源上了! 一.R ...

  6. 专题:DUILIB Win32 透明效果

    Win32 透明效果相关基础知识 Layered Windows 分层窗口.这是Windows2000开始引入的概念,重新定义了窗口的Hit Testing方法,以前都是把窗口按rectangle的方 ...

  7. 模态Model视图Push下一个视图(混合跳转)

    来自: http://www.cnblogs.com/dingding3w/p/6222626.html 如果没有UINavigationController导航栏页面之间切换是不能实现Push操作的 ...

  8. AVFoundation自定义拍照

    0.AVCapture  <AVFoundation/AVFoundation.h> 媒体采集需要的几个对象: 1.AVCaptureDevice: 代表抽象的硬件设备(如前置摄像头,后置 ...

  9. 通讯录--(iOS9独有的方法)

    导入库文件   #import <ContactsUI/ContactsUI.h> #pragma mark iOS9 新出的点击通讯录的获取信息的办法 #pragma mark - 先弹 ...

  10. SEO-百度推出新算法如何应对

    > 如何知道百度推出新算法百度推出算法的趋势> 学SEO目的做排名,长流量,赚钱> 最近一年百度搜索变动1> 2012年6月:6/22, 6/28事件,百度地震,4.5%网站被 ...