MySQL操作之事务管理

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL操作之事务管理




一、概念

1.1 简介

事务就是针对数据库的一组操作。由一条或者多条SQL语句组成,同一个事务的操作具备同步的特点,如果其中的一条语句无法执行,那么所有的语句都不会执行。

重点:

  • 也就是说事务中的语句要不都执行,要不都不执行。
  • 在MySQL中直接书写的SQL语句都是自动提交的。
  • ROLLBACK语句,只能针对未提交的事务执行回滚操作。已提交的事务是不能回滚的。
  • 事务的4个特性:原子性、一致性、隔离性、持久性

1.2 事务的4个特性

1 原子性

  • 是指一个事务必须被视为一个不可分割的最小工作单元,只有事务中所有的数据库操作都执行成功,才算整个事务都执行成功,事务中如果有任何一个SQL执行失败,已经执行成功的也必须要被撤销,数据库的状态要退回到执行事务前的状态。
  • ⼀个事务的执⾏被视为⼀个不可分割的最⼩单元。事务⾥⾯的操作,要么全部成功执⾏,要么全部失败回滚,不可以只执⾏其中的⼀部分。

2 一致性

⼀个事务的执⾏不应该破坏数据库的完整性约束。如果上述例⼦中第2个操作执⾏后系统崩溃,保证A和B的⾦钱总计是不会变的。

3 隔离性

还可以被称为并发控制、可串行化、锁等。当多个用户访问数据库时,数据库为每一个用户开启的事务,不能被其它事务的操作数据所干扰,多个并发事务之间要相互隔离。

4 持久性

事务一旦提交,其所作的修改就会永久的保存在数据库中,即使数据库发生故障也不应该对其有任何影响。

事务提交之后,需要将提交的事务持久化到磁盘。即使系统崩溃,提交的数据也不应该丢失。

二、事务的提交、回滚

  • 事务的操作是手动开启的,操完完成后,一定要提交事务。
  • 没有提交事务COMMIT,重新连接后,数据库结果将回到开启事务前,也就是更新操作未保存。

开启事务

START TRANSACTION;

提交事务

COMMIT;

回滚事务:

  • 在操作一个事务时,假如发现不合理可以,未提交之前COMMIT可以回滚事务ROLLBACK
ROLLBACK;

案例:

START TRANSACTION;
UPDATE account SET money = money - 100 WHERE name = 'zhangsan';
COMMIT;

三、事务的隔离级别

数据库是多线程并发访问的,很容易出现多个线程同时开启事务的情况,会出现脏读、重复读和幻读等,为避免这些情况,需要设置一定的事务隔离级别。

3.1 并发问题

1.脏读

脏读是指在⼀个事务处理过程⾥读取了另⼀个未提交的事务中的数据。

也就是不能读到前⼀个事务未完成,未commit的数据。只有commit后才能读到更新后的数据,没有commit,则还是之前的数据。

2. 不可重复读

线程1:在当前线程内,多次读,结果不⼀致(读到了另⼀事务update的数据)

不可重复读是指在对于数据库中的某个数据,⼀个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另⼀个事务修改并提交了,主要是针对update。

3.幻读

在当前线程内,多次读,结果不⼀致(读到了另⼀事务insert的数据)

例如事务T1对⼀个表中所有的⾏的某个数据项做了从“1”修改为“2”的操作,这时事务T2⼜对这个表中插入了⼀⾏数据项,⽽这个数据项的数值还是为“1”并且提交给数据库。⽽操作事务T1的⽤户如果再查看刚刚修改的数据,会发现还有⼀⾏没有修改,其实这⾏是从事务T2中添加的,就好像产⽣幻觉⼀样,这就是发⽣了幻读。幻读主要是针对insert与delete。

3.3 事务隔离级别

READ UNCOMMITTED(读未提交):

事务中的修改,即使没有提交,在其他事务也都是可⻅的。事务可以读取未提交的数据,这也被称为脏读。

READ COMMITTED(读已提交):

⼀个事务从开始直到提交之前,所做的任何修改对其他事务都是不可⻅的。这个级别有时候也叫做不可重复读,因为两次执⾏相同的查询,可能会得到不⼀样的结果。因为在这2次读之间可能有其他事务更改这个数据,每次读到的数据都是已经提交的。

REPEATABLE READ(可重复读):

解决了脏读,也保证了在同⼀个事务中多次读取同样记录的结果是⼀致的。但是理论上,可重读读隔离级别还是⽆法解决另外⼀个幻读的问题,指的是当某个事务在读取某个范围内的记录时,另外⼀个事务也在该范围内插入了新的记录,当之前的事务再次读取该范围内的记录时,会产⽣幻⾏。

SERIALIZABLE(可串⾏化):

它通过强制事务串⾏执⾏,避免了前⾯说的幻读的问题。

3.3 查询/设置事务隔离级别

脏读:(脏读是指在⼀个事务处理过程⾥读取了另⼀个未提交的事务中的数据。)

查看事务隔离界别

select @@tx_isolation;

设置事务隔离级别

set session transation isolation level read uncommitted;

四、InnoBD 可重复读隔离级别下如何避免幻读

  • 表象:快照读(非阻塞读)–伪MVCC
  • 内在:next—key锁(行锁+gap锁)

