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. 在vim中搜索单词

    基本的搜索: /pattern    向前搜索 ?pattern   向后搜索 n               向前重复搜索 N               向后重复搜索 搜索并替换 :%s/sear ...

  2. C++ 中的 delete[] 机制剖析

    本文简单总结了delete[]放在析构函数中VS放在主函数中的区别(针对自己定义类). delete原理简单剖析(摘至https://zhidao.baidu.com/question/1540902 ...

  3. APC注入

    0X01 注入原理 当线程被唤醒时APC中的注册函数会被执行的机制,并依此去调用我们的DLL加载代码,进而完成注入的目的 具体的流程: 1 当EXE里的某个线程执行到sleepEX(),或者waitF ...

  4. POJ 2914 Minimum Cut Stoer Wagner 算法 无向图最小割

    POJ 2914 题意:给定一个无向图 小于500节点,和边的权值,求最小的代价将图拆为两个联通分量. Stoer Wagner算法: (1)用类似prim算法的方法求"最大生成树" ...

  5. Java回调机制解读

    模块间调用 在一个应用系统中,无论使用何种语言开发,必然存在模块之间的调用,调用的方式分为几种: (1)同步调用 同步调用是最基本并且最简单的一种调用方式,类A的方法a()调用类B的方法b(),一直等 ...

  6. Java Calendar.set 方法设置时间的问题

    因项目需要,需要遍历一年中的其中几个月,获得每个月的用户数量.  变量有:开始时间--startDate,结束时间--endDate. 逻辑很简单:获取到开始时间的月份和结束时间的月份,然后得到月份差 ...

  7. python服务器环境搭建(1)——本地服务器准备

    去年十月底到新公司上班,由于公司旧系统存在各种问题同时不便于扩展,而公司领导对17年寄予很大的期望,用户量.收入要上一个新台阶,我经过全面评估后,决定全部用python重构过,开发一个基于微服务架构的 ...

  8. 瞎谈CNN:通过优化求解输入图像

    本文同步自我的知乎专栏: From Beijing with Love 机器学习和优化问题 很多机器学习方法可以归结为优化问题,对于一个参数模型,比如神经网络,用来表示的话,训练模型其实就是下面的参数 ...

  9. Tp框架之模型层

    数据模型层是专门针对数据库来操作的 我们在home模块用一下数据模型层 先把配置修改好 我们先来打开这个文件 然后再打开think里面的主配置,把那里面关于数据库的部分,复制到home下的配置文件,然 ...

  10. wemall app商城源码中实现带图片和checkbox的listview

    wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享其中实现带图片和checkbox的listvi ...