MySQL事务理论及实现
理论大多引自《高性能MySQL》一书,不过在自测的过程中不知道是不是SQL版本的问题,还是操作有问题,在设置事务隔离级别的时候 按书上讲SET TRANSACTION ISOLATION LEVEL 这样设置并没有实现
代码实现事务回滚,基于spring boot
1、将MySQL的自动提交关掉(不是必须的)。
SET SESSION autocommit=0; 只对当前会话生效
SET autocommit = 0; 只对本次连接生效,当断开本次与MySQL的连接,则又回到默认的自动提交模式
SET GLOBAL autocommit = 0 更改系统变量,但是如果MySQL重启则又回到默认的自动提交模式
修改配置文件永久生效
修改etc/my.cnf 文件
在[mysqld]下添加如下,记得重启。
autocommit=0
2、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
3、在启动类上添加注解
@EnableTransactionManagement
4、在service层添加注解(加在类名上对该类下所有方法生效,加在方法上只对该方法生效),对抛出的任何异常都进行自动回滚
@Transactional(rollbackFor = Exception.class)
public boolean insertBook() {
int i = 0;
i += bookMapper.insertBook();
i += bookMapper.insertUser();
if (i == 2) {
return true;
} else {
return false;
}
}
对于回滚失败的问题,整理以下问题
(1)MySQL默认存储引擎是InnoDB是支持事务的,你可能采用了不支持事务的引擎。
(2)如果异常被try{} catch{}了,你自己把异常处理了spring就不回滚了,如果想让事务回滚,必须手动再抛出异常,或者手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
(3)如果try-catch语句在finally中进行了return操作,那么catch中手动抛出的异常也会被覆盖,同样不会自动回滚
@Transactional(rollbackFor = Exception.class)
public boolean insertBook() {
int i = 0;
i += bookMapper.insertBook();
try {
i += bookMapper.insertUser();
} catch (Exception e) {
throw new Exception();
} finally {
return true;
}
//TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
/* if (i == 2) {
return true;
} else {
return false;
}*/
}
(4)两个方法A和B,A方法调用了B方法,A没有设置事务,B设置了,此时对于A来讲也不会发生回滚
(5)标记@Transactional的方法必须是public 其他类型都不会开启事务
(6)如果用到了shiro框架,需要对ShrioRealm中注入的service 加注解 @Lazy或者直接调用mapper,否则对该service层事务也是不起作用的
事务简介
事务就是一组原子性的SQL查询,简单说就是开启事务后,你所执行的一组SQL语句,如果其中有任何一条语句
因为崩溃或其他原因执行失败,那么所有语句都不会执行。要么全部执行成功,要么全部失败。
开启事务
START TRANSACTION;或者BEGIN;
开启事务后要么使用 COMMIT 提交事务将修改的数据持久保留,要么使用ROLLBACK回滚所有的修改
格式如下:
START TRANSACTION;
-- BEGIN;
SELECT * FROM booktype;
UPDATE booktype SET bookTypeName = '计算机类' WHERE id = 1
-- ROLLBACK;
COMMIT;
单纯的事务概念并不是故事的全部,如果在事务执行过程中因为服务器崩溃怎么办?所以一个运行良好的事务处理系统必须满足ACID标准。
原子性(atomicity):
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分。这就是事务的原子性。
一致性(consistency):
数据库总是从一个一致性状态转换到另一个一致性的状态。只要事务最终没有提交,事务中所作的修改也不会保存到数据库中。
隔离性(isolation):
简单来说就是一个事务所作的修改在最终提交前,对其他事务是不可见的。
持久性(durability):
一旦事务提交,则其所作的修改就会永久保存到数据库中,此时即使系统崩溃,修改的数据也不会丢失。持久性是个有点模糊的概念,因为实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些则未必。而且不可能有做到100%持久性保证的策略(如果数据库本身就能做到真正的持久性,那么备份又怎么能增加持久性呢?)
1、事务四种隔离级别
READ UNCOMMITTED(读未提交)
事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)。实际应用中很少使用。
READ COMMITTED(读已提交)
一个事务开始时,只能看到已经提交的事务所作的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别也叫做不可重复读,因为两次执行同样的查询,可能会得到不一样的结果。
REPEATABLE READ(可重复读)
MySQL默认的事务隔离级别。解决了脏读的问题。该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但是理论上,可重复读还是无法解决另外一个幻读的问题。所谓幻读,指的是当某个事务再次读取某个范围的数据时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。MySQL默认的存储引擎是InnoDB,通过多版本并发控制解决了幻读的问题。
SERIALIZABLE(可串行化)
事务隔离级别的最高级别,它通过强制事务串行执行,避免了前面说的幻读的问题。简单说就是SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁的争用问题。实际开发中也很少用这个隔离级别。
MySQL查询当前系统的隔离级别:
SHOW GLOBAL VARIABLES LIKE ‘%ISOLATION%’;
查询当前会话的隔离级别:SELECT @@tx_isolation;
MySQL可以通过SET GLOBAL TRANSACTION ISOLATION LEVEL 命令来设置系统隔离级别。新的隔离级别会在下一个事务中开始时生效。可以在配置文件中设置整个数据库的隔离级别,也可以指该表当前会话的隔离级别:SET SESSION TRANSACTION ISOLATION LEVEL
配置文件修改隔离级别
在mysql配置文件my.cnf中[mysqld]段下加上transaction-isolation=Read-Committed
然后重启
2、死锁
死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶行循环的现象。当多个事务试图以不同的顺序锁定资源时,就可能会产生死锁。多个事务同时锁定同一个资源时,也会产生死锁。
MySQL默认的存储引擎InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚(这是相对比较简单的死锁回滚算法)。
死锁发生以后,只有部分或者完全回滚其中一个事务,才能打破死锁。大多数情况下只需要重新执行因死锁回滚的事务即可。
3、MySQL中的事务
MySQL默认采用自动提交的模式(AUTOCOMMIT)。也就是说如果不是显示的开始一个事务,则每个查询都被当作一个 事务执行提交操作。在当前连接中,可以通过设置AUTOCOMMIT变量来启用或者禁用自动提交模式。
SHOW VARIABLES LIKE AUTOCOMMIT
SET AUTOCOMMIT= 1;
1或ON表示启用,0或OFF表示禁用。
当 AUTOCOMMIT= 0时,所有的查询都是在一个事务中,知道显式的执行COMMIT提交或者ROLLBACK回滚,该事务结束,同时又开始了另一个新事务。修改AUTOCOMMIT对非事务型的表,如MyISAM或者内存表,不会有任何影响。对这类表来说,没有COMMIT或者ROLLBACK的概念,也可以说是相当于一直处于AUTOCOMMIT启用的模式。
另外还有一些命令,在执行之前会强制执行COMMIT提交当前的活动事务。典型的在数据定义语言(DDL)中,如果是会导致大量数据改变的操作,比如ALTER TABLE就是如此。
在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻被释放。前面描述的都是隐式锁定,InnoDB会根据隔离级别在需要的时候自动枷锁。如果应用需要用到事务,还是应该选择事务型存储引擎。
MySQL事务理论及实现的更多相关文章
- MYSQL事务及存储引擎对比
Innodb支持事务,而myisam不支持事务. 事务的定义: 当多个用户访问同一份数据时,一个用户在更改数据的过程中可能有其他用户同时发起更改请求,为保证数据的更新从一个一致性状态变更为另一个一致性 ...
- MySQL事务原理&实战【官方精译】
事务隔离级别 事务隔离是数据库处理的基础之一.隔离是I中的首字母 ACID ; 隔离级别是在多个事务同时进行更改和执行查询时,对结果的性能和可靠性,一致性和可重复性之间的平衡进行微调的设置. Inno ...
- Mysql事务及锁
一.事务(Transaction)及其ACID属性 事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性:1.原子性(Atomicity):事务是一个原子操作单 ...
- MySQL事务实现原理
MySQL事务隔离级别的实现原理 知识储备 只有InnoDB支持事务,所以这里说的事务隔离级别是指InnoDB下的事务隔离级别 隔离级别 读未提交:一个事务可以读取到另一个事务未提交的修改.这会带来脏 ...
- 关于mysql事务行锁for update实现写锁的功能
关于mysql事务行锁for update实现写锁的功能 读后感:用切面编程的理论来讲,数据库的锁对于业务来说是透明的.spring的事务管理代码,业务逻辑代码,表锁,应该是三个不同的设计层面. 在电 ...
- 超干货!为了让你彻底弄懂MySQL事务日志,我通宵肝出了这份图解!
还记得刚上研究生的时候,导师常挂在嘴边的一句话,"科研的基础不过就是数据而已."如今看来,无论是人文社科,还是自然科学,或许都可在一定程度上看作是数据的科学. 倘若剥开研究领域的外 ...
- 熬夜肝出5大点,18张图带你彻底弄懂MySQL事务日志
在当今社会,充斥着大量的数据.从众多APP上的账户资料到银行信用体系等个人档案,都离不开对大量数据的组织.存储和管理.而这,便是数据库存在的目的和价值.目前数据库的类型主要分为两种,一种是关系型数据库 ...
- Mysql 事务隔离级别和锁的关系
我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于 ...
- Mysql事务探索及其在Django中的实践(二)
继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...
- MySQL 事务
MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成 ...
随机推荐
- Python 实时获取任务请求对应的Nginx日志
需求描述 项目需求测试过程中,需要向Nginx服务器发送一些用例请求,然后查看对应的Nginx日志,判断是否存在特征内容,来判断任务是否执行成功.为了提升效率,需要将这一过程实现自动化. 实践环境 P ...
- Scratch全套Q版三国人物角色素材包免费下载
全新Q版三国人物角色素材包,内含142张细腻可爱的Q版风格图片,涵盖三国名将.士兵.场景等丰富元素,为scratch爱好者提供多样选择,适合各类三国主题创作. 免费下载:www.xiaohujing. ...
- 【Eclipse】入门使用
Eclipse界面简单概述 第一次启动时,工作空间的选择 工作界面的介绍: 选项条 工具栏 工程浏览窗口 工程大纲窗口 控制台输出窗口 在窗口选项中悬浮放在Show View选项中可以查看所有的窗口 ...
- “refer to”和“refer to as”在英语中的用法有所不同
"refer to"和"refer to as"在英语中的用法有所不同,具体区别如下: Refer to "Refer to"意为" ...
- 【转载】 四轴PID算法:单环和串级
原文地址: http://m.elecfans.com/article/1122372.html --------------------------------------------------- ...
- 一个简单的例子测试numpy和Jax的性能对比 (续)
相关: 一个简单的例子测试numpy和Jax的性能对比 numpy代码: import numpy as np import time x = np.random.random([10000, 100 ...
- 强化学习框架chainerrl的安装
源码地址: https://gitee.com/mirrors_chainer/chainerrl PS: 需要注意的是本文的安装方式并不能支持CUDA,也就是无法使用GPU进行计算:年久失修的计算框 ...
- tf.py_func的一些使用笔记——TensorFlow1.x
tensorflow.py_func是TensorFlow1.x版本下的函数,在TensorFlow.2.x已经不建议使用了,但是依然可以通过tf.compat.v1.py_func的方式来进行调用. ...
- 【技术积累】如何处理Feign的超时问题
在使用Feign进行微服务之间的通信时,由于网络延迟等原因,可能会出现请求超时的情况.为了解决这个问题,我们可以对Feign进行配置,设置超时时间. 配置Feign的超时时间 在使用Feign时,我们 ...
- MPTCP(三) : 在内核中启用MPTCP相关模块
在内核中启用MPTCPv1相关的模块 1. 简介 本文所涉及的均为MPTCPv1版本的MPTCP,采用的内核版本为5.18.19 需要注意的是 虽然MPTCP官方文档中提到在5.6之后的linux内核 ...