In-Memory:内存数据库

2023-11-18

在逝去的2016后半年,由于项目需要支持数据的快速更新和多用户的高并发负载,我试水SQL Server 2016的In-Memory OLTP,创建内存数据库实现项目的负载需求,现在项目接近尾声,系统运行稳定,写一篇博客,记录一下使用内存数据库的经验。

SQL Server 2016的In-Memory OLTP,通俗地讲,是内存数据库,使用内存优化表(Memory-Optimized Table,简称MOT)来实现,MOT驻留在内存中,使用 Hekaton 内存数据库引擎访问。在查询MOT时,只从内存中读取数据行,不会产生Disk IO消耗;在更新MOT时,数据的更新直接写入到内存中。内存优化表能够在Disk上维护一个数据副本,该副本只用于持久化数据,不用于数据读写操作。

在内存数据库中,不是所有的数据都需要存储在内存中,有些数据仍然能够存储在Disk上,硬盘表(Disk-Based Table,简称DBT)是传统的表存储结构,每个Page是8KB,在查询和更新DBT时,产生Disk IO操作,将数据从Disk读取到内存,或者将数据更新异步写入到Disk中。

内存数据库将原本存储在Disk上的数据,存储在内存中,利用内存的高速访问优势实现数据的快速查询和更新,但是,内存数据库,不仅仅是存储空间的变化,Hekaton 内存数据库访问引擎实现本地编译模块(Natively compiled),交叉事务(Cross-Container Transaction)和查询互操作(Query Interop):

  • 本地编译模块:如果代码模块只访问MOT,那么可以将该模块定义为本地编译模块,SQL Server直接将TSQL脚本编译成机器代码;SQL Server 2016支持本地编译的模式有:存储过程(SP),触发器(Trigger),标量值函数(Scalar Function)或内嵌多语句函数(Inline Multi-Statement Function)。相比于解释性(Interpreted)TSQL 模块,机器代码直接使用内存地址,性能更高。
  • 交叉事务:在解释性TSQL模块中,一个事务既能访问硬盘表,也能访问内存优化表;实际上,SQL Server创建了两个事务,一个事务用于访问硬盘表,一个事务用于访问内存优化表,在DMV中,分别使用transaction_id 和 xtp_transaction_id 来标识。
  • 查询互操作:解释性TSQL脚本能够访问内存优化表和硬盘表,本地编译模块只能访问内存优化表。

内存数据被整合到SQL Server关系引擎中,使用内存数据库时,客户端应用程序甚至感受不到任何变化,DAL接口也不需要做任何修改。由于Query Interop的存在,任何解释性TSQL脚本都能透明地访问MOT,只是性能没有本地编译TSQL脚本性能高。在使用分布式事务访问MOT时,必须设置合适的事务隔离级别,推荐使用Read Committed,如果发生MSSQLSERVER_41333 错误,说明产生交叉事务隔离错误(CROSS_CONTAINER_ISOLATION_FAILURE),原因是当前事务的隔离级别太高。

一,创建内存数据库

内存优化表的数据必须存储在包含Memory_Optimized_Data的File Group中,该FileGroup可以有多个File,每个File实际上是Folder,一个DB只能创建一个包含Memory_Optimized_Data的File Group。

step1,创建一个数据库,创建的Data File的数量最好和CPU内核数量保持一致,存放在不同的物理磁盘上;

use master 
go 

--Create database
create database Test_MemboryDB
on Primary
(
name=Test_MemoryDB_1,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_1.mdf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_2,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_2.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_3,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_3.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_4,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_4.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_5,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_5.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_6,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_6.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_7,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_7.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_8,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_8.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_9,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_9.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_10,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_10.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_11,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_11.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_12,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_12.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_13,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_13.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_14,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_14.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_15,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_15.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_16,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_16.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_17,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_17.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_18,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_18.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_19,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_19.ndf',
size=5GB,
FileGrowth=1GB
),
(
name=Test_MemoryDB_20,
filename='D:\Program Files\Microsoft SQL Server\Test_MemoryDB_20.ndf',
size=5GB,
FileGrowth=1GB
)
LOG ON 
( 
name = N'Test_MemboryDB_log', 
filename = N'D:\Program Files\Microsoft SQL Server\Test_MemboryDB_log.ldf' , 
size = 10GB , 
filegrowth = 1GB 
)
GO
View Code

