Mysql数据库(2)—事务和锁

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Mysql数据库(2)—事务和锁

一、事务

数据库事务的特性?

数据库事务的四大特性是ACID。

  1. 原子性:就是所有操作要么全不做,要不全做。通过undo日志来实现。
  2. 一致性:就是在并发情况下数据库由一个状态转移到另一个状态的数据要一致。通过事务的隔离级别来实现。
  3. 隔离性:多个事务的操作互相不影响,数据有4种隔离级别来解决。基于锁+mvcc机制来实现。
  4. 持久性:数据库中事务一旦提交,数据持久到硬盘中。基于redo日志来实现。

数据不一致的问题

  1. 脏读:事务A读取一个数据,事务B对该数据进行修改,修改前后的数据都可以读到,但是数据会不一样,导致了脏读。脏读强调的是读到其他事务未提交的数据。
  2. 不可重复读:事务A读一个数据,事务B对该数据进行修改后提交,导致事务A前后读取的数据值不一致。不可重复度强调的是读到其他事务提交后的数据和提交前的数据不一致。
  3. 幻读:事务A读取一个数据,事务B在insert、delete增删记录,事务A两次读取的数据条数不一致

事务的隔离级别

事务的隔离级别描述的是在多个事务同时运行过程中各自事务中数据的隔离办法,事务的隔离级别是为了解决数据库中以上常见的三类问题,包括:脏读、不可重复读和幻读的问题,者四类隔离级别分别为:

  • 未提交读:事务A可以读到事务B未提交的数据;
  • 已提交读:事务A只能读到事务B提交后的数据;
  • 可重复读:事务A能读取到事务B还未执行完的数据,但是读取到的是事务B未开始事务前的数据,只有当事务B执行完成了才会读取到新的数据;
  • 可串形化:事务A、事务B的读写操作是串形化的;

总结:

  • 以上4类隔离级别的约束条件从宽松到严格;
  • 未提交读隔离级别没有解决任何问题;
  • 已提交读解决了脏读的问题;
  • 可重复读解决了不可重复读的问题,但还存在幻读的问题,但结合MVCC和record lock能解决幻读的问题;
  • 只有可串形化隔离级别能解决所有数据不一致的问题;
  • Mysql的默认隔离级别是可重复读。

mysql如何解决幻读?

在快照读情况下,即不加锁的非阻塞读,像普通select操作下通过mvcc避免幻读;通过乐观锁类避免。

对于可重复读的隔离级别下,select * from table的语句是采用快照读的模式,新的事务会读快照;

在当前读情况下,当前读表示需要读取当前最新数据,是加锁的阻塞读写操作,像普通update/insert/delete和加update的select操作,是通过next-key lock避免幻读;通过悲观锁来避免。

对于可重复读的隔离级别,如果是当前读场景,需要通过间隙锁(Gap Lock)模式来避免幻读,这样行间间距会被加锁,不会被新的事务插入新的数据,间隙锁加行锁合起来称为next-key lock;

二、锁

锁是计算机中协调多线程并发访问共享资源的机制,在数据库中就是协调多个事务同时访问同一数据记录的机制,在Mysql数据库中进行加锁的对象是索引中的索引项,会在索引项上做加锁标记。

锁的分类

mysql数据库的锁分为行锁和表锁。

A11F43AF-0F68-4D8F-83AB-2022CCC4884F

  • 行锁。是innodb存储引擎的默认加锁方式,特点是开销大,加锁慢,锁力度小,所以并发度高,适合写多读少场景。
  • 表锁。是myisam存储引擎的默认加锁方式,特点是开销小,加锁快,锁粒度大,所以并发度低,适合读多写少场景。

  • 记录锁(Record lock):即是行级锁,是innodb存储引擎的默认加锁方式。

  • 间隙锁(Gap lock):会对记录之间的左开右闭的区间进行加锁;
  • 临键锁(Next key Lock):记录锁+间隙锁统称为临键锁。
  • 共享锁(读锁)&独占锁(写锁):共享锁又称S锁/读锁,对记录进行读操作时进行加的锁,可以共享;独占锁又称X锁/写锁,对记录进行写操作时进行加锁,只能独占;
  • 意向共享锁&意向排它锁:为了解决对记录加了共享锁&独占锁,再对表加表锁的时候需要遍历,所以在对行加共享锁&独占锁时候,会对表加上意向共享锁&意向排它锁,下次加表锁一目了然,这是一类表锁。
  • 插入意向锁:就是多个事务在进行插入的时候,已经有事务在进行插入操作了,另一个在等待的事务需要加上插入意向锁,用以表面针对目前的间隙位置有插入的需求;

