- 博客(74)
- 收藏
- 关注
原创 未提交读的问题
因此,在实际应用中,应该避免使用 Read Uncmmitted 隔离级别,除非对数据一致性要求极低,并且能接受脏读带来的所有后果。如果事务 B 读取了事务 A 修改但未提交的数据,当事务 A 回滚时,事务 B 读取到的数据就是无效的脏数据。如果应用程序基于脏数据执行后续操作,则可能导致逻辑错误,例如错误的计算、错误的决策等。由于允许脏读,可能导致应用程序读取到不一致的数据,破坏数据的完整性。此时,事务 B 基于 200 元的脏数据进行了操作,导致数据不一致。读取账户余额,会读取到 200 元(脏读)。
2025-07-28 20:01:19
124
原创 RR不能解决幻读的原因
当执行 SELECT ... FR UPDATE、UPDATE、DELETE 等操作时,InnDB 会自动为影响的数据加上 Next-Key Lck,从而防止其他事务插入或删除数据,导致幻读。对于select * frm table where id = 10 fr update, 会锁住id=10的索引和间隙, 防止其他事务修改id=10,或者插入id = 10.x 的数据。当一个事务在读取数据时,MVCC不会记录新插入的数据,当再次读取的时候,新插入的数据就会造成幻读。
2025-07-28 19:55:32
305
原创 解决幻读问题
当使用范围查询时(例如 SELECT * FROM table WHERE id > 10 FOR UPDATE),InnoDB 会使用 Next-Key Lock 锁定指定范围的所有记录及间隙,避免在查询期间出现幻读。幻读(Phantom Read) 是指在同一个事务中,多次读取同一范围内的记录时,由于其他事务的插入或删除操作,导致该事务前后读取到的记录数量不一致。Next-Key Lock 不仅会锁定索引记录本身,还会锁定索引记录之间的间隙,防止其他事务在该间隙中插入新记录,从而避免幻读。
2025-07-28 19:52:42
331
原创 Go语言中的并发模型
Goland使用goroutines和channels来实现并发。goroutines是轻量级的线程,由Go运行时管理,可以高效的执行并发任务。channels是用于在goroutines之间传递数据的类型安全管道,支持阻塞和解除阻塞操作,使得并发编程更加安全和简单。
2025-07-24 19:15:31
99
原创 事务的特性和隔离级别
事务的隔离级别定义了并发环境下,一个事务在执行读写操作时,会受到其他事务影响的程度。它是数据库保持acid中的“隔离性”的关键机制之一。事务隔离级别,就是给不同事务之间设置“保护伞”,防止“你看一半”被别人改了。4.持久性:一旦事务提交,其对数据库的修改应永久保存,即使系统发生故障也不会丢失。3.隔离性:多个事务并发执行时,每个事务的操作应彼此隔离,避免相互干扰。高级别 = 慢 = 数据更稳定。1.原子性:事务中的所有操作要么全部成功,要么全部失败。2.一致性:事务执行前后,数据库都必须处于一致的状态。
2025-07-24 19:08:59
190
原创 explain中每个字段的解释
select_type:查询类型(const,eq_ref,ref,range,index按效率从高到低)id:查询中每个Select子句的标识,数字越大,优先级越高。key:实际使用的索引(如果是null,说明未命中索引)type:连接类型,判断索引是否命中的最关键字段之一。possible_keys:查询可能使用的索引。key_len:使用的索引的长度,越短越高效。rows:预估要扫描的行数,越少越高效。table:当前正在访问的表名。extra:补充信息。
2025-07-23 17:51:48
88
原创 聚簇索引的优势
数据存储效率高:聚簇索引将数据行与索引存储在同一个结构中,数据按照索引键的顺序物理存储。减少回表操作:普通索引查询可能需要通过回表(回到主索引获取完整数据行),而聚簇索引的叶子节点直接包含完整数据行,避免了额外的查找步骤,降低了查询延迟。范围查询性能优异:由于数据按索引键顺序物理存储,范围查询可以快速定位到起始点,并顺序读取后续数据,避免了随机I/O带来的性能损耗。优化排序和分组操作:如果查询涉及索引键的排序或分组,聚簇索引可以避免额外的排序步骤,因为数据已按索引键物理有序存储。
2025-07-22 19:15:02
141
原创 索引快的原因
避免全表扫描:没有索引时,查询需逐行检查所有数据(全表扫描)。例如,对 100 万行数据的等值查询,全表扫描需比较 100 万次,而索引可能仅需 3~4 次(B+ 树高度通常很低)。索引通过有序存储键值(如 B+ 树结构),将随机访问转化为顺序访问,减少磁盘寻道时间。它类似于书籍的目录,通过预先组织关键信息(如字段值)和对应的存储位置,减少查询时需要扫描的数据量。排序和分组优化:索引本身是有序的,对于ORDER BY或GROUP BY操作,数据库可直接利用索引顺序返回结果,避免临时排序的额外开销。
2025-07-22 18:22:14
130
原创 Mysql基本操作
添加字段:ALTER TABLE users ADD 字段名称 字段类型 NOT NULL DEFAULT ' ' COMMENT '字段中文名称';修改NULL值:LTER TABLE users MODIFY COLUMN 字段 字段类型 NOT NULL;修改字段类型:ALTER TABLE users MODIFY COLUMN 字段 新的字段类型;修改字段:ALTER TABLE users CHANGE 原字段 新字段 新字段的类型;查看数据库中有哪些表:show tables;
2025-07-21 21:45:54
195
原创 对称加密速度更快的原因
计算复杂度不同,对称加密使用的是同一个秘钥进行加密和解密,算法简单直接,运算量小;飞堆成加密使用两种秘钥,基于复杂的数学问题,计算量大,速度慢10-1000倍。实际应用中,通常采用混合加密,先用非对称加密交换密钥(安全但慢),再用对称加密传输数据(快,但需要安全密钥),兼顾速度与安全。
2025-07-15 15:43:04
82
原创 IP地址的分类
A类地址适用于大型网络,因为它允许非常多的主机地址。C类地址:192.0.0.0-223.255.255.255,前三个数字代表网络地址,最后一个代表主机地址,C类地址适用于小型网络,因为它提供的主机地址相对较少。B类地址:128.0.0.0-191.255.255.255,前两个数字代表网络地址,后两个数字代表主机地址,,B类地址适用于中型网络,介于A类和C类之间。D类地址:224.0.0.0-239.255.255.255,D类地址不用于标识具体的网络或主机,而是用于多播。
2025-07-15 14:26:44
176
原创 DNS的含义以及例子
DNS服务器其实就相当于一个负责翻译的中介,比如,我们在浏览器输入baidu.com,DNS系统会查到这个baidu.com(域名)相对应的IP地址,紧接着,浏览器通过这个IP地址就找到了百度的服务器。DNS是互联网的核心目录服务,本质是一个分布式数据库,专门负责将人类友好的域名(如。它的设计目标是解决互联网中寻找效率和可扩展性的问题。)转换为机器可识别的IP地址(如。
2025-07-15 13:53:47
120
原创 HTTP2更快的原因
2.二进制协议:HTTP2采用的是二进制协议,计算机可以直接处理二进制,解析更快、HTTP1.1采用的是文本格式传输数据,计算机首先需要解析这些文本,效率比较低。4.服务器推送:传统的需要先让浏览器请求HTML,解析后在请求CSS/JS等,有延迟,服务器推送可以主动推送资源给浏览器,省去了“请求等待”的步骤。1.多路复用:HTTP允许同时发送和接收多个响应,HTTP1.1中,浏览器与服务器之间的通信是需要“排队”的。5.优先级和依赖控制:HTTP2允许给请求设置优先级。
2025-07-15 13:43:36
197
原创 sync.Mutex和sync.RWMutex的区别和它们的使用场景。sync.RWMutex在读多写少的场景下性能更好的原因。
RWMtuex是读写互斥锁,读操作允许多个goroutines并发进行,写操作只允许一个goroutines进行操作。Mutex是普通互斥锁,读写操作都需要先获取锁,同一时刻只能有一个goroutines在进行操作。Mutex适用于读写操作频繁且无明显倾向的场景,RWMutex适用于读多写少的操作。
2025-07-11 15:16:32
133
原创 Go语言的Channel通道的含义。区分缓冲通道和非缓冲通道,并讨论通道的发送、接收、关闭以及如何安全地从已关闭的通道读取数据。
非缓冲通道:非缓冲通道在确定时没有声明容量大小,发送和接收操作会同步阻塞,直到另一端准备好。发送方和接收方必须同时就绪才能完成数据交换,否则会阻塞。缓冲通道:缓冲通道在确定时就声明了容量大小,发送操作在缓冲区未满时不会阻塞,接收操作在缓冲区非空时不会阻塞。当缓冲区满时发送会阻塞,空时接收会阻塞。关闭通道:使用close()关闭通道,关闭后不可在发送数据。非缓冲通道:无接收方的发送或无发送方的接收会导致永久阻塞。关闭通道后,接收方读取零值,发送方panic。缓冲通道:仅当缓冲区满/空时阻塞。
2025-07-11 15:04:51
154
原创 Go语言中数组和切片的主要区别
3.传递方式:数组传递是值传递,当对第一个数组作为参数传递给函数时,得到的是数组的副本,对副本的修改不会影响到原数组;切片传递是引用传递,传递的是切片结构体的副本,但其中的指针指向底层数组,所以在函数内对切片的修改会影响到原切片。2.内存结构:数组是一块儿连续的、固定大小的内存空间,可以直接存储元素,切片是一个结构体,包含指向底层数组的指针,切片的长度和容量。1.长度方面:数组的长度是固定的,在声明时就是确定好的,之后不能更改,切片的长度是可变的,可以根据需要进行动态增长或缩小。
2025-07-11 14:49:20
115
原创 Go语言中defer语句的含义,它使用的场景,写出的示例。
Go语言的defer语句用于延迟执行某一个函数或方法调用,直到包含它的函数执行完毕(无论正常返回还是发生异常)。它的应用场景一般在:资源释放,错误处理,日志记录。
2025-07-11 14:39:18
117
原创 map数据结构在Golang中是无序的,并且键值对的查找效率较高的原因
map,map在Go语言中是无序的,是因为在Go语言中,map基于哈希表实现,它的遍历顺序依赖于哈希表内部存储状态,对并发编程的潜在影响包括可能引发数据一致性问题,也就是并发度写实易导致读到不一样的数据或遍历出错;(4)动态扩容,当负载因子(键值对数量/桶数量)超过阈值时,map会自动扩容,减少哈希冲突概率,维持O(1)的平均操作时间。(2)哈希表的函数优化,Go会根据键的类型选择高效的哈希函数,均匀分布键以减少冲突。(1)哈希表的时间复杂度,哈希表的平均复杂度为O(1),最欢情况下为O(n)。
2025-07-11 14:30:21
230
原创 在Go语言中,声明一个指向整型变量 x 的指针变量
声明一个指向整型变量x的指针变量有两种方式,一种是使用var关键字声明,语法为var p *int,这代表着声明了一个名为p的指针变量,可以指向一个整型变量;另一种是短变量声明,需要获取变量x的地址并赋值给指针变量,也就是p := &x。
2025-07-11 13:25:40
100
原创 sync.WaitGroup的用途和工作原理。并且它们常使用的场景。
用途:让一个或多个goroutine等待一组其他goroutine全部完成任务后,再继续执行,避免主逻辑提前退出导致子goroutine被终止。wait:阻塞当前goroutine直到计数器归0,,此时所有被等待的goroutine已执行完毕。Done:等价于Add(-1),由子goroutine任务结束时调用,标记自身完成。需协调多goroutine执行顺序,确保一组并发任务全部完成后在执行后续逻辑。Add():修改计数器的值,用于声明需等待的goroutine数量。
2025-07-10 19:37:02
151
原创 Go语言的类型转换和类型断言的定义,它们之间的区别。
3.使用限制:类型转换要求目标类型和源类型有一定的兼容性,类型断言针对接口类型,接口实际存储的类型和断言类型不匹配时会有特定的返回值。2.应用场景:类型转换适用于不同但兼容的非接口类型之间的转换,类型断言适用于处理接口类型,判断接口中实际存储的类型并获取值。1.语法形式:类型转换是将表达式转换为指定类型,类型断言针对接口类型变量进行具体类型的判断和值的提取。类型转换:将一种类型的变量转换为另外一种类型的变量。类型断言:用于从接口类型变量中提取具体的类型值。
2025-07-10 19:25:36
76
原创 Go语言中map的零值,对零值map进行读写操作会发生的情况,正确初始化和使用map的步骤
Go语言中map的零值是nil,对map进行进行读操作:如果读取一个不存在的值,那么将会返回相对应的值的类型,对map进行写操作的话,可能会引发运行时的问题。4.遍历:使用for-range遍历map,例如for Key.value := range m {fmt.Println(key,value)}2.读取数据:通过值 := map变量[键]的方式读取数据,可以同时获取值和一个布尔值,来判断键是否存在。1.导入数据:通过map 变量 [键] = 值的方式写入数据,例如m["newkey"] = 5。
2025-07-10 19:04:49
127
原创 Go语言中map的创建和基本操作(增删改查)
使用var创建,var m map[string]int,进行初始化才能进行使用,若不进行初始化,map的零值是nil。使用make初始化,m := make(map[string]int)查询:val, ok := m["key"]遍历:fork, v := range m。删除:delete(m, "key"),增改:m["key"]=value。
2025-07-10 18:11:58
82
原创 Golang中的内置类型
首先,内置类型是指不需要引入任何关于这些数据类型的包,就可以引用的数据类型。那么,内置类型主要包括基本类型,复合类型,控制并发,高级抽象,特殊类型。基本类型包括,整型,浮点型,布尔型,字符串,复数型(complex64,complex128)结构体是用户自定义复合类型,需通过type关键字手动声明定义不属于Go语言内置类型。高级抽象包括,interface,function,pointer。复合型包括,数组,切片,map,slice。特殊类型包括,error,any。控制通道,channel。
2025-07-10 18:00:34
208
原创 Deepseek
Deepseek作为一个人工智能应用,可以与用户进行智能对话,根据用户的需求进行文本生成;可以对自然语言进行各方面的分析,智能的识别内容主题进行文本分类;对于一些逻辑性的问题能够进行智能推理,从而给出答案;在编程与代码方面,我们可以把详细的需求告诉它,从而根据需求生成答案,或者进行代码调试,技术文档的处理等等。deepseek是一家人工智能科技公司所开发的能够进行人工智能对话的一个应用,它的主要目标是大规模的研发与应用。deepseek-R1是它的开源推理模型,主要负责处理复杂任务并且可以免费使用。
2025-02-10 21:32:34
346
原创 从入门到精通:如何更好地使用AI
策略五:灵活运用开放式提示与封闭式提示--开放式提示:提出开放性问题,允许AI根据多个角度进行生成--封闭式提示:提出具体问题或设定明确限制,要求AI给出精准回答。非推理模型(GPT-3、GPT-4、BERT(Google))侧重于文本生成、语义理解,文本分类,翻译,缺乏推理模型复杂的推理和决策能力。未来规划是年终总结的重点,目的是在为新的一年设定明确的目标和发展方向,提示语应侧重目标设定,行动计划,个人成长。推理模型的提示语要简洁,不需要分布式的需求,但通用模型的提示语需要分布式的需求。
2025-02-10 21:25:11
2225
原创 Models如何使用Gorm与数据库进行交互?
ORM(Object-RelationalMapping,对象关系映射)是一种技术,它把程序中的对象(比如Go的结构体)和数据库中的表(比如MySQL的表)自动映射起来。通过ORM,你可以用面向对象的方式操作数据库,而不需要直接写SQL。它的作用是把Go语言中的结构体(struct)和数据库中的表(table)对应起来,让你可以用Go代码直接操作数据库,而不需要写复杂的SQL语句。Golang的代码解析成SQL语句,把查到的数据解析成GOlang的数据结构。
2025-01-19 21:02:36
365
原创 Controller-Services-Models
然后Services层在反馈给Controller层,Controller层接收到数据以后显示给在屏幕上;Services:属于中间层,问Models层要符合Controller层的需求的东西;Controller:负责接受任务,然后将需求告诉Services层;Models:该层去数据库找符合要求的数据,反馈给Services层;
2025-01-12 16:05:46
151
原创 获取天气信息
如下所示,在网页中,还会出现城市对应的行政区,例如,“深圳”市中有“福田区。现在我们可以查询到“福田区”的id号是101280603,现在我们把id号复制粘贴到查询天气的网址中,然后复制你的Key到网址中,假设我的key是d5a4d4as4d4f3as4df4sa,那么最终查询天气的网址就是。登录和风天气开发服务平台后,进入“开发服务控制台”,点击左侧“项目管理”,在右侧点击“创建项目”,然后填写“项目名称”,选择“免费订阅”,设置KEY为“Web API”,并给KEY起个名称,最后点击创建。
2025-01-09 22:01:39
838
原创 网络授时笔记
复制到实验文件夹,路径为D:\esp32c3\sntp,不用修改名字,使用VSCode打开sntp文件夹,程序不需要修改,直接配置好串口、目标芯片,menuconfig就可以下载看结果,menuconfig中,除了把flash大小修改为8MB以外,还需要添加你要连接wifi的名称和密码。前面我们已经知道,程序每10秒钟会唤醒一次,每次唤醒后,boot_count值会加1,并使用ESP_LOGI把boot_count的值打印到终端。点击软件最上面的向左的箭头←,回到obtain_time函数中刚才的位置。
2025-01-09 19:04:22
1197
原创 WiFi连接
再往后使用esp_event_handler_instance_register()函数注册了WIFI_EVENT和IP_EVENT事件,并且定义了事件处理函数名称为event_handler。最后一个参数为portMAX_DELAY,表示将一直等待,直到WIFI_CONNECTED_BIT 事件或WIFI_FAIL_BIT事件的发生。然后在wifi_init_sta()函数的最开始处,使用xEventGroupCreate()创建了事件组,并返回给s_wifi_event_group句柄。
2025-01-09 18:19:48
434
原创 WiFi扫描
上述代码中,第4~10行,是wifi初始化阶段。直接复制scan这个例程到你的实验文件夹,该例程位于esp-idf-v5.1.3\examples\wifi\scan,复制过来后,使用VSCode打开工程,直接配置串口号、芯片型号、menuconfig等就可以,不需要修改代码,menuconfig中,除了要修改FLASH大小为8MB之外,还可以修改扫描wifi名称后列出的最大数量,默认是10。在app_main函数,如下代码所示,由两部分代码组成,第一部分是初始化nvs,第二部分是执行wifi_scan。
2025-01-09 17:53:36
1309
原创 LVGL Demo
然后找到example_lvgl_port_update_callback函数,现在的case分别是NONE、90、180、270,默认是NONE,是竖屏,现在需要把默认改成横屏,就是默认是90的样子,所以,现在把90改成NONE,然后把180改成90,把270改成180,把NONE改成270。在app_main函数中,找到esp_lcd_panel_mirror函数,原来的mirror,xy都是false不翻转,从上一个函数中我们知道,y需要翻转,所以把y参数位置变成true。
2025-01-09 17:04:29
1230
1
原创 LCD触摸
默认是LV_DISP_ROT_NONE,点击一次按钮后,变成LV_DISP_ROT_90,再点击一次变成LV_DISP_ROT_180,再点击一次变成LV_DISP_ROT_270,再点击一次回到LV_DISP_ROT_NONE,点击了一次,说明函数进LV_DISP_ROT_90进行了处理。第2个if编译是修改的,把鼠标放到esp_lcd_touch_new_i2c_ft5x06上面单击右键选择“转到定义”,会发现这个函数是在esp_lcd_touch_ft5x06.c文件中定义的。
2025-01-09 16:01:33
1795
6
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人