step2,为数据库创建一个包含内存优化数据的FileGroup,向该FileGroup中添加“File”,实际上是目录(Directory),用于存储内存优化数据文件,主要是CheckPoint文件,用于还原持久化的内存优化表。

-- Add File Group from memory-optimized data
alter database [Test_MemboryDB]
add filegroup fg_MemoryOptimizedData
contains MEMORY_OPTIMIZED_DATA;

alter database [Test_MemboryDB]
add file 
(
name=Test_MemboryDBDirectory,
filename='D:\Program Files\Microsoft SQL Server\Test_MemboryDBDirectory'
)
to FILEGROUP fg_MemoryOptimizedData;

文件组属性:CONTAINS MEMORY_OPTIMIZED_DATA 子句,指定File Group用于存储内存优化表数据,每个数据库只能指定一个存储内存优化数据的File Group,可以在该File Group下创建多个Directory,分布在不同的物理Disk上,加快内存优化表数据还原的速度。

二,创建内存优化表

内存优化表用于存储用户数据,可以持久化存储,数据存储在内存中,同时,在Disk上维护数据的一个副本,通过选项 DURABILITY= SCHEMA_AND_DATA 指定持久化存储内存优化表;也可以只存储在内存中,通过选项DURABILITY= SCHEMA_ONLY指定。在内存优化表上,可以创建nonclustered index 或nonclustered hash index,每个内存优化表中至少创建一个Index。

--create memory optimized table
create table [dbo].[products]
(
    [ProductID] [bigint] not null,
    [Name] [varchar](64) not null,
    [Price] decimal(10,2) not null,
    [Unit] varchar(16) not null,
    [Description] [varchar](max) null,
    constraint [PK__Products_ProductID] primary key nonclustered hash ([ProductID])with (bucket_count=2000000)
    ,index idx_Products_Price  nonclustered([Price] desc)
    ,index idx_Products_Unit nonclustered hash(Unit) with(bucket_count=40000)
)
with(memory_optimized=on,durability= schema_and_data)
go

1,内存优化:MEMORY_OPTIMIZED

[MEMORY_OPTIMIZED = {ON | OFF}]

默认值是OFF,指定创建的表是硬盘表;设置选项MEMORY_OPTIMIZED为ON,指定创建的表是内存优化表;

2,持久性:Durability 

DURABILITY = {SCHEMA_ONLY | SCHEMA_AND_DATA}

默认值是SCHEMA_AND_DATA,指定创建的内存优化表是持久化的,这意味着,数据更新会持久化存储到Disk上,在SQL Server重启之后,内存优化表的数据能跟根据存储在Disk上的副本还原。选项 SCHEMA_ONLY 指定创建的内存优化表是非持久化的,这意味着Table Schema是持久化存储到Disk上,但是,任何数据更新都不会持久化到Disk上,在SQL Server重启之后,内存优化表的数据会丢失。

3,哈希索引和范围索引

内存优化表支持Hash Index,属性 BUCKET_COUNT 指定为Hash Index创建的bucket的数量,一般hash bucket的数量是数据行的1-2倍,如果无法估计bucket的数量,请创建范围索引(NonClustered Index),索引结构是Bw-Tree。

Hash 索引由一个数组和多个数据行链组成,每一个数组元素叫做一个Hash Bucket,通过内置的Hash函数,将Hash索引的Key映射到Hash Bucket上,例如,如果Hash Index的Key是(Col1,Col2),根据HashFunction(Col1,Col2)返回的Hash Value,将数据行映射到指定的Hash Bucket上;如果多个Key映射到同一个Hash Bucket上,那么这些Key组成一个链。例如:数据表结构是(Name,City),在Name字段上创建Hash Index,Hash值相同的数据行链接成一个单向链。

