首页 > 数据库 >MySQL事务与隔离

MySQL事务与隔离

时间:2024-01-13 13:34:21浏览次数:29  
标签:事务 读取 并发 提交 MySQL 数据 隔离


事务

假设你想给张三转账500块钱,这时需要扣除你卡上的账户余额,并同时给张三卡上增加500块钱。如果转账的两个操作中的一个失败,那你就可能损失金钱或者让金钱消失不见,张三也就收不到钱了。

这时,事务就派上用场了。它可以保证这两个操作要么同时成功,要么同时失败,绝不会出现一半成功一半失败的尴尬局面。

所以,数据库为什么要有事务?其实就是为了保证业务正常运转,数据最终一致。

事务特性

接下来我们聊一聊事务的 4 个特性:原子性、一致性、隔离性和持久性,简称 ACID。

原子性(Atomicity)

原子性是指事务包含的操作要么全部成功,要么全部不成功。

比如 A、B 账户的初始余额为 800 元,100元。此时,A 向 B 转账 500 元,那么分解开来就是 A 账户减 500 元,B 账户加 500 元。

最终结果是 A 账户余额为 300 元,B 账户余额为 600 元。这两个账户余额更新的操作,要么全部执行,要么都不执行。

一致性(Consistency)

事务执行前,和执行后都会保持一致性状态。

A、B 账户在转账后,会发生两种情况:

钱转到 B 账户里了,这时 A、B 账户分别为 300、600 元;

钱转出去的过程中数据库网络断开,事务回滚了,A、B 账户还是 800、100 元。

无论怎样,事务发生前后,A、B 银行账户的总额都应该为 900 元,这就是前后一致性。

隔离性(Isolation)

隔离性是当多个用户并发访问数据库时,不管是不是操作同一个库、还是同一张表,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间也要相互隔离。

比如,A 向 B 转账的时候,不管别人怎么转账,都不会影响他们的交易。

持久性(Durability)

一个事务一旦被提交了,那么对数据库中的数据的改变就是持久性的【即保存到磁盘里】,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

拿给张三的例子,持久性就是:你只要给张三转了钱,钱就进了她的账户。

Q:为什么事务有这几大特性?

A:我们要保证事务的数据一致性,就需要一些手段来实现,这几种手段就是事务的几个特性。

它们分别是原子性、一致性、隔离性和持久性,其中一致性是目的,而原子性、一致性和隔离性都是为了实现数据一致性的手段。

事务并发和隔离

事务并发

并发是指计算机系统或程序在同一时间内同时处理多个任务或操作的能力,也就是允许多个用户进程去处理同一块临界区。

拿转账为例,用户进程就是负责交易的服务器进程,临界区就是张三账户的存储空间。

如果出现了事务并发,就会带来一些意想不到的问题,例如常见的脏写、脏读、重复读和幻读

脏写

脏写是指:在事务并发的时候,一个事务可以修改另外一个正在进行中的事务的数据,这可能会导致一个写的事务会覆盖另外一个写的事务数据。

拿转账为例,假如你给张三转了 500 块,王五给张三转了 1000 块,在写入数据库的时候,你写入的数据被王五的数据给覆盖了。最后导致的结果就是,你钱没了,而张三却只收到了王五的转账。

事务隔离

500 块钱没了怎么办?这时就要用到事务隔离。

MySQL 提供了事务隔离级别,包括:读未提交、读已提交、可重复读以及串行化,来解决事务中各种并发问题,专治各种不开心。

RU - 读未提交(Read uncommitted)

RU(读未提交)是指,如果一个事务开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读取此行数据。RU 可以排他写,但是不排斥读线程实现。这种隔离级别解决了上面的脏写问题,但可能会出现脏读,即事务 B 读取到了事务 A 未提交的数据。

RC - 读已提交(Read committed)

该隔离级别在一个事务进行数据写入时,不允许别的事务对该行数据进行访问(包括读写)。这样就可以保证事务读到的数据一定是已经提交了的,解决了脏读的问题。但是会出现不可重复读的问题,比如:事务 A 需要读取两次数据,在读取完第一次数据后,有另一个事务 B 对该数据进行的更新并提交事务。此时事务 A 再次读取该数据时,数据已经发生了改变,即事务中两次读取的数据不一致。

RR - 可重复读( Repeatable read)

在同一个事务内,多次读取同一个数据,在这个事务还未结束时,其他事务不能访问该数据(包括读写)。这种隔离级别下解决了脏读和不可重复读的问题,但是可能会出现幻读。

如事务 A 在多次读取数据时,有另一个事务 B 在数据行中间插入或删除了数据,此时事务 A 再次读取时,可能会发现数据的行数变了。

简单来说,RR - 可重复读可以保证当前事务不会读取到其他事务已提交的 update 操作,但无法感知其他事务的 insert 和 delete 操作。

可串行化(Serializable)

该隔离级别下,事务只能依次执行,解决了脏读、不可重复读和幻读的问题。但是代价较高,性能很低,一般很少使用。

在这种情况下,每次有事务进来都需要排队等候,直到前面的交易事务完全结束。

