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. 用keychain这个特点来保存设备唯一标识。

    由于IOS系统存储的数据都是在sandBox里面,一旦删除App,sandBox也不复存在.好在有一个例外,那就是keychain(钥匙串). 通常情况下,IOS系统用NSUserDefaults存储 ...

  2. java作业—3

    动手动脑: 一.编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数. 方法1(数据类型)(最小值+Math.random()*(最大值-最小值+1)) 例:(int)(1+Math.r ...

  3. python - bilibili(一)获取直播间标题

    近几年,直播平台蛮火的.小时候,经过各种日漫的洗礼,在直播平台自然而然的就盯上了B站. 目前还是python菜鸟一枚,各位大佬请轻拍. 最终效果图: 闲话不说,我们来一步步解析B站的弹幕. 工具:py ...

  4. window7 32位安装Oracle11g

    http://www.cnblogs.com/wangsaiming/p/3573509.html

  5. IOS缓存管理之YYCache使用

    前言: 最近一直在致力于为公司app添加缓存功能,为了寻找一个最佳方案,这几天先做个技术预研,经过这两天的查找资料基本上确定了两个开源框架进行选择,这两个开源框架分别是:PINCache.YYCach ...

  6. 关于Monkey的一切都在这里

    关于Monkey的一切都在这里 版权声明: 本账号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影所有. 允许有条件转载,转载请附带底部二维码. 一.什么是Monkey Monkey是 ...

  7. 【转】搜索引擎选择: Elasticsearch与Solr

    原文地址:http://i.zhcy.tk/blog/elasticsearchyu-solr/ Elasticsearch简介 Elasticsearch是一个实时的分布式搜索和分析引擎.它可以帮助 ...

  8. 微软MSBI商业智能视频

    第一讲:BI介质安装.BI基础知识讲解.BI方法论讲解.项目讲解                 1.BI基础知识讲解.BI方法论实施2.微软BI的介绍(数据仓库介绍.SSIS介绍.SSAS介绍.SS ...

  9. 康复计划#5 Matrix-Tree定理(生成树计数)的另类证明和简单拓展

    本篇口胡写给我自己这样的什么都乱证一通的口胡选手 以及那些刚学Matrix-Tree,大致理解了常见的证明但还想看看有什么简单拓展的人- 大概讲一下我自己对Matrix-Tree定理的一些理解.常见版 ...

  10. 关于margin

    ----W3School -----margin CSS 边距属性定义元素周围的空间.通过使用单独的属性,可以对上.右.下.左的外边距进行设置.也可以使用简写的外边距属性同时改变所有的外边距. 这个简 ...