三,创建Natively Compiled SP

本地编译SP在创建时编译成机器代码,整个SP以原子方式执行,这意味着,以SP为单位,整个SP中的所有操作是一个原子操作,要么执行成功,要么执行失败。

create procedure dbo.usp_GetProduct
    @ProductID bigint not null
with native_compilation, schemabinding, execute as owner
as
begin atomic with (transaction isolation level = snapshot, language = N'US_English')  
select  [ProductID]
      ,[Name]
      ,[Price]
      ,[Unit]
      ,[Description]
from [dbo].[Products]
where ProductID=@ProductID
end
go 

1,在本地编译SP中,能够为参数,变量指定Nullability属性,默认值是NULL

NOT NULL 属性:不能为参数或变量指定NULL值,

  • 在本便编译SP中,为参数指定NOT NULL属性,不能为参数指定NULL值;
  • 在本便编译SP中,为变量定义NOT NULL属性,必须在Declare时初始化变量;

2,本地编译SP必须包含两个选项:SCHEMABINDING 和 ATOMIC Block

  • SCHEMABINDING:绑定引用的内存优化表
  • ATOMIC Block:在原子块中的所有语句,以单个事务运行;在事务成功时,所有语句都提交成功;在事务失败时,所有语句都回滚。Atomic Bloc保证原子地执行SP,如果SP在其他事务的上下文中被调用,那么该SP开始一个新的事务。
    • Atomic blocks guarantee atomic execution of the stored procedure. If the procedure is invoked outside the context of an active transaction, it will start a new transaction, which commits at the end of the atomic block.

使用Atomic Block必须设置两个选项:

  • TRANSACTION ISOLATION LEVEL:指定Atomic Block开启事务的隔离级别,通常指定Snapshot隔离级别;
  • LANGUAGE:指定SP上下文的语言;

3,解释型SP和本地编译SP的区别

解释性SP能够访问硬盘表(Disk-Based Table)和内存优化表(Memory-Optimized Table),其真正的区别是解释性(Interpreted)SP在第一次执行时编译,而本地编译(Natively Compiled)SP是在创建时编译,并且直接编译成机器代码,绑定的是内存地址。

4,延迟持久化

在本地编译SP中,设置Atoic Block的选项:DELAYED_DURABILITY = ON ,使SP对内存优化表的更新操作,以异步写事务日志方式,延迟持久化到Disk,这意味着,如果内存优化表维护了一个Disk-Based 的副本,数据在内存中修改之后,不会立即更新到Disk-Based 的副本中,这有丢失数据的可能性,但是能够减少Disk IO,提高数据更新的性能。

四,使用内存优化的表变量和临时表

传统的表变量和临时表,都使用tempdb存储临时数据,而tempdb不是内存数据库,使用Disk存储临时表和表变量的数据,会产生Disk IO和竞争,SQL Server提供了内存优化的表变量,将临时数据存储在内存中,详细信息,请参考我的博客:《In-Memory:在内存中创建临时表和表变量》。

五,在内存数据库中使用JSON

自从使用JSON之后,我的第一感概是:数据库岂能没有JSON,不管是数据库将值传递前端,还是前端将数据传递到数据库,使用JSON方便很多,相比XML,JSON的使用简单很多,详细信息,请参考我的博客:《使用TSQL查询和更新 JSON 数据

六,内存数据库的事务处理

交叉事务是指在一个事务中,解释性TSQL语句同时访问内存优化表(Memory-Optimized Table,简称MOT)和硬盘表(Disk-Based Table,简称DBT)。在交叉事务中,访问MOT的操作和访问DBT的操作都拥有自己独立的事务序号,就像在一个大的交叉事务下,存在两个单独的子事务,分别用于访问MOT和DBT;在sys.dm_db_xtp_transactions (Transact-SQL)中,访问DBT的事务使用transaction_id标识,访问MOT的事务序号使用xtp_transaction_id标识。详细信息,请参考我的博客:《In-Memory:内存优化表的事务处理

 