数据库里的乐观锁和悲观锁?

所有需要加锁的操作都是在进行多线程情况下才需要的。

  1. 乐观锁比较好理解,就是预测所有线程对数据的操作都是不会冲突的,所以每次对数据进行操作时候都不会加上锁;mysql内部机制可以通过mvcc机制来是实现乐观锁;
  2. 悲观锁则相反,就是认为每次线程对数据的操作都可能存在冲突,所以需要对数据加上行锁、表锁等。mysql主要通过record lock+nextKey lock来实现。

mysql的悲观锁实现?

mysql加锁是通过锁住索引来实现的,如果没有索引和主键则会锁住整张表。mysql是通过record lock、Gap lock和next-key lock来实现加锁策略的。

  • Record lock:对行进行加锁
  • Gap lock:对间隙进行加锁
  • Next-key lock:Record lock+Gap lock的统称,innodb的默认实现方案;

InnoDB在执行查询语句SELECT时(非串行隔离级别),不会加锁。但是update、insert、delete操作会加行 锁。

mysql默认是autocommit提交事务,如果需要对select语句加锁,需要使用手动设置加锁操作。手动设置加锁的步骤:

beginSelect * from xxx where xxx for update//加上for update进行强制加写锁;
select * from xxx where xxx lock in share mode//加上lock in share mode进行强制加读锁
进行各种操作//这样的话在还么有commit之前,该行记录一直处于锁定状态;
commit

mysql的乐观锁mvcc机制原理?

mysql是通过mvcc机制来实现乐观锁的。mvcc是一种不加锁的方式解决读写冲突的机制,支持mysql上了写锁,还能继续支持读,解决读操作阻塞写操作的问题。在mysql中对一行记录的读写,默认使用的是mvcc机制,避免频繁使用加锁机制影响性能。

主要通过隐含字段undo日志read view来实现。核心思想是在select查询操作前生成一个read view(一致性读视图)中事务id的大小,用来判断是否需要从undo日志组成的版本链中读取历史数据。

  • 隐藏字段:每一条记录都会隐藏row_id、trx_id、roll_ptr。
  • undo日志:mysql中的undo日志记录操作前的状态,可以实现回滚到之前状态。
  • read view:mysql中存在当前读和快照读的概念,mvcc是通过快照读来实现多线程并发操作的,每次进行读操作时,会生成一个read view,读取之后比较事务id的大小来判断是否进行了一致性读。

mysql本身如何处理死锁问题?

Mysql目前机制是死锁超时会退出,将持有最少行级互斥锁的事务回滚。针对mysql无法自己解决的死锁问题,需要通过线程日志找到发生死锁的线程id,再通过kill 杀掉发生死锁的线程。

如何避免死锁?

问题说明:

两个或多个事务占用同一个共享资源,并且互相请求对方资源的锁,这样就会造成死锁。比如事务A请求事务B加锁的数据,同时事务B请求事务A加锁的数据,这样就会形成死锁情况。

解决方案:

  1. 让数据的查询尽量索引完成,避免索引加锁失败,从行级锁升级成表锁。
  2. 保持事务的顺序执行;
  3. 尽量减少查询范围,避免间隙锁加锁的范围;
  4. 事务执行逻辑简短,减少加锁时间;
  5. 死锁检测。执行之前做循环引用的检测。