当前读和快照读:

  • 当前读:select…lock in share mode ,select … for update
  • 当前读:update,delete,insert 加了锁的增删改查语句。
  • 快照读:不加锁的非阻塞读,select

当前读:

当前读就是加了锁的增删改查语句,不管上的是共享锁还是排它锁上的都是当前读,因为它读取的是最新版本,读取后还保证其它并发事务不能读取当前记录。对读取的记录加锁,除了select lock… 会加共享锁之外,其它的操作加的都是排它锁。

update、delete、insert 也都是当前读,RDBMS主要由程序实例和存储组成,如图所示。程序实例在这里指的是mysqlServer的程序实例,存储就是InnoDB。

拿update来举个例子:

当update发送给mysql之后,mysqlServer会根据where读取第一条满足where的条件记录,InnoDB会将第一条数据返回并加锁。mysqlServer收到加锁的记录后会发起一个update操作,去更新这条记录,一条记录读取完成后再去读取下一条记录,直至没有满足条件的记录出现。

update操作就包括一个当前读来获取数据的最新版本,就如之前在已提交读的隔离级别下出现的幻读的情况一样,由于先前事务新提交了一个数据,当前事务update全表的时候就莫名其妙多了一条数据,即读取到了数据的最新版本,同理delete也一样,insert会稍有不同,简单来说insert会触发唯一键的检查,也会进行一个当前读。

快照读:

快照读与当前读不太一样,它就是简单的select操作,不加锁,是在隔离级别不在串行化的条件下实现的,在serializable下由于是串行读,所以快照读也退化成当前读的lock in share mode的模型。

之所以出现快照读是基于提升并发性能的考虑,快照读的实现是基于多半版并发控制即MVCC,可以认为MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此:开销更低,但是快照读读取的可能不是最新版本,是历史版本。

在Read committed(读已提交)情况下当前读和快照读读到的数据是一样的。

在Repeatable read(可重复读)的情况下

情况1:

session1、session2都开启事务,先在session1中读取账户余额发现是600,在session2中修改账户余额为300,再在session1中用当前读查看账户余额为300,用快照读查询账户余额还是600。图中第一条语句为快照读,第二条语句为当前读。这里快照读读到的就是历史版本。

情况2:

session1、ession2都开启事务,我们在session2中更新账户余额,在session1中当前读与快照读查询到的都是最新版本。

在RR级别下可以让我们看不到幻读,是因为采用了伪MVCC机制,关于伪MVCC机制更多的可以去看第五章,其实伪MVCC机制有一些掩耳盗铃的感觉,已经做了更改就是看不见,真正实现避免幻读的还是使用了间隙锁。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
5月前
|
SQL 运维 关系型数据库
MySQL 中 GRANT 操作会引起复制中断吗?
GRANT 操作并不是一个原子性操作,不管执行成功与否,都会触发一个隐式重载授权表的行为。 在生产环境中需要规范用户创建及授权的操作,不推荐使用 DML 语句去直接变更 mysql.user 表,可能会引发其他的问题,若使用了 DML 语句进行变更, 需要手工执行 flush privileges。
76 4
|
5月前
|
JavaScript 关系型数据库 MySQL
创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作
创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作
74 0
|
6月前
|
关系型数据库 MySQL
【mysql技巧】如何在这个mysql语句执行前加个前提,也就是只有表里没有相同数据才进行添加插入操作
【mysql技巧】如何在这个mysql语句执行前加个前提,也就是只有表里没有相同数据才进行添加插入操作
45 1
|
5月前
|
存储 关系型数据库 文件存储
面试题MySQL问题之简单的SELECT操作在MVCC下加锁如何解决
面试题MySQL问题之简单的SELECT操作在MVCC下加锁如何解决
54 2
|
5月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版操作报错合集之从mysql读数据写到hive报错,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
5月前
|
消息中间件 关系型数据库 MySQL
实时计算 Flink版操作报错合集之运行mysql to doris pipeline时报错,该如何排查
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
5月前
|
消息中间件 关系型数据库 MySQL
实时计算 Flink版操作报错合集之整库同步mysql到starRock提交任务异常,该如何处理
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
5月前
|
SQL 关系型数据库 MySQL
「Python入门」python操作MySQL和SqlServer
**摘要:** 了解如何使用Python的pymysql模块与MySQL数据库交互。首先,通过`pip install pymysql`安装模块。pymysql提供与MySQL的连接功能,例如创建数据库连接、执行SQL查询。在设置好MySQL环境后,使用`pymysql.connect()`建立连接,并通过游标执行SQL(如用户登录验证)。注意防止SQL注入,使用参数化查询。增删改操作需调用`conn.commit()`来保存更改。pymssql模块类似,但导入和连接对象创建略有不同。
73 0
「Python入门」python操作MySQL和SqlServer
|
5月前
|
SQL 存储 关系型数据库
|
6月前
|
关系型数据库 MySQL 数据库
『Django』模型入门教程-操作MySQL
一个后台如果没有数据库可以说废了一半。日常开发中大多数时候都在与数据库打交道。Django 为我们提供了一种更简单的操作数据库的方式。 在 Django 中,模型(Model)是用来定义数据库结构的类。每个模型类通常对应数据库中的一个表,类的属性对应表中的列。通过定义模型,Django 的 ORM(Object-Relational Mapping)可以将 Python 对象映射到数据库表,并提供一套 API 来进行数据库操作。 本文介绍模型的用法。