参考文档:

sqlserver2014内存数据库特性介绍

In-Memory OLTP (In-Memory Optimization)

Introduction to Memory-Optimized Tables

Natively Compiled Stored Procedures

Memory-Optimized Tables

试试SQLSERVER2014的内存优化表

SQLServer 2014 内存优化表

SQL Server 2014 内存优化表(1)实现内存优化表

作者悦光阴
本文版权归作者和博客园所有,欢迎转载,但未经作者同意,必须保留此段声明,且在文章页面醒目位置显示原文连接,否则保留追究法律责任的权利。
分类: In-Memory
本文转自悦光阴博客园博客,原文链接:http://www.cnblogs.com/ljhdo/p/5762716.html,如需转载请自行联系原作者
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

In-Memory:内存数据库 的相关文章

  • JSON 中的哈希到底是什么?

    我正在学习 JSON 但我发现你也可以将所谓的 哈希 放入 JSON 中 我在哪里可以找到什么是哈希 或者你能向我解释一下什么是哈希吗 另外 什么是哈希图 我有 C 和 C 经验 正在学习 JS Jquery 和 JSON 哈希是一个稀疏数
  • 有没有办法在 jqgrid treeGrid url 请求中传回附加数据?

    i am 使用 jqgrid 树视图 http www trirand com jqgridwiki doku php id wiki 3atreegrid我正在传回 json 响应 效果很好 我想将一些有关请求的附加信息传递回 GUI 并
  • Mandrill 验证错误

    很高兴能在 StackOverflow 上提出我的第一个问题 多年来我一直依靠它自学了很多东西 我的问题是这样的 尝试通过 Mandrill 的 API 发送邮件时出现以下错误 status error code 1 name Valida
  • 如何在 Serde 中(反)序列化强类型 JSON 字典?

    我正在编写一个 Rust 应用程序 它使用公共接口处理来自 TypeScript 客户端的 JSON 消息 我写了一些代码使用serde derive它运行良好 但我不知道如何实现字典 例如 foo data 42 bar data 133
  • 如何将异常序列化为Json

    C 异常是 ISerialisable 因此它们不能也是 DataContract 因此我无法使用 JsonDataContractSerializer 将异常序列化为 JSON 的替代方案是什么 由于这个问题还没有真正得到解答 只需创建一
  • Postgres JSON 数据类型 Rails 查询

    我正在使用 Postgres 的 json 数据类型 但想要使用嵌套在 json 中的数据进行查询 排序 我想在 json 数据类型上使用 where 进行订购或查询 例如 我想查询关注者数量 gt 500 的用户 或者我想按关注者或关注数
  • Kubernetes / kubectl - “必须指定容器名称”,但看起来确实如此?

    我正在调试 kubectl 的日志输出 其中指出 Error from server BadRequest a container name must be specified for pod postgres operator 49202
  • 使用python将json和文件发送到flask

    我遇到这个问题 我试图在单个函数中向 Flask API 发送 接收一些文件和 JSON 在我的客户端 发件人 上我有 my json to be sent datas var1 var1 var2 var2 my file to be s
  • Postgres JSONB:数组数组的 where 子句

    postgres 中有 v 9 5 如果有的话 create table json test id varchar NOT NULL data jsonb NOT NULL PRIMARY KEY id 其中 data 是 json 并且包
  • 根据 .NET Core 2.1 中的更改重新加载 Serilog JSON 配置

    我目前正在开发 ASP NET Core 2 1 应用程序 并使用 Serilog 进行日志记录 我想在运行时为我的 Serilog 实现重新加载应用程序设置文件 我的目标是在运行时更改日志级别 例如我写入minimumLevelDebug
  • Ruby on Rails 服务器在 HTTPS POST 请求期间崩溃

    我正在尝试与你沟通城市飞艇API http urbanairship com docs push html broadcast使用 ROR Web 应用程序 在我的控制器中 我有以下代码 require net http require n
  • 为什么 PyYAML 花费这么多时间来解析 YAML 文件?

    我正在解析一个大约 6500 行的 YAML 文件 格式如下 foo1 bar1 blah name john age 123 metadata whatever1 whatever whatever2 whatever stuff thi
  • 包含 contains 的 json 格式查询

    我在 ansible 中有以下 json 输出 active transaction null cores 4 hostname alpha auth wb01 active transaction null cores 4 hostnam
  • Oracle 中的 Json_object 返回 ORA-00907: 缺少右括号

    我正在尝试将 Oracle 表数据转换为 JSON 文件 我有三个数据库 下面的代码在一个数据库中以 JSON 文件形式提供输出 但其他两个数据库抛出ORA 00907 missing right parenthesis error 从语法
  • Groovy - JsonSlurper 解析 JSON 文件

    我有一个类似于下面的 JSON 文档 我正在尝试在 Groovy 中解析它 基本上对于每所学校 学校信息 我想抓住SCHOOL COUNTRY和其他领域 我正在尝试下面的代码 但它没有返回我需要的内容 对于列出的每所学校 1 000 所 我
  • json_encode 返回 NULL?

    由于某种原因 项目 描述 返回NULL使用以下代码 这是我的数据库的架构 CREATE TABLE staff id int 11 NOT NULL AUTO INCREMENT name longtext COLL
  • 编码:类型错误:write() 参数必须是 str,而不是 bytes

    我对 python 有初步的了解 但不清楚处理二进制编码问题 我正在尝试运行 firefox webextensions 示例中的示例代码 其中 python 脚本发送由 javascript 程序读取的文本 我不断遇到编码错误 蟒蛇代码是
  • 无法将数据加载到 mvc 4 中的 jTable 中

    好的 我第一次尝试 jTable 我可以加载表 但这对我没有什么好处 因为它不会加载我的任何数据 当我调试程序时 我想要的表中的所有行都存储在我的列表中 因此我很困惑为什么当我运行应用程序时会弹出一个对话框 显示 与服务器通信时发生错误 H
  • jq中如何分组?

    这是 json 文档 name bucket1 clusterName cluster1 name bucket2 clusterName cluster1 name bucket3 clusterName cluster2 name bu
  • 从 Twitter API 2.0 获取 user.fields 时出现问题

    我想从 Twitter API 2 0 端点加载推文 并尝试获取标准字段 作者 文本 和一些扩展字段 尤其是 用户 字段 端点和参数的定义工作没有错误 在生成的 json 中 我只找到标准字段 但没有找到所需的 user fields 用户