总结

数据库通过隔离级别解决了事务并发出现的各种问题:

  • RU,读未提交解决了脏写问题,但可能出现脏读;
  • RC,读已提交解决了脏读问题,但可能出现不可重复读;
  • RR,可重复读解决了不可重复读的问题,但可能出现幻读;
  • Serializable,串行化解决了幻读的问题,但性能很低。

MySQL 是怎么实现事务隔离性的呢?

答案是加锁

事务级别越高,解决的并发事务问题越多,同时也意味着加的锁就越多。

锁的个数对比:RU-读未提交 < RC-读已提交 < RR-可重复读 < Serializable-串行化。

但是,频繁的加锁可能会导致读取数据的时候没办法修改,修改数据的时候没办法读取,极大的降低了数据库读写性能,就像串行化的隔离级别那样。

所以,为了权衡数据安全和性能,MySQL 数据库默认使用的是 RR,即可重复读的隔离级别。

参考:微信公众平台

标签:事务,读取,并发,提交,MySQL,数据,隔离
From: https://blog.51cto.com/u_15856116/9232011

相关文章

  • 【LeetCode1747. 应该被禁止的 Leetflex 账户】MySQL用户变量编程;尝试维护一个multise
    题目地址https://leetcode.cn/problems/leetflex-banned-accounts/description/代码witht1as(selectaccount_id,ip_address,loginastick,"login"asmytypefromLogInfounionallselectaccount_id,ip_address,logoutastick......
  • 9 表操作之删除数据 -- MySQL数据库
    如果记录不再需要,则可以用delete命令进行删除。1.删除数据a.语法mysql>deletefrom表名[where条件];b.实例实例: --在emp中将ename为'dony'的数据全部删除。 代码:mysql>deletefromempwhereename='dony';2.删除多表数据a.语法mysql>delete表1,......
  • 如何在SAP GUI中快速执行新的事务代码
    当我们成功登录SAP的某个连接后,在SAPGUI起始页(SAP轻松访问),我们可以通过点击【收藏夹】或者在界面左上角的输入框输入对应的事务代码,直接进入对应事务的界面。但是下面列举的场景,你是否知道如何快速应对? 场景一:当前已处于某个事务代码中,如何进入新的事务代码?场景二:当前SA......
  • Mysql时间常用函数
    查看当前系统的时间  select sysdate();  selectcurdate(),now(),DATE_FORMAT('2024-01-03','%Y-%m-%d') 2024-01-13|2024-01-1311:32:28|2024-01-03 目前常用的就curdate now  DATE_FORMAT('2024-01-03','%Y-%m-%d')  oracle的s......
  • oracle和mysql语句的异同
    Oracle和MySQL是两个流行的关系型数据库管理系统,它们都有SQL(结构化查询语言)作为主要的查询语言。尽管它们共享许多基本的SQL功能,但它们之间也存在一些关键的差异。以下是一些Oracle和MySQL语句的异同点:数据类型:相同点:两者都有整数、浮点数、字符、日期等数据类型。不同点:Oracle有一......
  • MySQL一键安装Shell脚本的实现
    本文主要介绍了MySQL一键安装Shell脚本,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧−目录一、脚本说明1、linux系统版本2、MySQL版本3、运行方式二、脚本内容一、脚本说明1、linux系统版本EL6,EL7,EL8,......
  • 【Leetcode1949. 坚定的友谊】使用MySQL在无向图中寻找{"CompleteTripartite", {1, 1,
    目录题目地址思路代码MySQL代码等效Cypher查询(未验证)题目地址https://leetcode.cn/problems/strong-friendship/思路就是在无向图中寻找这个pattern:(*Mathematica*)GraphData[{"CompleteTripartite",{1,1,3}}]SQL写还是比较麻烦。更加复杂的查询还是建议把数据迁......
  • 【LeetCode 2142. 每辆车的乘客人数 I】乘客到站等车,车到站载客。MySQL用户变量编程完
    题目地址https://leetcode.cn/problems/the-number-of-passengers-in-each-bus-i/description/思路将所有关键时刻作为tick。(同一时刻车和人同时到,默认人在车前到)之后按照tick升序,使用MySQL用户变量编程完成计算逻辑。输出结果。代码withticksas(selectarrival_tim......
  • mysql8.0窗口函数
    2、新特性1:窗口函数2.1、使用窗口函数前后对比假设我现在有这样一个数据表,它显示了某购物网站在每个城市每个区的销售额:CREATETABLEsales(idINTPRIMARYKEYAUTO_INCREMENT,cityVARCHAR(15),countyVARCHAR(15),sales_valueDECIMAL);INSERTINTOsales(city,county......
  • 简单易用的 MySQL 官方压测工具
    一、MySQL自带的压力测试工具Mysqlslapmysqlslap是mysql自带的基准测试工具,该工具查询数据,语法简单,灵活容易使用.该工具可以模拟多个客户端同时并发的向服务器发出查询更新,给出了性能测试数据而且提供了多种引擎的性能比较。mysqlslap为mysql性能优化前后提供了直观的验证依据......