20240306数据库的毫秒级上锁特性与可重复读级别的MVCC快照处理方式

news2024/11/17 23:35:32

从后端程序发送SELECT指令到数据库加上读锁,这个过程的时间差取决于多个因素,包括网络延迟(如果存在)、数据库服务器的处理能力、当前数据库的负载以及查询本身的复杂度。在你的情况下,由于后端程序和数据库服务器运行在同一台服务器上,网络延迟可以忽略不计。

以下是一些可能影响查询响应时间的因素:

  1. 数据库服务器的处理速度:这取决于服务器的硬件配置,包括CPU、内存和磁盘I/O性能。
  2. 数据库的负载:同时执行的查询数量和类型(读/写操作的比例)会影响性能。
  3. 查询的复杂度:涉及的数据量、是否需要全表扫描、是否利用到索引等,都会影响执行时间。
  4. 数据库的配置:例如,缓冲池的大小、索引配置等。
  5. FastAPI和异步IO:FastAPI基于Starlette实现异步IO操作,这意味着它能够在等待I/O操作(如数据库查询)完成时,释放资源处理其他任务。但是,实际查询执行的速度取决于数据库本身的处理能力。

在理想情况下,如果查询简单(如针对已索引列的简单查找),且数据库负载不高,查询响应时间可以在毫秒级别(通常是数毫秒到几十毫秒)。复杂查询或高数据库负载可能会导致这个时间增加到数百毫秒,甚至更长。然而,这是一个非常粗略的估计,实际时间可能根据上述因素而大幅度变化。

为了获得更精确的测量,直接在环境中进行测试,使用Python的时间测量库(如timedatetime模块)来记录从发送SELECT指令到收到响应的确切时间。这样可以根据实际情况获得最准确的时间差。

import asyncio
import aiomysql
import time

async def test_select():
    # 数据库连接配置
    conn_config = {
        'host': 'localhost',
        'port': 3306,
        'user': 'your_username',
        'password': 'your_password',
        'db': 'your_database',
    }

    # 创建数据库连接池
    pool = await aiomysql.create_pool(**conn_config)
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            # 开始测量时间
            start_time = time.time()

            # 执行SELECT指令
            await cur.execute("SELECT * FROM your_table LIMIT 10")

            # 获取所有结果
            result = await cur.fetchall()

            # 结束测量时间
            end_time = time.time()

            # 计算执行时间
            elapsed_time = end_time - start_time
            print(f"Query executed in {elapsed_time} seconds.")

            # 打印结果(可选)
            for row in result:
                print(row)

    # 关闭连接池
    pool.close()
    await pool.wait_closed()

# 运行异步函数
asyncio.run(test_select())

选择aiomysql而不是pymysql主要是因为aiomysql提供了异步IO支持,这使得它在与异步框架(如FastAPI)结合时更为有效和适合。这里有几个关键点来解释为什么在某些情况下使用aiomysql比使用pymysql更好:

  1. 异步支持aiomysql是为了与Python的asyncio库一起工作而设计的,这意味着它可以在不阻塞主线程的情况下执行数据库操作。这对于需要高性能和高并发的web应用程序来说非常重要,因为它们可以同时处理大量的请求而不会因为数据库操作而导致性能瓶颈。

  2. 与FastAPI兼容性:FastAPI是一个现代的、快速(高性能)的web框架,用于构建API,它基于Python 3.6+的类型提示。FastAPI本身就是建立在异步IO之上的,意味着它能够非常高效地处理并发请求。使用aiomysql作为数据库驱动能够充分利用FastAPI的异步特性,从而提高应用的性能和响应能力。

  3. 提高应用的可伸缩性:异步IO可以帮助你的应用更好地处理大量并发连接,因为它通过非阻塞操作减少了等待时间。这在处理大量请求时可以显著提高应用的吞吐量和响应速度,同时也减少了资源消耗,比如减少了对线程和内存的需求。

相比之下,pymysql是一个纯Python实现的MySQL客户端,它提供了对MySQL数据库的同步操作。虽然pymysql非常易用且广泛应用于各种Python项目中,但它不支持异步操作,这意味着在执行数据库操作时,它会阻塞执行它的线程直到操作完成。在高并发的web应用场景中,这可能导致性能瓶颈。

综上所述,如果你的项目使用FastAPI或其他支持异步IO的框架,且需要高性能和高并发处理能力,aiomysql是一个更合适的选择。然而,如果你的项目不需要处理大量并发请求,或者使用的框架和库不支持异步IO,pymysql仍然是一个非常可靠和方便的选择。

结果:表内只有一行,行内3列,两个文字单元格,一个用base64编码存储的35k图片,用了3ms

 

我的运行结果是0.003.。second,但我要怎么确定这部分时间中哪些是上读锁的时间

