事务一
点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃
1.什么是事务
mysql存的是数据注定会被多个客户端同时访问,mysql内部是采用多线程方式来实现存储相关工作的,注定会有对数据并发访问的场景,为了更好解决这类事情,关系型数据库为我们提供了事务。
CURD不加控制,会有什么问题?
当两个人同时向火车票售票系统买票时,买票肯定先判断是否有票,当A进入判断之后,客户端A因为某些原因线程被切走了,然后客户端B也要判断进来之后也因为某些原因线程被切走了。此时A被唤醒从被切走的地方继续往下执行然后把票数减1就结束了它的操作。B然后也被唤醒了继续往下执行因为它是已经在判断里面的,它并不知道此时票数减为0了,它以为还有此时票数又被减1了。此时就有问题了。一张票被卖了两次!
数据库为了解决并发带来的问题,必须提出解决的方案!
CURD满足什么属性,能解决上述问题?
- 买票的过程得是原子的吧
要么没买,要么一定买成功,不存在中间状态,出现问题回滚到开始状态,彷佛什么事情都没干一样。 - 买票互相应该不能影响吧
我买的过程之中,你就来了,你会影响到我。彼此之间要隔离开,你买你的,我买我的,不要互相影响。 - 买完票应该要永久有效吧
购买成功这件事情必须是持久的,不受其他情况影响。 - 买前,和买后都要是确定的状态吧
买前就是没买状态,买了就是买了状态,不能出现中间状态。
随着下面的学习,我们慢慢理解为什么四个就已经能够解决这个问题了。
那什么是事务?
实际上当我们写sql语句的时候,不一定一条sql就能解决所有问题,有时候我们需要一批sql语句在一起才有意义。就比如转钱,一定是这里update 减去100 ,哪里update 加上100。这两句单但拿出来就是一条sql语句没有意义,但是站在上层使用数据库的人,把两条sql合在一起(看成一个整体)它就叫做转账逻辑。所以我们把两条sql共同构成的一组DML数据管理语句,叫做事务。 换句话说,
事务是由一条或者多条sql语句构成的sql集合体,这个集合体合在一起共同要完成某种任务。
事务就是一组DML语句组成,这些语句在逻辑上存在相关性,(比如转账逻辑,分开就是两条单独update语句,但是合在一起它们是有逻辑关系的,所以学习事务不能站在程序员视角理解事务,一定要站在使用数据库的使用者去看待事务)这一组DML语句要么全部成功,要么全部失败,是一个整体。这是由MySQL给我们提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。
事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。假设一种场景:你毕业了,学校的教务系统后台 MySQL 中,不在需要你的数据,要删除你的所有信息(一般不会:) ), 那么要删除你的基本信息(姓名,电话,籍贯等)的同时,也删除和你有关的其他信息,比如:你的各科成绩,你在校表现,甚至你在论坛发过的文章等。这样,就需要多条 MySQL 语句构成,那么所有这些操作合起来,就构成了一个事务。
正如我们上面所说,一个 MySQL 数据库,可不止你一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,在向 MySQL 服务器发起事务处理请求。而每条事务至少一条 SQL ,最多很多 SQL ,这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现并发执行访问公共数据的问题。甚至,因为事务由多条 SQL 构成,那么,也会存在执行到一半出错或者不想再执行的情况,那么已经执行的怎么办呢?
所以,一个完整的事务,绝对不是简单的 sql 集合,还需要满足如下四个属性:
-
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,要么自动回滚(Rollback)到事务开始前的状态,要么用户手动回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
-
持久性:事务处理结束后,那事务对表中数据的修改就是永久的,即便系统故障也不会丢失。
-
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交替去进行修改同一份数据进而导致数据的不一致。所以事务可以将我们要访问的数据一个个隔离开,你访问你的并不会影响我,这就是隔离性。事务隔离可以分为不同级别,包括读未提交( Readuncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化( Serializable ),因为有隔离性所以可以保证数据在不同的隔离级别下保证不同用户对数据的可见性。
-
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。(意思是我们从一种状态变成另一种状态它的结果是可预期的,比如我转账,我账户200,你账户50。我给你转50,所以我可以预期的是成功了,我账户150,你账户100,失败了我还是200,你还是50。这就是我还没有操作,但是为了操作后结果是可预期的,这就是一致性。)这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
事务的四大特性之中,原子性和持久性最好理解,隔离性是我们要重点理解的,一致性比较不好理解,但是mysql对于事务一致性其实没有做什么工作。在技术上没有对一致性有什么策略,只不过一致性是通过原子性、持久性、隔离性来保证数据库的一致性 。原子性、持久性、隔离性是因,一致性是果。并且一致性光靠数据库是做不到的,还需要用户配合才能达到一致性,具体后面在说。
上面四个属性,可以简称为 ACID 。
- 原子性(Atomicity,或称不可分割性)
- 一致性(Consistency)
- 隔离性(Isolation,又称独立性)
- 持久性(Durability)
事务是一堆sql集合在业务层面上要完成某种具体需求,mysql为了支持我们,将多条sql这些sql在逻辑上有上下文关系的把它们封装成事务。 而为了更好支持事务不仅仅是简单把sql做封装,为了事务在并发条件下更好、更快、更安全去运行,此时就需要用原子性、持久性、隔离性、一致性来保证事务正确运行。最终一句话总结,所谓的事务在ACID的加持下由一条或者多条sql共同构建出的我们就称之为事务。
事务在mysql中的存在可以这样理解,mysql要同时帮助多个客户端完成不同的事务请求,就决定了mysql在运行期间会存在大量的事务,mysql也要把这些事务管理起来,先描述,在组织!所以mysql所谓的事务在我看来就是在mysql中来的一批sql,把这批sql打包成一个事务对象,然后将事务对象放在事务执行列表里,然后让mysql执行。
2.为什么会存在事务
刚才说的是多个sql在交叉执行可能会出现并发问题,进而导致数据不一致,进而导致数据完整性,这都知道。但是对事务的理解不能光站在程序员角度理解,一定要站在数据库使用者角度考虑。
事务被 MySQL 编写者设计出来,但是事务并不是天然就有的,而是在用一段时间发现要有这个事务。本质是为了当应用程序访问数据库的时候,事务能够简化我们的编程模型,不需要我们去考虑各种各样的潜在错误和并发问题。只需要把告诉我你要干什么,把你的sql给我,我帮你封装成事务,帮你去运行。可以想一下当我们使用事务时,要么提,要么回滚,我们不会去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?这些问题统统不考虑。因此事务本质上是为了应用层服务的,是为了让上层的应用服务更好的使用数据库。而不是伴随着数据库系统天生就有的。
备注:我们后面把 MySQL 中的一行信息,称为一行记录
3.事务的版本支持
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务, MyISAM 不支持。
查看数据库引擎
show engines; --表格显示
show engines \G --行显示
我们mysql默认搜索引擎是InnoDB,并且支持事务,MyISAM支持
4.事务的提交方式
事务的提交方式常见的有两种:
- 自动提交
- 手动提交
查看事务提交方式
show variables like 'autocommit';
事务默认是自动提交
可以手动用 SET 来改变 MySQL 的自动提交模式:
set autocommit=0; --设置为手动提交
set autocommit=1; --设置为自动提交