Day03:什么是缓存击穿 ? 怎么解决 ?

缓存击穿

缓存击穿的就是给某一个热点key设置了过期时间,当key过期的时候,恰好这时间点对这个Key有大量的并发请求,这些请求发现缓存过期一般都会从后端 DB 加载数据并写回缓存(往往热点key的重新构建有比较耗时),这个时候大量并发的请求可能会瞬间把 DB 压垮。

在这里插入图片描述

解决方案有两种方式:

1.互斥锁(分布式锁), 发现热点key过期加互斥锁,新线程抢不到锁会不断重试 数据强一致,但会等待。

在这里插入图片描述
第一可以使用互斥锁(分布式锁):当缓存失效时,假设有线程过来,只能一个一个的来访问数据库,从而避免对于数据库访问压力过大,但这也会影响查询的性能,因为此时会让查询的性能从并行变成了串行,我们可以采用setnx方法 + double check(第一次获取锁的check,如果有线程已经更新DB并且重建缓存后,应先再次check一下缓存是否命中)来解决这样的问题。

2.逻辑过期,发现key过期,单开线程去查DB重建缓存,原来线程以及新线程直接返回旧数据,数据高可用

第二种方案可以设置当前key逻辑过期,大概是思路如下:

前提是默认该热点key是必命中的 在命令上把这个key设置为永不过期,但是要在逻辑上,也就是通过设置值vlaue去给它一个逻辑过期时间字段。

在这里插入图片描述

①:在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间,而是设置他的逻辑过期(其实就一个时间戳)

②:当查询的时候,从redis取出数据后判断时间是否过期

③:如果过期则开通另外一个线程进行数据同步(同步之前肯定还是要获取互斥锁的,但此时的锁并不会造成线程间的串行执行,这是因为一旦线程获取不到互斥锁,就会直接放弃,返回过期的数据),当前线程正常返回数据,但是这个数据不是最新的,会造成数据的弱一致(软状态)。

当然两种方案各有利弊:

如果选择数据的强一致性,建议使用分布式锁的方案,性能上可能没那么高,锁需要等,也有可能产生死锁的问题。一般跟钱相关的业务通常要保持强一致性需要使用。

如果选择逻辑过期,则优先考虑的高可用性,性能比较高,但是数据同步这块做不到强一致。业务更注重用户的体验,互联网的行业一般使用逻辑过期。

<think>嗯,用户遇到了SQL错误ORA-00932,具体是NUMBER和INTERVAL DAY TO SECOND类型不匹配的问题。我需要先理解这个错误的含义。ORA-00932通常发生在两个数据类型不一致的情况下,比如在比较或赋值操作中。用户提到的两种类型是NUMBER和INTERVAL DAY TO SECOND,这可能出现在哪里呢? 首先,检查用户可能在哪里使用了这两种类型。比如,在WHERE子句中进行比较,或者在INSERT、UPDATE语句中赋值。例如,用户可能尝试将NUMBER类型的列与INTERVAL类型的值进行比较,或者反过来。 接下来,我应该考虑如何解决这个问题。可能的解决方案包括显式转换数据类型。比如,使用TO_DSINTERVAL函数将字符串转换为INTERVAL DAY TO SECOND类型,或者在处理数值时确保两边类型一致。例如,如果用户试图将NUMBER类型的列与INTERVAL值相加,可能需要用NUMTODSINTERVAL函数将数字转换为INTERVAL。 另外,需要检查涉及到的列和表达式,确认它们的数据类型。如果用户想存储时间间隔,应确保列定义为INTERVAL DAY TO SECOND类型,而不是NUMBER。如果是计算问题,可能需要调整表达式,确保两边类型兼容。 还有,可能需要使用CAST函数显式转换类型,或者在计算时使用正确的函数。例如,当需要将数字转换为秒数的时间间隔时,可以使用NUMTODSINTERVAL(seconds, 'SECOND')。 然后,生成相关问题的时候,要考虑用户可能的后续疑问。比如如何转换其他数据类型,或者ORA-00932的其他常见原因,以及INTERVAL类型的应用场景。 需要确保回答的结构清晰,分点说明解决方案,并提供示例代码帮助用户理解。同时,引用来源要正确,虽然用户没有给出具体引用,但可能需要参考Oracle官方文档中的相关函数和错误说明。</think>### ORA-00932 数据类型不匹配解决方案 **问题原因** ORA-00932错误表示SQL语句中存在不兼容的数据类型操作,例如尝试将$NUMBER$类型与$INTERVAL\ DAY\ TO\ SECOND$类型直接比较、赋值或运算[^1]。 --- ### 解决方案分步说明 #### 1. 明确数据类型差异 - $NUMBER$:存储数值 - $INTERVAL\ DAY\ TO\ SECOND$:存储时间间隔(如`3天5小时`) #### 2. 使用显式类型转换 **场景1:将数值转换为时间间隔** 若需将数值(秒数)转换为时间间隔: ```sql SELECT NUMTODSINTERVAL(3600, 'SECOND') AS time_interval FROM dual; -- 结果:+00 01:00:00.000000 ``` **场景2:将时间间隔转换为数值** 若需提取时间间隔中的秒数: ```sql SELECT EXTRACT(SECOND FROM INTERVAL '01:30:00' HOUR TO SECOND) AS seconds FROM dual; -- 结果:5400(1.5小时=5400秒) ``` #### 3. 检查表结构定义 若字段需要存储时间间隔,应定义为`INTERVAL DAY TO SECOND`: ```sql CREATE TABLE events ( event_id NUMBER, duration INTERVAL DAY TO SECOND ); ``` #### 4. 修正表达式类型匹配 **错误示例**(混合数值与时间间隔): ```sql SELECT duration + 3600 FROM events; -- 错误 ``` **修正方法**: ```sql SELECT duration + NUMTODSINTERVAL(3600, 'SECOND') FROM events; ``` --- ### 典型错误场景与修正 | 错误场景 | 修正方案 | |---------|----------| | `WHERE number_col = INTERVAL '1' HOUR` | `WHERE number_col = EXTRACT(HOUR FROM INTERVAL '1' HOUR)` | | `SELECT number_col || INTERVAL '2' DAY` | `SELECT TO_CHAR(number_col) || INTERVAL '2' DAY` | --- 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值