要准确地测量和区分在0.003秒的执行时间中,哪部分时间用于数据库加锁,哪部分时间用于其他操作(如网络通信、查询解析、数据检索等),需要更详细的内部测量和分析。通常,这种细粒度的性能分析不容易直接通过应用程序代码来实现,因为它涉及到数据库内部的操作细节。不过,有几种方法可以帮助你理解和分析这部分时间:

  1. 数据库的慢查询日志:启用MySQL的慢查询日志,并设置一个非常低的阈值,比如0.001秒。这样,几乎所有的查询都会被记录下来,包括它们的执行时间和是否等待锁。通过分析这些日志,你可以了解到具体的查询是否因为锁等待而变慢。

  2. 性能模式(Performance Schema):MySQL的性能模式是一个强大的工具,用于监控MySQL服务器的运行时信息和统计数据。通过性能模式,你可以获得关于锁等待时间、锁争用情况以及其他性能相关指标的详细信息。这可以帮助你确定查询中的时间是如何分配的。

  3. InnoDB监控:如果你的MySQL使用的是InnoDB存储引擎,那么InnoDB提供的监控工具可以提供锁等待的信息。通过查询INFORMATION_SCHEMA.INNODB_LOCK_WAITS表或使用SHOW ENGINE INNODB STATUS命令,可以获得关于锁等待和锁争用的详细信息。

  4. 专业的性能分析工具:使用专业的数据库性能分析工具(如Percona Toolkit、MySQL Workbench的性能仪表盘等)也可以帮助识别和分析锁等待时间。这些工具通常提供了直观的界面和深入的性能指标,以帮助定位性能瓶颈。

要注意的是,直接从应用程序层面区分查询执行时间的不同组成部分是困难的,特别是区分锁等待时间。通常需要结合数据库层面的监控和分析工具来获得这些细节。

Navicat是一款强大的数据库管理和开发工具,支持多种数据库,包括MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL等。Navicat提供了一系列的功能来帮助用户管理数据库,如数据迁移、备份、恢复、同步、查询构建等。它也包含了一些性能监控和分析的功能,尤其是对于MySQL和MariaDB数据库。

navicat上面有这样的监控和分析工具吗

在Navicat中,你可以利用以下几种方式来监控和分析数据库性能:

  1. 查询分析器:Navicat提供了查询分析器工具,允许用户执行SQL查询并查看执行计划。这有助于理解查询是如何执行的,包括是否利用了索引、是否进行了全表扫描等。虽然这个工具主要是用于优化查询性能,但通过分析执行计划,你可以间接了解到查询性能问题的一些可能原因。

  2. 服务器监控:对于支持的数据库(如MySQL),Navicat提供了服务器监控工具,允许用户实时监控服务器的性能指标,如CPU使用率、内存使用情况、连接数等。这有助于识别系统级别的性能瓶颈。

  3. 慢查询日志:虽然Navicat本身不直接提供慢查询日志的分析工具,但你可以通过它来访问和执行查询在数据库中查看慢查询日志。这对于识别执行时间较长的查询非常有用。

尽管Navicat提供了一些有用的监控和分析工具,但它可能没有专门针对锁等待时间或锁争用情况的直接监控工具。要获取这类更深入的分析,你可能需要结合使用数据库自带的性能分析工具(如MySQL的性能模式)或第三方专业的性能分析工具。

如果你需要进行深入的锁等待分析,可能还需要直接查询数据库的系统表或使用数据库的命令行工具来获取更详细的信息。不过,Navicat作为一个数据库管理工具,仍然可以帮助你执行这些查询和访问这些信息,从而间接地支持你进行性能分析。

问题

不管怎么说,说明数据库的读执行时间是到毫秒级的,这样对于用户量大的系统就会出现一个情况。那就是

如果用串行化,读锁持有时间太长了,太容易死锁。

(串行化读锁持续时间是从读行到事务提交,并且如果有范围锁还会锁掉一定范围内的行防止插行导致幻读,这边提一下串行化不是真串行,是通过严格的锁机制实现的逻辑串行)

如果隔离级别是串行化以下的级别,会存在一个问题。对于读重复级别的隔离,读锁只在事务运行到读指令时上锁。对于可重复读和读指令级别的隔离,写锁在写指令时上锁,在事务提交之后解锁。那么就会出现下图情况。

事务A的读写之间如果有使用读数据进行运算再把结果写入的话,事务C的更新被吞掉了。

一个场景是购买,数据处理是判断是否>0,>0就-1然后写入数据库。假如库存是1。事务A读了库存,解读锁之后,这边在做库存-1。那边事务C也是购买,也给库存-1,可能因为执行事务C的后端进程之前就占用了计算资源没释放,(或者各种原因,反正结果上C这边比A快了,这是很可能发生的)那边没算完这边先算完了,并且写入了0更新了。但是A不知道,A拿到计算资源算完了,也是0,好,把0写入。

