事务
 
爸妈让往他们银行卡里转点儿钱,可是我这钱全在支付宝里,爸妈又没有支付宝,只能从支付宝里转给他
们了,假如转账过程中,支付宝扣款成功了,但是银行系统崩溃了,钱没转进去,这咋整?我的大洋就这样
打水漂了?肯定不可以,为了避免这种情况的发生,就用到了事务,在转钱过程中遇到了任何差错,就回到
没转钱之前的状态,这个就叫做事务
 
事务四大特性(ACID)
以下特性纯属个人理解
原子性(Atomicity):转账前 -> 转账  -> 转账成功,以上述转账为例,转账这个动作包括【从我的支付宝扣
除money,在我爸妈的卡上增加money】,中括号里的内容要么全部执行(转账成功),如果没有全部执行就
回到转账前的状态(跟没执行一个效果),不能停留在转账的中间过程——我的支付宝扣了钱,爸妈银行卡没
多钱
 
一致性(Consistency):我的理解是能量守恒,转账前后,我的支付宝金额+我爸妈卡内金额是一致的
 
隔离性(Isolation):这个一般用在并发,两个线程的操作会互相影响的情况下,隔离性又分为若干个隔离级
别,下面具体讨论
 
永久性(Durability):只要事务提交了,就成了事实。
 
隔离级别
在说隔离级别之前先来说几个概念
 
脏读:读到了另一个事务未提交的更改
 
例如 
 事务一:包工头给农民工转账
 事务二:农民工查看工资
 
 事务一:开始事务
 事务一:包工头给农民工转账1000
 事务二:开始事务
 事务二:农民工查看账户,多了1000块
 事务二:提交
 事务一:包工头回滚,转账失败
 
不可重复读:一个事务对同一记录的读取结果不一致,因为另一个事务更新了该记录,并提交
 
例如
 事务一:查看宾馆8301 的状态
 事务二:预订8301房间
 
 事务一:开始事务
 事务一:查看8301状态,未预定
 事务二:开始事务
 事务二:预定8301房间
 事务二:提交
 事务一:再次查看8301 状态,被预定
 
幻读:一个事务执行同一个查询结果不一样,因为另一事务插入了新的记录,并提交
 
例如
 事务一:统计网站的注册用户数
 事务二:注册新的用户
 
 事务一:开始事务
 事务一:查看注册用户数为10000
 事务二:开始事务
 事务二:新增一个用户(插入一条记录)
 事务二:提交
 事务一:查看注册用户数为10001
 
四种隔离级别
 
是否允许脏读
是否不可重复读
是否幻读
read uncommitted
read committed
repeatable read
serializable
事务的使用:
MariaDB [jason]> begin;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [jason]> insert into test values(2);
Query OK, 1 row affected (0.00 sec)
 
MariaDB [jason]> select * from test;
+------+
| i    |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)
 
MariaDB [jason]> rollback;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [jason]> select * from test;
+------+
| i    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
 
MariaDB [jason]> insert into test values(2);
Query OK, 1 row affected (0.00 sec)
 
MariaDB [jason]> commit;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [jason]> select * from test;
+------+
| i    |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)
 
mysql默认自动开启事务,可以通过begin 手动开启事务,如果想要回到begin之前的状态,则rollback,
操作完成后记得commit,否则推出窗口会就等同rollback 了
 
mysql 中的锁 
 
行级别锁只对事务安全的表(innodb,bdb)有效
 
for update 行级锁
首先我们先建一张表,插入两条数据
 
create table test(
f1 int,
f2 char(10),
index (f1)
)engine=innodb;
 
insert into test (f1) values
(1),
(2);
 
假设我们现在有个需求,f1 必须是唯一的,不可重复,每次插入只能插入当前最大值加 1,假设有两个窗
口各有一个事务,在读取最大值并插入
 
窗口1:
MariaDB [jason]> begin;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [jason]> select max(f1) from test;
+---------+
| max(f1) |
+---------+
|       2 |
+---------+
1 row in set (0.00 sec)
 
MariaDB [jason]> insert into test (f1) values(3);
Query OK, 1 row affected (0.00 sec)
 
窗口2:
MariaDB [jason]> begin;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [jason]> select max(f1) from test;
+---------+
| max(f1) |
+---------+
|       2 |
+---------+
1 row in set (0.00 sec)
 
MariaDB [jason]> insert into test (f1) values(3);
Query OK, 1 row affected (0.00 sec)
 
窗口1:
MariaDB [jason]> commit;
Query OK, 0 rows affected (0.01 sec)
 
窗口2:
MariaDB [jason]> commit;
Query OK, 0 rows affected (0.01 sec)
 
