MySQL存储引擎介绍以及InnoDB引擎结构理解

news2024/11/15 6:10:35

目录

    • 存储引擎概述
    • 各个存储引擎介绍
      • InnoDB
      • MySIAM
      • Memeory
      • 其他引擎
    • 引擎有关的SQL语句
    • InnoDB引擎
      • 逻辑存储结构
      • 架构
        • 内存部分
        • 磁盘部分
        • 后台线程
        • InnoDB三大特性

存储引擎概述

数据引擎是与数据真正存储的磁盘文件打交道的,它的上层(服务层)将处理好的SQL指令(SQL处理分析结果)交给数据引擎,数据引擎按照指令或将数据存储在磁盘文件,或将磁盘文件数据进行读取。所以说数据引擎是整个DBMS的核心,它有着最本质的功能:读取数据,存储数据。

存储引擎也可以看做是表的类型(存储引擎原名表处理器),因为不同的表可以选择不同的存储引擎,不同的存储引擎数据处理方式、表的结构,文件形式等也不同

MySQL的数据存储引擎采用的是可插拔式的,即可以任意切换。数据存储引擎作用单位是表,每张表可以选择一个合适的存储引擎。
MySQL5.5版本后默认的存储引擎是InnoDB引擎(之前是MyISAM),它相较与其他数据引擎有非常多的优势(具体优势后面会说),所以除极特殊的场景外,都常建议每张表都使用默认的存储引擎InnoDB

SQL语句的大致执行流程
在这里插入图片描述
当我们想要操作数据库时,首先要对数据库服务进行一个连接,使用图形化客户端也好,还是命令行也好,总之要想能够连接都需要连接层提供连接,认证,授权等服务。
连接好后,我们能够输入SQL进行操作,这时服务层会对我们输入的SQL语句进行语义、语法的检查,创建语法解析树,并进行自动的优化(5.7版本之前还要查询缓存,如果缓存中有,直接返回缓存结果。因为命中率过低,8版本后已经废弃)。然后将处理数据交引擎层
引擎层就负责按照对上一层的结果对数据进行存储或抽取等
存储层是真正对数据,日志进行存储的,与引擎层来管理它们

各个存储引擎介绍

可以通过命令行 show engines查看MySQL支持的所有命令行
在这里插入图片描述
如图,可以看出MySQL共支持8种类型的数据存储引擎,默认使用的是InnoDB引擎,它的最大特点是支持事务以及分布式事务,支持行级锁,支持外键
每个引擎都有各自的特点,因为是开源的,所以大的公司可根据具体业务对引擎进行定制
在数据库中最重要的就是 InnoDB引擎和MyISAM引擎,他俩各有各自的优劣势,不是替代关系,一个现版本使用的引擎,一个是老版本使用的引擎

InnoDB

MySQL3.2版本后出现此引擎,MySQL5.5版本后作为默认存储引擎

InnoDB的优点

  1. InnoDB引擎支持外键,但外键会带来性能问题
  2. InnoDB引擎支持事务(十分重要),引入了提交和回滚两个操作。对于重要的数据,有了事务能够确保数据的ACID(原子性、一致性、隔离性、持久性)。在崩溃后,能够自行恢复,对没有提交的数据进行回滚。
  3. InnoDB支持行级锁。在多线程并发时,为了解决线程安全问题,要进行上锁。其他引擎通常是表级锁,二InnoDB可以在具体操作的行进行上锁,这样就不影响整张表其他数据的并发操作,提高并发效率。因此,在数据量大,并发量高时特点尤为突出

InnoDB的特点

  • 在MySQL8之前,表的存储文件分为两类:表结构.frm,表数据和索引.idb;在MySQL8版本之后,表结构,表数据,表索引都放入一个文件.idb进行存储。
  • InnoDB的主键索引在叶子节点中存储的是整条数据

InnoDB相较于MyISAM的缺点

  • 批量查询不如MyISAM
  • 对内存占用高:因为InnoDB是将数据与索引放在一起,在加载叶子页时也要加载此页的数据。而MyISAM加载的是此页数据的地址地址就相对于数据节省很多空间,这就使得InnoDB对内存的要求更高。

