Mysql事务

一:隔离级别

READ UNCOMMITTED(未提交读)
在READ UNCOMMITTED级别下,在一个事务中的修改,即时没有提交,对其他事务也多是可见的。事务可以读取未提交的数据,这也称为脏读(Dirty Read)。这个级别会导致很多问题,而且从性能上来说,也不会比其他级别好太多,除非有非常必要的理由,在实际应用中一般很少用到。

READ COMMITTED(提交读)
大多数据库系统的默认隔离级别都是READ COMMITTED(但MySQL不是)。READ COMMITTED满足事务的隔离性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改,对其他事务是不可见的。这个级别也叫做不可重复读(nonrepeatable read),因为两次执行相同的查询结果,可能会得到不一样的数据。

REPEATABLE READ(可重复读)
REPEATABLE READ解决了脏读的问题。该级别保证了在同一个事务中多次读取相同记录的结果是一样的。但理论上,可重复读仍然无法解决幻读的问题。所谓脏读,指的是当某个事务在读取某个范围的数据时,另外一个事务又在该范围插入了新的记录 。当之前的事务在此读取该范围时,会产生幻读行(Phantom Row)。InnoDB和XtraDB存储引擎通过版本并发控制MVCC(Multiversion Concurrency Control)解决了幻读问题。可重复读诗MySQL的默认事务隔离级别。

SERIALIZABLE(可串行化)
SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读区每一行数据上都加索,所以可能导致大量的超时和锁争用问题。实际应用中也很少用到这个隔离级别,只有在非常要求确保数据的一致性而且不考虑并发的情况下,才考虑到用该级别。

二:死锁
死锁是指两个或多个事务在同一资源上互相占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。当多个事务试图以不同的顺序锁定资源时,就可能会产生死锁。多个事务同时锁定同一个资源时,也会产生死锁。例如下面的例子:
事务1:

START TRANSACTION;
UPDATE StockPrice SET close = 45.50 WHERE stock_id = 1;
UPDATE StockPrice SET close = 19.80 WHERE stock_id = 2;

事务2:

START TRANSACTION;
UPDATE StockPrice SET close = 20.50 WHERE stock_id = 2;
UPDATE StockPrice SET close = 47.80 WHERE stock_id = 1;

如果凑巧,两个事务都执行了第一条UPDATE语句,同时也锁定了该行数据,接着每个事务都尝试去执行第二条UPDATE语句,却发现改行已经被对方锁定,然后两个事务都等待对方释放锁,同时又都持有对方需要的锁,则陷入死循环。除非有外部因素介入才可能解决死锁;
InnoDB目前处理死锁的方式是:将持有最少行级排他锁的事务进行回滚(这也是相对比较简单的死锁回滚算法)。
死锁发生以后,只有部分或者完全回滚其中一个事务,才能打破死锁。对于大多事务型的系统,这是无法避免的。所以应用程序在设计时必须考虑如何避免和处理死锁。大多数情况下,只需要重新执行因死锁回滚的事务即可。

三:MySQL中的事务

MySQL提供了两种事务类型的存储引擎:InnoDB和NDB Cluster。另外还有一些第三方的存储引擎也支持事务,例如比较知名的XtraDb和PBXT。
自动提交(AUTOCOMMIT)
MySQL默认采用自动提交(AUTOCOMMIT)模式。也就是说,如果不是hi显示的开始一个事务(START TRANSACTION),则每个查询都被当成一个事务执行提交操作。在当前连接中,可以通过设置AUTOCOMMIT变量来启用或禁止自动提交模式:
clipboard.png
1或者ON表示开启,0或者OFF表示禁止。当AUTOCOMMIT=0时,所有的查询都是在一个事务中,直到显示的执行COMMIT或ROLLBACK回滚,该事务结束,同时又开始另一个新事事务。
注:修改AUTOCOMMIT对非事务型的表,比如MyISAM不会有任何影响。对这类表来说,没有COMMIT或ROLLBACK的概念。
另外,还有一下命令,在执行之前会强制执行COMMIT提交当前的活动事务,比如DDL语句,ALTER TABLE导致大量数据改变的操作。

MySQL可以通过 SET TRANSACTION ISOLATION LEVEL命令来设置隔离级别。新的隔离级别在下一个事务开始的时候生效。可以在配置文件中设置整个数据库的隔离级别,也可以指改变当前回话的隔离级别:
mysql> SET TRANSACTION ISOLATION LEVEL READ COMMITED;

四:在事务中混合使用存储引擎

MySQL服务层不管理事务,事务是由下层的存储引擎实现的。所以在同一个事务中,使用多种存储引擎室不可靠的。
如果在一个事务中同时使用了事务型和非事务型的表(比如InnoDB和MySIAM表),在正常提交的情况下不会有什么问题。注:在非事务型的表上执行事务相关操作,MySQL不会发生提醒。但是在回滚时会发出一个警告。
但是要回滚该事务,非事务型的表上的变更就会无法撤销,这回导致数据库处于不一致的状态,这种情况很难修复,事务的结果最终也将无法确定。所以,为每张表选择合适的存储引擎非常重要。

关于更深入的事务执行,等小爷研究后了再来更新...(不会太久)

web工程师

13 声望
1 粉丝
0 条评论
推荐阅读
一文搞懂秒杀系统,欢迎参与开源,提交PR,提高竞争力。早日上岸,升职加薪。
前言秒杀和高并发是面试的高频考点,也是我们做电商项目必知必会的场景。欢迎大家参与我们的开源项目,提交PR,提高竞争力。早日上岸,升职加薪。知识点详解秒杀系统架构图秒杀流程图秒杀系统设计这篇文章一万多...

王中阳Go33阅读 2.5k评论 1

封面图
万字长文~vue+express+mysql带你彻底搞懂项目中的权限控制(附所有源码)
所谓的权限,其实指的就是:用户是否能看到,以及是否允许其对数据进行增删改查的操作,因为现在开发项目的主流方式是前后端分离,所以整个项目的权限是后端权限控制搭配前端权限控制共同实现的

水冗水孚11阅读 1.5k

花了几个月时间把 MySQL 重新巩固了一遍,梳理了一篇几万字 “超硬核” 的保姆式学习教程!(持续更新中~)
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。

民工哥11阅读 1.1k

封面图
一次偶然机会发现的MySQL“负优化”
今天要讲的这件事和上述的两个sql有关,是数年前遇到的一个关于MySQL查询性能的问题。主要是最近刷到了一些关于MySQL查询性能的文章,大部分文章中讲到的都只是一些常见的索引失效场合,于是我回想起了当初被那个...

骑牛上青山8阅读 2.2k评论 2

2023最新MySQL高频面试题汇总
本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~

程序员大彬3阅读 978

Mysql索引覆盖
通常情况下,我们创建索引的时候只关注where条件,不过这只是索引优化的一个方向。优秀的索引设计应该纵观整个查询,而不仅仅是where条件部分,还应该关注查询所包含的列。索引确实是一种高效的查找数据方式,但...

京东云开发者2阅读 936

封面图
初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go2阅读 407评论 1

封面图

web工程师

13 声望
1 粉丝
宣传栏