结果就出问题了,库存少记录了一次,而且这个库存为1的商品被卖了2个。

这种情况就是一种可重复读的危险情况。

MVCC与可重复读级别

很多2C产品的购买(危险事务)也是不能够串行化的,死锁太多,牺牲性能太多,这时候读提交又不可接受,所以办法就是在这样的危险事务上,牺牲部分性能换取安全性,就是用可重复读级别。

这个级别不是依靠读提交和串行化的锁机制取其轻来实现的,这个级别没有读锁,靠快照实现读,在第一次读的时候直接把数据记录下来,生成快照。

注意MVCC快照特指数据访问层查询数据的某一时间点视图。

还可以在应用层自己做数据快照,就是查询到后端,用后端保存时间点数据备份到内存,后续查询的时候功能一样,但是用不了数据库软件的一些其他功能。

应用层做数据快照

  • 直接控制:应用层可以根据当前业务逻辑和需求,灵活地选择何时以及如何生成数据快照。这种灵活性有助于优化性能,特别是在只需要部分数据快照的场景中。

  • 网络开销:如果应用层与数据存储不在同一台机器上,进行快照操作可能涉及跨网络的数据传输,这可能会导致额外的延迟。

  • 数据一致性:在高并发场景下,应用层生成快照可能需要额外的机制来确保数据的一致性和完整性,特别是当数据来源于多个分布式数据源时。

数据访问层做数据快照

  • 内置支持:很多数据库管理系统(DBMS)提供了内置的快照功能,如多版本并发控制(MVCC)。这些功能可以有效地在数据访问层生成一致的数据快照,而不影响正在进行的写操作。

  • 性能优化:数据库系统通常对于如何存储、访问和快照数据进行了优化。例如,使用MVCC时,数据库可以在不锁定整个表的情况下,提供一个查询时间点的数据视图。

  • 减少网络开销:在数据访问层生成快照,特别是在数据库本身就支持快照的情况下,可以减少或避免跨网络传输大量数据,从而降低延迟。

结论

  • 速度和效率:如果考虑网络延迟,数据访问层(尤其是在数据库系统内部)生成快照可能更高效,因为它可以直接访问数据,且利用了数据库的内置机制。

  • 灵活性和控制:应用层生成快照在某些情况下可能提供更高的灵活性和控制,尤其是当涉及到复杂的业务逻辑时。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1508147.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Intel@cpu产品参数和命名@单核睿频和全核睿频

文章目录 选择合适的cpuintel cpu型号和命名小结 cpu排行时钟速度睿频单核睿频和全核睿频网络上流传的方法 在线查询 产品比较跑分比较 选择合适的cpu 如何选择游戏 CPU - 英特尔 (intel.cn)在决定购买具体的产品之前,建议广泛地查阅用户对它的评价以及是否有哪些因素是不满足…

AI时代,AI智能交互数字人赋能公共服务降本增效

人工智能时代,AI交互数字人技术不断在冲击公共服务领域。越来越多公共服务领域开始在自身业务中运用AI智能交互数字人,通过布局AI交互数字人应用于代言人、推荐官、客服、主播等诸多领域。 近年来,数字人技术正在成为引领数字化时代营销的重…

常用云产品连接

阿里云常用云产品 云服务器 阿里云:云服务器ECS_云主机_服务器托管_计算-阿里云 对象存储 阿里云:对象存储 OSS_云存储服务_企业数据管理_存储-阿里云 短信服务 阿里云:短信服务_企业短信营销推广_验证码通知-阿里云 CDN服务 阿里云&…

mysql日常优化的总结

文章目录 一、数据表结构相关优化建字段类型注意事项1. int类型的选择2.varchar、char、text类型3.date、datetime、timestamp类型 表规划1. 垂直分表2. 水平分表 二、查询语句优化1.对于字段多的表,避免使用SELECT *2.避免使用!操作符3.避免使用null做条件4.like查…

李彦宏:程序员会消失;拜登谈TikTok撤离;李想终就MEGA风波表态;英伟达紧急处理全球范围故障;刘作虎:AI手机非噱头

一、商业圈 1.阿里包揽中国估值最高的5家大模型独角兽 在对AI大模型初创企业的投资竞赛中,阿里巴巴已成为中国互联网巨头中最大的投资者目前,中国一级市场上估值最高的5家A大模型初创公司,阿里均参与投资,并在2-3家公司中可能是…

pip 和conda 更换镜像源介绍

1、前言 很多深度学习的项目免不了安装库文件、配置环境等等,如果利用官方提供的连接,网速很慢,而且很容易download掉。 所以配置好了虚拟环境,将pip换源属实重要 常见的国内镜像源有清华、中科大、阿里等等... 这里建议用中科…