InnoDB不支持hash索引,但会引擎内部根据查询自动优化创建自适应hash索引,不能够人为干预
在新增大量数据时,可先将表中索引全部删除,进行批量添加后再重新创建,这样可以使得在添加时不用去维护索引,提升效率

MySIAM

MySIAM的优点

  • 访问速度更快
  • count(*)效率更高O(1)级别,因为有变量进行统计计算,而InnoDB是用到去逐个查O(n)级别

MySIAM相较于InnoDB的缺点:

  • 不支持外键,事务,行级锁(MyISAM是表级锁)

MySIAM处理适用于小型,并发量不高(因为表锁影响并发),对数据没有完整性要求的(因为不支持事物,但性能高),查询和增加远远高于修改和删除的表,能够节省内存资源,访问效率更高 (绝大多数场景建议使用InnoDB数据引擎)

Memeory

  • 表结构在磁盘存储, 表数据在内存存储, 因为是在内存,所有速度更快,但也受到内存大小的限制,使得不能存放大量数据
  • 默认索引结构是hash索引,该索引的特点是在定位某条数据时十分的快速,但范围查找时,就不如B+树索引。
  • 受到内存大小、断电等物理因素影响,只能用于存储临时的数据或用作缓存。但这些特性又有其他的服务器软件代替它,如Redis。所以较少使用。

三个引擎的对比

特点InnoDBMyISAMMemeory
事务支持不支持不支持
外键支持不支持不支持
锁级别行级锁表级别表级别
B+树索引支持支持支持
hash索引不支持,但内部优化会创建且无法干预不支持支持(默认)
插入速度快(内存级别)
内存使用中(索引结构)高 (数据放在内存存储)
使用场景大量数据,并发写,有事务的要求小数据,节省资源消耗,业务简单,数据没有事务要求数据量少,不在意数据安全性,对性能要求高

使用关系型数据库主要就是因为其具有的事务的特性能够使得数据更加安全,如果数据不需要事务的特性,那么也会先考虑使用NoSQL来代替。

其他引擎

  • Archive:为大量很少引用的历史、归档、或安全审计信息的存储和检索提供了完美的解决方案。不支持索引,不支持更新,支持行级锁。适合插入一次再也不进行修改且查询也较少的数据。
  • CSV引擎: 可以将csv文件作为mysql的表进行处理。存储格式就是普通的csv文件
    等其他极少用到的引擎

引擎有关的SQL语句

  • 查看当前系统默认的存储引擎 show variables like '%storage_engine%';
    在这里插入图片描述
  • 修改系统默认存储引擎 SET DEFAULT_STORAGE_ENGINE=引擎名称; 这样设置在服务器重启后又会恢复为原来设置,可以在SQL的配置配置文件 my.cnf进行修改
    在这里插入图片描述
  • 创建表时指定表的存储引擎,不指定采用默认的存储引擎 CREATE TABLE 表名( 建表语句; ) ENGINE = 存储引擎名称;
  • 修改表的存储引擎 ALTER TABLE 表名 ENGINE = 存储引擎名称;

InnoDB引擎

推荐阅读

逻辑存储结构

InnoDB引擎共分为5级结构:按照从大到小依次是 表空间、段、区、页、行
表空间
表空间是InnoDB逻辑存储的最高结构,又分为系统表空间、独立表空间、通用表空间、临时表空间、Undo表空间
MySQL8后默认每张表的数据以及索引都会存在一个独立的表空间中(结构仍放在系统表空间),在磁盘使用单独的xx.ibd文件存放。可以通过innodb_file_per_table进行设置,如果将其设置为0,则每张表的数据都会放入系统表空间ibdata1


段又分为数据段,索引段,回滚段等。一个表的数据以及索引放入一个表空间中,在一个表空间中,索引与数据也是分为不同的段进行存储的。根据索引B+树的结构,数据段存放的是索引树叶子节点,索引段存放是索引树中的非叶子节点
一个段的空间是随着表的大小扩展的,表有多大,段就有多大。一个段至少包含一个区,段的最小扩展单位就是区。