Mysql只操作一条记录也有可能发生死锁吗?

有可能。Mysql的加锁对象是索引而不是记录,所以当一个事务对该记录的非主键索引加锁,并请求主键索引的锁,但另一个事务对该记录的主键索引已加锁,并请求该记录的非主键索引的锁,那么就会进入死锁状态。

如何优化事务

  1. 将数据处理工作放在事务外进行,缩短在事务中执行的时间;
  2. 不要一次性创建逻辑流程太长的事务,将这些事务拆分成多个小事务;
  3. 事务中不要进行RPC等耗时较长的操作,调用超时可能导致事务超时;
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
SQL 关系型数据库 MySQL
乐观锁在分布式数据库中如何与事务隔离级别结合使用
乐观锁在分布式数据库中如何与事务隔离级别结合使用
|
26天前
|
存储 Oracle 关系型数据库
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
从基本特性、技术选型、字段类型、事务提交方式、SQL语句、分页方法等方面对比Oracle和MySQL的区别。
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
|
10天前
|
监控 关系型数据库 MySQL
MySQL锁机制与解决死锁问题
MySQL锁机制与解决死锁问题
42 5
|
1月前
|
SQL 关系型数据库 MySQL
MySQL基础:事务
本文详细介绍了数据库事务的概念及操作,包括事务的定义、开启、提交与回滚。事务作为一组不可分割的操作集合,确保了数据的一致性和完整性。文章还探讨了事务的四大特性(原子性、一致性、隔离性、持久性),并分析了并发事务可能引发的问题及其解决方案,如脏读、不可重复读和幻读。最后,详细讲解了不同事务隔离级别的特点和应用场景。
93 4
MySQL基础:事务
|
10天前
|
存储 SQL 关系型数据库
MySQL 的锁机制,那么多的锁,该怎么区分?
MySQL 的锁机制,那么多的锁,该怎么区分?
21 0
|
10天前
|
SQL Oracle 关系型数据库
详解 MySQL 的事务以及隔离级别
详解 MySQL 的事务以及隔离级别
21 0
|
1月前
|
关系型数据库 MySQL 数据库
Mysql的锁
本文介绍了MySQL中表级锁和行级锁的区别,其中MyISAM仅支持表级锁,而InnoDB支持表级锁和行级锁,默认为行级锁。表级锁锁定整个表,实现简单,资源消耗少,但并发度低;行级锁仅锁定相关记录,减少冲突,提高并发度,但加锁开销大。此外,还介绍了共享锁和排他锁的概念及意向锁的作用。
|
1月前
|
SQL 安全 数据库
基于SQL Server事务日志的数据库恢复技术及实战代码详解
基于事务日志的数据库恢复技术是SQL Server中一个非常强大的功能,它能够帮助数据库管理员在数据丢失或损坏的情况下,有效地恢复数据。通过定期备份数据库和事务日志,并在需要时按照正确的步骤恢复,可以最大限度地减少数据丢失的风险。需要注意的是,恢复数据是一个需要谨慎操作的过程,建议在执行恢复操作之前,详细了解相关的操作步骤和注意事项,以确保数据的安全和完整。
69 0
|
2月前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
75 0
|
2月前
|
C# Windows 监控
WPF应用跨界成长秘籍:深度揭秘如何与Windows服务完美交互,扩展功能无界限!
【8月更文挑战第31天】WPF(Windows Presentation Foundation)是 .NET 框架下的图形界面技术,具有丰富的界面设计和灵活的客户端功能。在某些场景下,WPF 应用需与 Windows 服务交互以实现后台任务处理、系统监控等功能。本文探讨了两者交互的方法,并通过示例代码展示了如何扩展 WPF 应用的功能。首先介绍了 Windows 服务的基础知识,然后阐述了创建 Windows 服务、设计通信接口及 WPF 客户端调用服务的具体步骤。通过合理的交互设计,WPF 应用可获得更强的后台处理能力和系统级操作权限,提升应用的整体性能。
77 0

热门文章

最新文章