现在查看数据:
MariaDB [jason]> select * from test;
+------+------+
| f1   | f2   |
+------+------+
|    1 | NULL |
|    2 | NULL |
|    3 | NULL |
|    3 | NULL |
+------+------+
4 rows in set (0.00 sec)
 
结果我们插入了重复的数据,这与我们的要求相背离了,mysql 提供了锁,可以解决这个问题
我们先把错误数据删掉
 
MariaDB [jason]> delete from test where f1=3;
Query OK, 2 rows affected (0.00 sec)
 
我们可以用一个for update 锁来达到这个目的,只能有一个会话可以拥有这个锁,当另一个会话也申请这个锁
时,会暂时卡住,直到前一个会话commit  释放锁之后,
 
窗口1:
MariaDB [jason]> begin;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [jason]> select max(f1) from test for update;
+---------+
| max(f1) |
+---------+
|       2 |
+---------+
1 row in set (0.00 sec)
 
窗口2:
MariaDB [jason]> begin;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [jason]> select max(f1) from test;
+---------+
| max(f1) |
+---------+
|       2 |
+---------+
1 row in set (0.00 sec)
 
MariaDB [jason]> select max(f1) from test for update;
窗口2 暂时没有查询结果,要等到 窗口1 commit 之后才行
 
窗口1:
MariaDB [jason]> insert into test (f1) values (3);
Query OK, 1 row affected (0.00 sec)
 
MariaDB [jason]> commit;
Query OK, 0 rows affected (0.01 sec)
 
i窗口2:
+---------+
| max(f1) |
+---------+
|       3 |
+---------+
1 row in set (0.00 sec)
 
MariaDB [jason]> insert into test (f1) values (4);
Query OK, 1 row affected (0.00 sec)
 
MariaDB [jason]> commit;
Query OK, 0 rows affected (0.01 sec)
窗口2 的等待可能会超时,报错:Lock wait timeout exceeded;
 
我们再来看看
MariaDB [jason]> select * from test;
+------+------+
| f1   | f2   |
+------+------+
|    1 | NULL |
|    2 | NULL |
|    3 | NULL |
|    4 | NULL |
+------+------+
4 rows in set (0.00 sec)
 
共享读锁:lock in share mode 行级锁
如果一个事务正在修改f1 的值,而另一个窗口想读取有关f1 的最新值,可以用共享读锁
 
窗口1:
MariaDB [jason]> begin;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [jason]> select max(f1) from test;
+---------+
| max(f1) |
+---------+
|       4 |
+---------+
1 row in set (0.00 sec)
 
MariaDB [jason]> insert into test (f1) values(5);
Query OK, 1 row affected (0.00 sec)
 
窗口2;
 
MariaDB [jason]> select max(f1) ,f2 from test lock in share mode;
上面语句会阻塞直到 窗口1 commit;同样会超时跑异常
 
表级锁
 
读锁
只能对表进行读操作,不能进行写操作,写操作被锁
 
窗口1:申请test 表的读锁,在窗口1 中可以读,写test
窗口2:允许读test,但是写操作会阻塞,直到窗口1 unlock
 
 
写锁
上锁的那段时间没有读或写操作
上锁的窗口可以执行插入和insert 操作,其他窗口执行的命令会遇到阻塞
 
lock table 不是事务安全的,在锁表之前会提交全部的活动事务,
在更新比较频繁的表中应该尽量避免表级锁,以避免拥堵
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