一个区大小默认为1M,即64个连续页。在进行区扩展时,为了确保页的连续性,尽量避免随机IO,每次会从磁盘申请4~5个区。

每个页的大小默认为16K,正好是Linux页大小的4倍,InnoDB中页是磁盘与内存交互的最小单位,操作系统会分4次将进行读取或写入
索引树上每一个节点都是一个页,一个页上至少存储2个数据项。如果向一个已满的数据页中顺序插入数据,就会从区中重新分配一个新页。如果是从索引树中间插入一个数据,这个页满了就会发生页分裂。

  • 页分裂
    叶子中行数据的存储一定是按照顺序进行存储的,如果是乱序插入,如果插入到一个已满的页,就会发生页分裂。思考?为什么不插入新的页中?因为数据的存储是有顺序的。如何避免页分裂呢?不向中间已满的数据页插入数据,即有序插入。
    在这里插入图片描述
    直接从满的页中间分开,分为两个页,自己按照顺序插入一个页中
    在这里插入图片描述
    分裂后,页就留有空余,再将要插入的数据插入
    在这里插入图片描述
    最后再将新开辟的页按顺序连接,注意是InnoDB引擎对bB+树做了优化,页和页是双向连接
    在这里插入图片描述
    页分裂导致会有大量的页剩余,浪费空间。页分裂耗费性能,所以在插入数据时尽量要按照顺序进行插入

  • 页合并
    当数据删除时,InnoDB引擎只是做了一个标记,当一个页中删除数达到页的50%,就会寻找前后的页判断是否可以进行合并使用。
    在这里插入图片描述
    将两个不满页进行合并
    在这里插入图片描述

    行中存储的就是表中的数据行,每一行的存储大小取决于表的字段设计和行中数据大小
    InnoDB是以 为单位存储的,一个页中包含多个行。

总结
在这里插入图片描述

架构

在这里插入图片描述

InnoDB引擎由内存池,后台线程,磁盘文件三部分组成。

内存部分

在这里插入图片描述
由图中来看,内存主要由4部分构成 分别是 Buffer PoolChange bufferLog BufferAdaptive Hash Index

Buffer Pool:
首先注意:Buffer pool与查询缓存不是一个东西(因为我开始时,就对这个混淆了)
查询缓存:当服务层收到要执行查询类的SQL时,先去内存的查询缓存中去寻找是否有该SQL的缓存的结果,如果没有再经过语义语法解析等,最终交给引擎层去处理。 而Buffer Pool就是在引擎层面的。且这种查询缓存十分的不智能,也就是虽然是同一个语义的SQL,有略微改动(如加个空格)就查找不到上一次SQL的缓存,命中率十分低下,已经在MySQL8版本去除。
为什么要引入Buffer Pool
各种数据以及索引都是以页的形式放在表空间中的,表空间也是磁盘上文件的抽象。也就是说数据是放在磁盘中的。
而磁盘速度与内存有鸿沟,在访问某个数据时,是将数据所在的整个页加载到磁盘中,这样效率会有巨大的提升。但访问后,并不立即把页刷回磁盘,一是这样频繁刷盘随机IO大大的影响性能,二是,内存中数据可能还会用上,免得再次去读取。
Buffer Pool介绍
Buffer Pool默认的大小是128M,越大内存数据越多,去查询磁盘的概率越小,性能就越高,所以在设备允许的情况下,是越大越好的。是可以存在多个Buffer Pool的,默认是一个,也可以修改其个数。
缓冲池是以页为单位的,每页大小与磁盘大小一致是16K,按照页的功能分为:索引页数据页,undo 页,插入缓存,自适应哈希,锁信息等
按照页的状态又分为:

  • free page:空闲页,内存中未被使用的页
  • clean page:从磁盘加载到内存数据后,页中未被修改与与磁盘一致的页
  • dirty:页中数据被修改,还未刷新到磁盘的页,也就是内存数据与磁盘不一致的页
    MySQL使用的内存中,通常将80%多的空间给缓冲池,其大小将直接影响整体的性能。当内存不够时,InnoDB引擎采用LRU页面置换算法即最近时间最少使用,将最近没有用到的页从磁盘中移出,刷新到磁盘。但InnoDB引擎是对LUR算法进行了优化,例如:select * ,会进行全表扫描,这就使得不常用的数据被扫描到,成为最新使用数据。而InnoDB引擎就是对这种情况进行了优化。