随机推荐

  • 陷波器设计

    中心频率 f c H z f c rm Hz fc Hz 3dB陷波器带宽 f
  • emplace_back与push_back异同

    vector的emplace back与push back 文章目录 vector的emplace back与push back 前言 1 区别总览 2 push back 支持右值引用 不支持传入多个构造参数 总是会进行拷贝构造 3 em
  • C++学习笔记——随机数

    利用rand 函数生成随机数如何随机是根据随机数种子来生成 一个程序的随机数种子一般是固定的 所以是伪随机数 若想生成真随机数 则用电脑的时间来初始化这个随机数种子 include
  • LLM 赋能的研发效能:如何探索软件开发新工序?

    上周末 我们 我和我的同事谢保龙 在 QCon 广州 2023 上分享了一个 AI 结合研发效能的话题 探索软件开发新工序 LLM 赋能研发效能提升 我们分享了 Thoughtworks 在过去的两个月里对于 LLM 大语言模型 结合软件开
  • 高防CDN和加速CDN有什么区别?

    高防CDN和加速CDN有什么区别 随着互联网技术的不断发展 CDN Content Delivery Network 已经成为了网络加速和安全保障的重要手段 在CDN的领域中 高防CDN和加速CDN是两种不同的CDN服务 它们有不同的特点和
  • 重积分的计算与理解

    主要分为二重积分和三重积分 二重积分 二重积分的基本思想是变成两次积分 物理意义已知面密度f 算质量 即首先把y方向的每一根线段计算出质量 相当于把y的线捏起来了 然后算x 主要方法如下 计算 D f x
  • 数据结构之链表:单向链表、单向循环链表、双向链表及基本操作

    目录 一 链表 1 1 单向链表 1 1 1 单链表的操作 1 2 单向循环链表 1 3 双向链表 了解 二 链表与顺序表的对比 一 链表 链表 将元素存放在通过链接构造起来的一系列存储块中 在每一个节点 数据存储单元 里存放下一个节点的位
  • 2020美赛建模F题思路和理解

    2020 MCM ICM 美国大学生数学建模竞赛 MCM ICM F题 2020 ICM Weekend 2 Problem F The Place I Called Home 思路和理解 问题中心 设计模型研究海平面上升对相关国家的人口
  • 报错:Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

    这两天自己搭spingmvc 总是报错 找不到自动注册的bean Could not autowire field private lf service UserService lf controllers UserController u
  • java实现队列_java实现队列

    队列的定义 队列的特点是节点的排队次序和出队次序按入队时间先后确定 即先入队者先出队 后入队者后出队 即我们常说的FIFO first in first out 先进先出 顺序队列定义及相关操作 顺序存储结构存储的队列称为顺序队列 内部使用
  • 使用 pad_sequence

    pad sequence 是用来干嘛的 首先 pad sequence 是用来对对tensor做padding 的 先看官方示例 文档地址https pytorch org docs stable generated torch nn ut
  • seaborn分类数据的绘制

    转载 seaborn分类数据的绘制https zhuanlan zhihu com p 27683042 总结很全的资料
  • json工具类ObjectMapper的详细使用记录

    1 用于json与其他对象之间转化的工具类 public class JsonUtil private static final ObjectMapper MAPPER new ObjectMapper private static fin
  • Java面向对象三大特性:继承、封装、多态

    面向对象编程 一 继承 1 表现形式 A extends B 2 子类继承了父类的什么 BAT 面试 3 this 和 super 关键字的区别 面试 4 Java 中访问权限修饰符 5 重写 与 重载的区别 面试 6 final 的用法
  • Qt学习笔记(四)ui界面通过样式表添加图片、背景、字体颜色等

    1 创建工程 添加ui 添加qrc资源文件 将图片导入 2 进入ui 可对背景界面 可对label pushbutton等构件右键改变样式表 进入样式表 看到添加资源下有三个选项 background image board image i
  • 【密码学】古代、古典密码

    古代密码 数据的保密基于加密算法的保密 Scytale密码 使用一条纸袋作为载体 环绕在一根固定半径的圆柱上 加密 在绕好的纸带上写上明文 解开缠绕后 就是加密好的 无序的密文 圆柱的半径就是密钥 解密 找到相同大小的圆柱 将纸带缠绕在援助
  • 随机数函数(一):均匀分布的随机数函数

    随机数是随机产生的数 可以分为两种 真随机数和伪随机数 计算机所使用的都是伪随机数 并不能像投硬币或者投骰子那样产生真正随机的 事前不能确定结果的数值 事实上 计算机在模拟产生随机数前就会按照某种算法产生一个特定的序列 也就意味着每个随机数
  • 主流WEB漏洞扫描器种类及其指纹特征分析

    福利 网络安全重磅福利 入门 进阶全套282G学习资源包免费分享 0x01 Web 漏洞扫描 器 国内 绿盟 WVSS https www nsfocus com cn html 2019 206 0911 8 html 安恒 明鉴 htt
  • ESP32 的esp_http_client详解

    说明 我使用的是esp idf V3 1 3 官方给我们封装好了 HTTP 使用起来还是很方便 一 wifi连接 在main函数里面主要是做了wifi连接的初始化和HTTP任务的创建 如下是main的全部内容 void app main e
  • In-Memory:内存数据库

    在逝去的2016后半年 由于项目需要支持数据的快速更新和多用户的高并发负载 我试水SQL Server 2016的In Memory OLTP 创建内存数据库实现项目的负载需求 现在项目接近尾声 系统运行稳定 写一篇博客 记录一下使用内存数