《一起学mysql》2的更多相关文章

  1. 《从零开始做一个MEAN全栈项目》(1)

    欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 在本系列的开篇,我打算讲一下全栈项目开发的优势,以及MEAN项目各个模块的概览. 为什么选择全栈开发? ...

  2. 《从零开始做一个MEAN全栈项目》(2)

    欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习.   上一节简单介绍了什么是MEAN全栈项目,这一节将简要介绍三个内容:(1)一个通用的MEAN项目的技 ...

  3. 《从零开始做一个MEAN全栈项目》(3)

    欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 上一篇文章给大家讲了一下本项目的开发计划,这一章将会开始着手搭建一个MEAN项目.千里之行,始于足下, ...

  4. 《从零开始做一个MEAN全栈项目》(4)

    欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 在上一篇中,我们讲了如何去构建第一个Express项目,总结起来就是使用两个核心工具,express和 ...

  5. 一个关于vue+mysql+express的全栈项目(一)

    最近学了mysql数据库,寻思着能不能构思一个小的全栈项目,思来想去,于是就有了下面的项目: 先上几张效果图吧       目前暂时前端只有这几个页面,后端开发方面,有登录,注册,完善用户信息,获取用 ...

  6. Vue、Nuxt服务端渲染,NodeJS全栈项目,面试小白的博客系统~~

    Holle,大家好,我是李白!! 一时兴起的开源项目,到这儿就告一段落了. 这是一个入门全栈之路的小项目,从设计.前端.后端.服务端,一路狂飙的学习,发量正在欣喜若狂~~ 接触过WordPress,H ...

  7. Vue、Node全栈项目~面向小白的博客系统~

    个人博客系统 前言 ❝ 代码质量问题轻点喷(去年才学的前端),有啥建议欢迎联系我,联系方式见最下方,感谢! 页面有啥bug也可以反馈给我,感谢! 这是一套包含前后端代码的个人博客系统,欢迎各位提出建议 ...

  8. SpringBoot 整合 Elastic Stack 最新版本(7.14.1)分布式日志解决方案,开源微服务全栈项目【有来商城】的日志落地实践

    一. 前言 日志对于一个程序的重要程度不用过多的言语修饰,本篇将以实战的方式讲述开源微服务全栈项目 有来商城 是如何整合当下主流日志解决方案 ELK +Filebeat . 话不多说,先看实现的效果图 ...

  9. 全栈项目|小书架|服务器端-NodeJS+Koa2实现首页图书列表接口

    通过上篇文章 全栈项目|小书架|微信小程序-首页水平轮播实现 我们实现了前端(小程序)效果图的展示,这篇文章来介绍服务器端的实现. 首页书籍信息 先来回顾一下首页书籍都有哪些信息: 从下面的图片可以看 ...

  10. 全栈项目|小书架|服务器开发-NodeJS 使用 JWT 实现登录认证

    通过这篇 全栈项目|小书架|服务器开发-JWT 详解 文章我们对JWT有了深入的了解,那么接下来介绍JWT如何在项目中使用. 安装 $ npm install jsonwebtoken 生成 Toke ...

随机推荐

  1. 基于 Swoole 的轻量级框架 CabalPHP

    CabalPHP CabalPHP 是一个基于Swoole的轻量.高效.全异步开源框架. 亮点 全异步单机超高性能,轻松分布式部署 支持HTTP.TCP.websocket等多种协议 完善数据库引擎, ...

  2. 02-Git远程仓库Github

    1.Git远程仓库 (Gitgub网站作为远程代码仓库时的操作和本地代码仓库一样的,只是仓库位置不同而已) 需要准备的东西: 1.准备Git源代码仓库https://github.com/ 2.准备李 ...

  3. 【计算机网络】HTTPS协议的传输细节及过程分析

    1. 介绍一下HTTPS协议? 1.1 基本概念 http默认采用80作为通讯端口,对于传输采用不加密的方式,https默认采用443,对于传输的数据进行加密传输. 1.2 密码学基础 明文: 明文指 ...

  4. git报错:failed to push some refs to 'git@github.com:JiangXiaoLiang1988/CustomerHandl

    一.错误信息 今天在使用git将代码上传到GitHub的时候报下面的错误: 以前上传代码的时候重来没有出现这种错误,在网上查找了半天终于找到原因了:github中的README.md文件不在本地代码目 ...

  5. 使用dapper遇到的问题及解决方法

    在使用dapper进行数据查询时遇到的一个问题,今天进行问题重现做一个记录,免得忘记以后又犯同样的错误. 自己要实现的是:select * from tablename where id in(1,2 ...

  6. python基础(8):基本数据类型三(dict)、is和==、编码和解码

    1. 字典 1.1 字典的介绍 字典(dict)是python中唯一的一个映射数据类型,它是以{}括起来的键值对组成.在dict中key是唯一的,在保存的时候,根据key来计算出一个内存地址,然后将k ...

  7. Python入门你要懂哪些?

    前言 什么是计算机语言 计算机就是一台用来计算的机器,人让计算机干什么计算机就得干什么! 需要通过计算机的语言来控制计算机(也就是编程语言)! 计算机语言其实和人类的语言没有本质的区别,不同点就是交流 ...

  8. Python 爬取大众点评 50 页数据,最好吃的成都火锅竟是它!

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 胡萝卜酱 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

  9. 一个匹配字字符串是aabbcc或者其他模式的运用

    <!--一个匹配字字符串是aabbcc或aaaabccc或者其他模式的运用--> function isPattern(str, pattern) { let str_a = str.sp ...

  10. Socket简单实现ssh笔记

    Scoket概念: socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实现数据的互相传递. 我们知道网络 通信 都 是基于 ip+port 方能定位到目标的具体机器上 ...