Changer Pool:又叫插入缓冲池,是针对非主键索引插入的优化,因为主键通常都要按顺序插入,在主键索引树的重新建立索引时较为方便。(只需叶子节点按需添加即可)。而在插入时,如果建立了非主键索引,不仅需要向主键索引树插入,还要向非主键索引树中插入。对于非主键索的索引key往往插入时是无序的,离散的访问非主键索引,随机IO会导致性能下降。使用change pool,在插入非主键索引时,先判断在插入时用到的索引树的页是否在内存中,存在则直接插入,不存在则在磁盘读取后,将对应索引页放入内存中,再插入。在读取数据时,将Change Buffer与 Buffer Pool进行合并,Buffer Pool再以一定频率刷新到磁盘
例如:要插入一条 id=2,name=‘zs’的数据,id为主键索引,name为普通索引。在插入数据时,id是有序的直接插入主键索引页中即可,而插入name时,名字通常是无序的,这就需要将部分索引放入插入缓冲池中,先在changer Pool中进行插入,最终再以一起刷新到磁盘。提高非主键索引的插入性能


自适应哈希索引 AHI:引擎自动为热点页建立一个哈希索引,是以为单位的。因为hash索引在没有hash碰撞的情况下,只需要一次就可以访问到数据,而B+树主键索引通常需要1~3次才可以。但是hash索引不支持范围查询,这就需要引擎判断情况为适合的数据建立hash索引,无需人为干预


logo buffer:日志缓冲区,像redo日志的内存部分就在这里,默认大小为16M,内存中的数据会以指定的频率刷新到磁盘,共有三种选择。第一种是共有的,每隔1s刷新到磁盘;第二种是在事务提交后刷新到磁盘,同时兼用第一种。第三种是事务提交后,交给系统缓存页,由系统指定时机刷新到磁盘,同时兼用第一种。

磁盘部分

在这里插入图片描述
磁盘结构重要有以下几部分:

  • System tablespace:系统表空间
    系统表空间可以有一个或多个数据文件。默认情况下,在数据目录中创建一个名为 ibdata1 的系统表空间数据文件。
    系统表空间包含 数据字典(包含元数据),双写缓冲区(8版本后没有存储区),变更缓冲区、undo日志,以及在系统表空间创建的表的数据和索引(不在系统表空间创建则保存在独立表空间)。

  • File-Per-Table Tablespaces :独立表空间
    每张表默认使用独立表空间,存储数据和索引,对应磁盘上一个单个.idb文件

  • General Tablespaces :通用表空间
    是共享的表空间,可以存储多个表

  • redo log
    redo 的两个循环写文件 ib_logfile0和ib_logfile1

后台线程

是线程往来于内存与磁盘之间,进行相应调度,提供数据服务
主要分为 Master Thread,IO Thread,Purge ThreadPage Cleaner Thread

Master Thread
核心后台线程,负责其他线程的调度,还负责合并 buffer poolchange buffer的合并、脏页落盘,回收undo页等
IO Thread
在这里插入图片描述
Purge Thread
主要是 回收事务提交后的undo log日志,减少Master 线程压力
page Cleaner Thread
将内存中的脏页数据刷新到磁盘,减少Master 线程压力

InnoDB三大特性

推荐文章
InnoDB的三大特性分别是double writeBuffer pool自适应哈希索引
后两个上面已经介绍,这里只介绍双写机制。
为什么称之为双写呢? 因为在内存中一份数据先是顺序写入磁盘中双写缓冲区,确定写入成功后,在将内存中同样的数据离散写入对应表空间中。