抖音视频提取gif怎么做?分分钟帮你生成gif

通过将视频转换成gif动图的方式能够方便的在各种平台上分享、传播。相较于视频文件,gif动图的体积更小,传播起来更方便,能够吸引大众的注意力。下面,就来给大家分享一个gif图片制作(https://www.gif.cn/)的…

记录一个编译的LLVM 含clang 和 PTX 来支持 HIPIFY 的构建配置

llvm 18 debug 版本 build llvmorg-18.1rc4 debug $ cd llvm-project $ git checkout llvmorg-18.1.0-rc4 $ mkdir build_d $ cd build_d $ mkdir -p ../../local_d cmake \ -DCMAKE_INSTALL_PREFIX../../local_d \ -DLLVM_SOURCE_DIR../llvm \ -DLLVM_ENABLE_PROJECTS&…

WorkPlus Meet提供高效、安全视频会议解决方案

WorkPlus Meet是一款私有部署和定制化的视频会议解决方案,为企业提供高效、安全的远程协作平台。随着全球数字化转型的加速,视频会议已成为企业必不可少的工作工具,而WorkPlus Meet的私有部署和定制化功能,为企业提供了更大的控制…

【leetcode热题】排序链表

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。 示例 1: 输入:head [4,2,1,3] 输出:[1,2,3,4]示例 2: 输入:head [-1,5,3,4,0] 输出:[-1,0,3,4,5]示例 3: 输入…

14:00面试,14:10就出来了,问的问题有点变态。。。

从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到3月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%,…

有没有能用蓝牙的游泳耳机?四款好评如潮的游泳耳机速来围观

在如今的快节奏生活中,音乐已经成为了我们日常休闲和运动时的重要伴侣。尤其对于水上运动爱好者来说,一款好的游泳耳机更是必不可少。它不仅能让我们在水中畅享音乐,还能有效隔绝外界噪音,让我们更加专注于自己的运动。 &#xf…

鸿蒙开发为什么这么火,现在入行鸿蒙是否来的及?

鸿蒙开发是当前备受关注的技术领域之一,对于想要入门学习鸿蒙开发的初学者来说,需要掌握一定的基础知识和技能。鸿蒙开发又是否能为程序员们带来一片光明的未来呢?让我们一同探讨这些问题。 对于初学者来说,鸿蒙开发是否易于上手呢…

300分钟吃透分布式缓存-22讲:怎么认识和应用Redis内部数据结构?

Redis 内部数据结构 RdeisDb Redis 中所有数据都保存在 DB 中,一个 Redis 默认最多支持 16 个 DB。Redis 中的每个 DB 都对应一个 redisDb 结构,即每个 Redis 实例,默认有 16 个 redisDb。用户访问时,默认使用的是 0 号 DB&…

C语言实现贪吃蛇

前言:今天给大家详细介绍一下小游戏贪吃蛇的代码。 目录 一 .贪吃蛇实现的功能 二.贪吃蛇游戏设计与分析 1.贪吃蛇以及贪吃蛇所需要维护的数据 (1)贪吃蛇蛇体 (2)数据维护 2.地图设计 (1&#x…

【三十】springboot项目上高并发解决示例

互相交流入口地址 整体目录: 【一】springboot整合swagger 【二】springboot整合自定义swagger 【三】springboot整合token 【四】springboot整合mybatis-plus 【五】springboot整合mybatis-plus 【六】springboot整合redis 【七】springboot整合AOP实现日志操作 【…

【Python】一文详细介绍plt.rcParams 在 Matplotlib 中的原理、作用、注意事项

【Python】一文详细介绍plt.rcParams 在 Matplotlib 中的原理、作用、注意事项 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x…

导出谷歌浏览器收藏的网页,并查看网页保存的登录密码

导出谷歌浏览器(Chrome)收藏的网页(书签): 打开谷歌浏览器。在浏览器右上角找到并点击三个垂直排列的小点(或称汉堡菜单)以打开主菜单。在下拉菜单中选择“书签” > “书签管理器”。在书签…

NodeJS实现线性查找算法

NodeJS实现线性查找算法 以下是使用 Node.js 实现线性搜索算法的示例代码&#xff1a; function linearSearch(arr, target) {for (let i 0; i < arr.length; i) {if (arr[i] target) {return i; // 如果找到目标&#xff0c;返回索引}}return -1; // 如果未找到目标&am…

Android随手记

activity的生命周期 创建时 onCreate() - onStart() - onResume() - onPause() - onStop() - onDestroy() 切换时 a切换到b a.onCreate() - a.onStart() - a.onResume - a.onPause - b.onCreate() - b.onStart() - b.onResume() - a.onStop() b切换回a b.onPause() - a.onR…