MySQL事务和锁实战篇
MySQL事务和锁
事务
说到关系型的数据库的事务,相信大家对四大特性都不陌生,分别是原子性、一致性、隔离性、持久性,简称为ACID特性。
MySQL中支持3种不同的存储引擎:
MyISAM存储引擎、Memory存储引擎、和InnoDB存储引擎
注:只有InnoDB才支持事务。
事务的控制语句
控制语句 | 作用 |
---|---|
begin或者start transaction | 开启一个事务 |
commit 或者 commit work | 提交事务,进行持久性修改 |
rollback 或者 rollback work | 回滚事务,撤销已经进行修改但未提交的操作 |
savepoint [保存点] | 在事务中创建一个保存点,一个事务可以有多个保存点 |
releasavepoint [保存点] | 回滚到指定的保存点 |
set transaction | 设置事务的隔离级别 |
事务隔离级别设置
先复习一个事务的四大隔离级别
读未提交(READ-UNCOMMITTED)
读已提交(READ-COMMITTED)
可重复读(RE-PEATABLE-READ)
可序列化读(SERIALIZABLE)
下面是操作过程。
首先,查看默认的事务隔离级别,可以看到是可重复读(REPEATABLE-READ),
show variables like '%isolation%';
脏读
我们来演示一下脏读的场景,下面这张图是展示了我原先已经创建好的两个用户的账号都为100元。
分别打开两个连接mysql的会话窗口,其中一个会话的隔离级别为READ-UNCOMMITED,然后再另一个窗口中开启一个事务,例如,lisi给zhangsan转账100元,
set session transaction isolation level read uncommitted;
begin;
update user set money=money-100 where user=lisi;
我们在另外一个读未提交的窗口中查看,zhangsan看到钱已经转过来了,但是实际上lisi的事务还没有提交,假如这个时候,lisi不想转账了,回滚事务,那zhangsan就读到脏数据了。
不可重复读
下面来展示一下不可重复读的场景。
首先我们将zhangsan的窗口的事务隔离级别设置成READ-COMMITTED,并且在两个窗口都开启事务
set session transaction isolation level read committed;
假设zhangsan现在想统计全部人的钱有多少,很明显200;
但是这个时候lisi往账户里面存了100元,并提交事务,但是这个时候,zhangsan再次查询总和,我们会查询到总金额为300,但是这次查询是处于同一个事务中,查询到两次不一样的结果,属于不可重复读的情况。
update user set money=money+100 where user='lisi';
commit;
幻读
为了解决不可重复读的问题,我们将事务的隔离等级设置成RE-PEATABLE-READ,即MySQL默认的事务隔离等级,然后在两边都开启一个事务。
set session transaction isolation level repeatable read;
我们先在一个窗口插入一条数据并提交,然后在另外一个窗口查看,此时是查询不到这个记录的,但是假如这个时候我们新插入一条主键和刚插入的记录一样的话,我们就可以发现
insert into user values('zly1',100);
# 另外一个窗口
insert into user values('zly1',100);
ERROR 1062 (23000): Duplicate entry 'zly1' for key 'user.PRIMARY'
这样也算是一种幻读的现象,但是网上也有一种说法在可重复读的等级下,幻读是可避免的,这种说法不是非常准确的,如果在进行更新和插入时就可能会出现幻读的情况,如果想要解决幻读的情况,可以将事务隔离等级设置到SERIALIZABLE
锁机制
InnoDB的行级锁
InnoDB默认采用的行级锁,分为以下这两种,分别为共享锁和排他锁。
这两个概念我在这篇文章中也有介绍。
共享锁(S锁):也叫读锁,如果在该数据对象上加了共享锁,该事务可以读取但是不能修改数据。其他事务也可以在该对象上加共享锁,但是不能修改数据。
排他锁(X锁):也叫写锁,在一个数据对象只有一把排他锁,获取到该锁的事务可以读取数据和修改数据。
(加锁:一般的查询语句不会加任何的锁类型,当然也可以为数据加锁,比如在select * from … for update,这样可以为数据添加排他锁,而使用select … lock in share mode 可以为数据添加共享锁。
锁实战
首先关闭事务自动提交
set autocommit=0;
我们先在一个窗口输入一条获取到排他锁,虽然操作的是一条数据,但是锁的是整张表,因为我们没有添加索引。
select * from user where user='zly1' for update;
这个时候我们对user这一列添加索引,就可以看到我们对其进行加锁就不会出现阻塞的情况了。
alter table user add index(user);
注:在MySQL的行级锁是针对索引加的锁,而不是针对表中的行加级锁,虽然访问不同行的记录,但是如果不存在对应的索引,或者使用相同的索引的话,就会造成锁的冲突而锁住整张表。
死锁
死锁是指两个或者两个以上的额事务在执行过程中,因为互相的等待或者因为争抢相同的资源而造成的互相等待现象。
我们还是采用刚刚的例子,还是将事务的自动提交关闭掉,首先先在会话1中,更新id为1的记录,然后在会话2中更新id为2的记录,这个时候我们再回来在会话1更新id为2的记录,在会话2中更新id为1的记录,就会产生一个死锁;
总结
本文主要介绍了事务的隔离等级和事务的锁机制,主要更加偏向于实战部分,我前面也有一些文章涉及到。
MySQL事务和锁实战篇的更多相关文章
- MySQL 5.7主从复制实战篇
MySQL 5.7主从复制实战篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装MySQL数据库并启动 1>.在MySQL官方下载相应的安装包(https://dev ...
- MySQL事务与锁
MySQL事务与锁 锁的基本概念 锁是计算机协调多个进程或线程并发访问某一资源的机制. 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISA ...
- 关于mysql事务行锁for update实现写锁的功能
关于mysql事务行锁for update实现写锁的功能 读后感:用切面编程的理论来讲,数据库的锁对于业务来说是透明的.spring的事务管理代码,业务逻辑代码,表锁,应该是三个不同的设计层面. 在电 ...
- mysql事务和锁InnoDB
背景 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备 ...
- mysql事务和锁InnoDB(转)
背景 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备 ...
- javaweb(三十八)——mysql事务和锁InnoDB(扩展)
MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备就My ...
- 面试官一口气问了MySQL事务、锁和MVCC,我
面试官:你是怎么理解InnoDB引擎中的事务的? 候选者:在我的理解下,事务可以使「一组操作」要么全部成功,要么全部失败 候选者:事务其目的是为了「保证数据最终的一致性」. 候选者:举个例子,我给你发 ...
- MYSQL事务和锁
mysql事务(一)—转载 2012年12月20日 ⁄ Mysql数据库, 技术交流 ⁄ 暂无评论 一. 什么是事务 事务就是一段sql 语句的批处理,但是这个批处理是一个atom(原子) ,不可分割 ...
- MySQL 事务与锁机制
下表展示了本人安装的MariaDB(10.1.19,MySQL的分支)所支持的所有存储引擎概况,其中支持事务的有InnoDB.SEQUENCE,另外InnoDB还支持XA事务,MyISAM不支持事务. ...
- MySql 事务与锁
事务介绍 首先,什么是事务?事务就是一段sql 语句的批处理,但是这个批处理是一个atom(原子),不可分割,要么都执行,要么回滚(rollback)都不执行. MySQL 事务主要用于处理操作量大, ...
随机推荐
- 简介及spring mvc初体验
一.C\S和B\S C/S C/S 是 Client/Server 的简写,简称客户端/服务器模式.例如 QQ 是客户端和服务器模式,首先安装一个客户端到个人电脑,然后登入到腾讯服务器. 缺点:更新不 ...
- easycode模版-基于ruoyi-cloud
##定义初始变量 #set($tableName = $tool.append($tableInfo.name, "Controller")) ##设置回调 $!callback. ...
- FTP文件夹错误:【打开FTP服务器上的文件夹时发生错误。请检查是否有权限访问该文件夹】
资源管理器访问FTP服务器报错,提示FTP文件夹错误:[打开FTP服务器上的文件夹时发生错误.请检查是否有权限访问该文件夹]. 详细信息: 200 Switching to ASCII mode. 2 ...
- vue项目 - 自定义数字输入指令 | 限制自定义小数位输入
1.在main.js中直接加入代码: import Vue from 'vue' Vue.directive("input-limit", { bind(el, binding) ...
- flask orm 操作方法
数据库操作 常用的查询过滤器 过滤器 说明 filter() 把过滤器添加到原查询上,返回一个新查询 filter_by() 把等值过滤器添加到原查询上,返回一个新查询 limit() 使用指定的值限 ...
- 基于Kubernetes(k8s)部署Dubbo+Nacos服务
一.说明 本文介绍基于 Kubernetes(k8s) 环境集成阿里云 私有镜像仓库 来部署一套 Dubbo + Nacos 的微服务系统,并使用 Kubernetes DNS 以及 port-for ...
- 能快速构建和定制网络拓扑图的WPF开源项目-NodeNetwork
大家好,我是沙漠尽头的狼,今天介绍一个WPF开源项目-NodeNetwork,它可以帮助我们快速构建和定制网络拓扑图. 一.前言 在现代软件开发中,数据可视化和可交互性越来越受到关注.为了实现这一点, ...
- 正则表达式(cases)
匹配不含'aaa'和'bbb'的字符串: ^(?!.*aaa)(?!.*bbb).*$ To be continue...
- CSharp linq 的本质
linq 的本质是扩展方法和委托的结合 链式 linq 和 方法级linq List<int> list = new List<int>() { 3,9,32,7 }; // ...
- SpringBoot的EnableCaching简述
Spring Boot中的EnableCaching简述 spring boot中自带有数据缓存机制,主要通过其org.springframework.cache包下的各种类来实现. EnableCa ...