为什么要有双写机制呢?
先来说 双写机制带来的坏处:将同样的数据写入磁盘两次,多进行了一次IO,虽然是顺序写入,但多了一次IO,使得整体性能下降了5~10%。
再来说为什么引入了双写机制?根本原因就是解决内存数据在刷新磁盘过程中的页损坏问题,也就是部分写问题
页损坏问题:InnoDB引擎是以页为单位的,每页大小为16K,操作系统(Linux)也是以页为单位的,但它的大小是4K,也就是说当内存中的数据要想刷新到磁盘,要先交给操作系统页,由操作系统页去刷新到磁盘。这就代表内存数据每刷新一页,就要分4次写入操作系统。但如果在这4次中发生宕机等意外,导致内存中有一个不完整的页写入了磁盘,导致页损坏(部分写问题)。这时,也不能违背持久性原则,那因为宕机等没有正确写入磁盘的数据怎样进行恢复呢?
首先,我想到的就是确保内存数据写入磁盘的还有一个redo日志。但是redo log记载的是什么?是物理记录,即xxx页偏移量为xxx的地址数据为xxxx,但没有写完整导致宕机记载的页已经损坏!,页损坏了,相当于对应页地址的数据记录也无效了。因此redo无法使用
binlog呢?binlog的功能时数据备份和主从复制,它根本不关注内存与磁盘数据之间即它无法区分哪些是已写入磁盘,哪些是在脏页。
要是进行全量恢复,貌似还可以。但代价也太大了,是不现实的事。
这时就引入了双写机制,即不先操作redo log记载的页,这样就能防止在写入过程中发生意外后,导致redo 记载的页发生损坏使得无效。
那么先把数据写入哪里呢?写入的地方一定要是磁盘中,否则没有意义。因为做的的就是内存与磁盘间交互备份。
InnoDB引擎给出的是顺序先写入系统表空间中,成功后离散写入对应独立表空间。InnoDB还为double write的写入速度做了优化,因为这样写入是顺序写入,多了一个IO操作,也尽量减少其带来的性能损耗。
以上就是为什么要引入双写机制


Double write文件
有了这个机制肯定有对应的存储文件。
双写缓存去共有部分,一部分在内存,一部分在磁盘。每部分都固定为2M
双写缓冲区是磁盘表空间上的128个页,即两个区每个区1M,共2M。当Buffer Pool数据进行复制时,要先将数据复制到双写缓存的内存部分,再由内存部分分两次,每次以1M大小先顺序写入磁盘部分的双写文件,写入成功后,再将同样的数据离散写入对应的独立表空间中。


当内存触发了checkponit机制后,开始将部分页写磁盘。具体流程如下:

  1. 将要写入的脏页进行在内存中进行复制,复制到 double write内存部分
  2. double write 内存部分每次写入1个区即1M,分两次顺序写入系统表空间部分
  3. 确定写入成功后, double write内存部分再将同样的数据离散写入对应的独立表空间

如果在双写过程发生意外呢
第一写发生意外:第一次是将内存数据(double write 内存缓存区)写入系统表文件中进行备份
如果此过程发生意外,但redo记载的页没有发生损坏,可以使用redo直接进行恢复
第二次写发生意外:第二次写入是将内存数据(double write 内存缓存区)写入对应的独立表空间中
写入磁盘发生意外会导致页损坏,这时redo记载的页也无效。但有了系统表空间的文件,系统在重新启动,会检查过程页是否完好,发现页损坏会从系统表空间中进行恢复
redo页是不可能发生意外的, 因为只有redo页写入成功后,事务才算完成。

例: 有一张user表,id为主键,name为普通索引,age为普通字段。 当我连接MySQL并开启事务向中user表将 name为’zs’的用户age修改为10并提交时,MySQL内部的大致流程:
MySQL的连接层创建与客户端建立连接,将SQL语句进行语法语义检查后,交给引擎层。发现此张表的引擎是InnoDB引擎,InnoDB 引擎将从Buffer Pool中寻找name为‘zs’的用户,没有找到再去通过非聚簇索引将name作为索引值查找到此行数据的id,在通过id去聚簇索引中查找到此行数据所在的页(在xxx.ibd文件中) 将其加载到Buffer Pool中,并将此行上写锁、MDL锁等(这个过程有来读取此行数据的就MVCC机制)。同时将数据中的undo log指针指向此事务开启前的undo log记录,同时开启新的undo log。然后在Buffer Pool中将age修改为10,此时redo 记载着磁盘地址中数据的修改,undo记载着如何恢复原记录操作,binlog记载着用户的命令操作,当事务提交后,redo、binlog立即将缓冲区内容刷新到磁盘,undo交给Purge Thread线程回收。但内存中修改的数据可能并未刷新到磁盘,当有其他数据来读取时,直接返回Buffer Pool中的数据。当此数据的脏页触发了cheakPoint机制,此时会将此脏页从Buffer Pool中复制到double writer 内存缓冲区,内存中先将数据分两次写入到系统表中,当确定写入成功后,在将内存中的数据写入对应的页。对应的redo log记录无用,将被新的数据覆盖。

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

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

相关文章

我的Python学习笔记:私有变量

一、私有变量的定义 在Python中,有以下几种方式来定义变量: xx:公有变量_xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入__xx:双前置下…

掌握Python中列表生成式的五个原因

1. 引言 在Python中我们往往使用列表生成式来代替for循环,本文通过引入实际例子,来阐述这背后的原因。 闲话少说,我们直接开始吧! 2. 简洁性 列表生成式允许我们在一行代码中创建一个列表并对其元素执行相应的操作&#xff0…

(十五)大白话我们每一行的实际数据在磁盘上是如何存储的?

文章目录 1、前情回顾2、真实数据是如何存储的?3、隐藏字段4、初步的把磁盘上的数据和内存里的数据给关联起来1、前情回顾 之前我们已经给大家讲过了,一行数据在磁盘文件里存储的时候,包括如下几部分: 首先会包含自己的变长字段的长度列表然后是NULL值列表接着是数据头然后…

图的概念及存储结构

文章目录图的概念图(graph)有向图(directed graph)无向图(undirected graph)加权图(weighted graph)无向完全图(undirected complete graph)有向完全图(directed complete graph)子图(subgraph)稀疏图与稠密图度路径与回路连通图与连通分量强连通图与强连通分量生成树图的存储结…

STM32H750自制开发板调试经验

​本篇只是一个记录,没啥可看的。 STM32H750硬件相关 STM32H750可以通过USB-OTG下载程序,也可以使用SWD进行调试,所以设计板子得时候将PA13和PA12预留出来即可,后续也可以用作usb虚拟串口(CDC)功能或者模拟…

stm32f407VET6 系统学习 day08 利用adc 模数转换 监控光敏电阻。

1. ADC 的知识 1.基本概念 : Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件 。典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。 2.STM32F4x ADC特点 1. 可配…

git操作

删除暂存区文件: git rm --cached 完整文件名 git rm --cached xxx.txt这个删,只是把暂存区里的文件删了,工作区里面的没有删 把本地文件添加到暂存区 git add完整文件名 例如:git add xxx.txt git add xxx.txt此时xxx.txt已经…

Linux 权限理解和学习

✨个人主页: Yohifo 🎉所属专栏: Linux学习之旅 🎊每篇一句: 图片来源 🎃操作环境: CentOS 7.6 阿里云远程服务器 Don’t argue with the people of strong determination, because they may ch…

AtCoder Beginner Contest 283 Ex. Popcount Sum(类欧经典问题:数x在二进制表示下第k位的值)

题目 t(t<1e5)组样例&#xff0c;每组样例给定n,m,r(1<m<n<1e9,0<r<m) 求[1,n]这n个数中&#xff0c;所有满足i%mr的数i的二进制的1的个数之和 即&#xff1a;&#xff0c; 其中&#xff0c;__builtin_popcount(i)统计的是i的二进制表示中&#xff0c;1的…

Web APIs

文章目录一. Web API介绍1. Web APIs 和 JS 基础关联性1.1 JS 的组成1.2 JS 基础阶段以及 Web APIs 阶段2. API的概念[3.Web API的概念](https://developer.mozilla.org/zh-CN/docs/Web/API)4. API 和 Web API 总结二. DOM 介绍1. DOM 简介1.1 什么是 DOM1.2 DOM 树2. 获取元素…

Linux-6 三剑客命令

Linux-6 三剑客命令 awk&#xff08;取列&#xff09; 将系统的IP地址打印出来 [rootdestiny ~]# yum install net-tools -y #分析&#xff1a;#1.肯定是需要拿到IP地址&#xff0c;仅看某一个特定的网卡&#xff1b;ifconfig#2.先想办法过滤出数据的那一行&#xff1b; ###行#…

5)Django Admin管理工具,Form组件,Auth

目录 一 Django Admin管理工具 激活管理工具 使用管理工具 复杂模型 自定义表单 内联(Inline)显示 列表页的显示 二 django Form组件 局部钩子和全局钩子 三 Django 用户认证&#xff08;Auth&#xff09;组件 一 Django Admin管理工具 Django 提供了基于 web 的管理…

年终报告撰写小技巧,你学会了吗?

年年岁岁花相似&#xff0c;岁岁年年人不同。 临近年底&#xff0c;又到了一年一度的年终报告时段了。同事间见面最让人头疼的问候&#xff0c;莫过于&#xff0c;“你的年终报告写了吗&#xff1f;” 有的人东拼西凑、应付了事&#xff0c;汇报内容乏善可陈&#xff0c;领导…

美美的圣诞树画出来-CoCube

2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ CSDN诚邀各位技术er分享关于圣诞节的各种技术创意&#xff0c;展现你与众不同的精彩&#xff01;参与本次投稿即可获得【话题达人】勋章【圣诞快乐】定制勋章&#xff08;1年1次&#xff0c;错过要等下一年喔&#…

尚医通-上传医院接口实现(十八)

目录&#xff1a; &#xff08;1&#xff09;上传医院接口-基础类的创建 &#xff08;2&#xff09;数据接口-上传医院接口-初步实现 &#xff08;3&#xff09;上传医院接口-最终实现 &#xff08;1&#xff09;上传医院接口-基础类的创建 复制相关的工具类&#xff1a;这…

Redis Windows版安装和使用

下载地址&#xff0c;亲已测试可放心使用 https://github.com/tporadowski/redis/releases Redis安装和基本使用&#xff08;windows版&#xff09; 1.Redis简介 完全开源免费的高性能的key-value的数据库 支持数据的持久化&#xff0c;可以将内存中的数据保存在磁盘中&…

【函数】一篇文章带你看懂控制流、递归、高阶函数

目录 控制流 条件语句 迭代语句 示例&#xff1a;质因数分解 递归 示例&#xff1a;阶乘 示例&#xff1a;斐波那契数列 示例&#xff1a;判断奇偶数 高阶函数 lambda 表达式 设计函数 示例&#xff1a;累加计算 示例&#xff1a;柯里化 Lab 1: Functions, Control …

个人能用的短信平台有哪些?看这一篇就够了

对于程序员个人来说&#xff0c;在做开发或者是接项目的时候&#xff0c;常常会用到发送短信功能模块&#xff0c;而自己写这个模块会要相当多的精力和时间&#xff0c;去找短信平台来解决问题&#xff0c;已经成了不少程序员的共识。 但市面上的短信平台确实很杂&#xff0c;鱼…

服务注册与发现原理

一、什么是服务注册与发现&#xff1f; 服务注册与发现就是一套管理微服务的组件&#xff0c;方便各拆分的服务平滑上线和下线&#xff0c;以及某个服务出现故障自动剔除。其实质就是维护一张记录各在线服务的表。让消费服知道服务在线可以请求。。。。。。 二、服务注册与发现…

SQL限制

SQL限制目录概述需求&#xff1a;设计思路实现思路分析1.URL管理参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,challenge Survive. happy…