oracle的sys_guid() 函数

1 解释

sys_guid(),是Oracle 8i 后提供的函数。sys_guid产生并返回一个全球唯一的标识符(原始值)由16个字节组成。在大多数平台,生成的标识符由主机标符,执行函数的进程或者线程标识符,和进程或线程的一个非重复的值(字节序列)

2 查看方式

select sys_guid() from dual;

注:如果为乱码则使用rawtohex()函数

select rawtohex(sys_guid()) from dual;

3 sys_guid()作为主键的优缺点

3.1 优点

(1)序列从起点开始进行自增,但只能保持在单个实例里唯一。因此不适合用作并行或远程环境的主键,因为各自环境里的序列可能会生成相同的数字,从而导致冲突的发生。而SYS_GUID会保证它创建的标识符在每个数据库里都是唯一的。
(2)序列必须是DML陈述式的一部分,因此它需要一个到数据库的往返过程(否则它就不能保证其值是唯一的)。SYS_GUID不需要对数据库进行访问的时间戳和机器标识符,这就节省了查询的消耗。

3.2 缺点

(1)从空间上,相同条件下,使用SYS_GUID做主键比用Sequence做主键,表多消耗了空间。
(2)用SYS_GUID使用时相对不太方便,必须(手动)输入或者通过脚本来填充相应的字段。

4 SYS_GUID()函数第一次调用慢的原因

1. SYS_GUID() 函数的工作原理

SYS_GUID() 函数的作用是生成一个全球唯一的 16 字节(128 位)的原始二进制值。为了保证全球唯一性,它通常会结合以下元素:

  • 时间戳:精确到微秒级。

  • 系统标识:例如服务器的 MAC 地址。

  • 随机数: cryptographically secure random number,这是导致速度变化的关键。

2. 为什么第一次调用特别慢?(~10秒)

当数据库实例刚刚启动,或者某个会话是第一次请求一个密码学安全的随机数时,会发生以下情况:

  1. 初始化请求: Oracle 代码调用操作系统提供的安全随机数生成器接口(在 Linux 上通常是 /dev/urandom)。

  2. 熵池饥饿: 安全随机数生成器的核心是“熵池”。熵可以理解为系统的“随机性噪音”,它来自于硬件中断、键盘敲击、鼠标移动、磁盘 I/O 时间等各种不可预测的事件。在系统刚启动时,熵池中积累的随机性熵很少,处于“饥饿”状态。

  3. 阻塞等待: 为了保证随机数的安全性,当熵池中的熵不足时,对 /dev/urandom 的读取可能会被阻塞或变得极慢。操作系统会等待收集到足够的环境噪音来“哺育”熵池,然后才能产生出高质量的随机数。这个等待和收集熵的过程,就是那 10 秒钟延迟的来源。

3. 为什么后续调用就快了?

一旦完成了第一次艰难的初始化:

  1. 熵池已就绪: 第一次调用成功后,熵池已经被填充到一定水平。

  2. 缓存机制: 更重要的是,Oracle(以及操作系统)会有一定的缓存或预取机制。在第一次等待之后,系统已经预生成并缓存了足够的随机数据块,后续的请求可以直接从缓存中快速获取数据,而无需再次阻塞等待熵的积累。

  3. 持续喂养: 即使在后续调用中,系统的后台进程也在不断地收集新的熵来补充熵池,确保其始终有足够的随机性储备,避免了再次出现饥饿状态。

这就好比从一口很深的井里打水:

  • 第一次打水:需要先安装辘轳,放下水桶,费很大力气才能把第一桶水打上来(耗时很长)。

  • 后续打水:井绳和水桶都已经就位,并且井边可能已经有一桶储备水,打水就变得非常快了。

总结与启示

 
阶段原因结果
第一次调用 初始化安全随机数生成器,熵池不足导致阻塞等待 速度极慢(约10秒)
后续调用 熵池已充足,且有预生成的随机数缓存可用 速度极快(毫秒级)

对开发的启示:

  • 如果你的应用程序在启动后需要立即使用 SYS_GUID()(例如,为第一个用户会话生成ID),需要意识到可能会有这个初始延迟。

  • 对于一些批量插入操作,完全不必担心性能,因为只有“第一个”GUID会有成本,后续的代价极小。

  • 在某些极端的虚拟化或容器环境中,如果硬件中断等熵源很少,可能会导致熵池积累缓慢,使得这个问题更加频繁或严重。在这种情况下,有时会使用“熵池代理”如 haveged 来加速熵的生成。

原文链接:https://blog.csdn.net/qq_41861832/article/details/128205231

posted @ 2023-08-02 21:37  DAYTOY-105  阅读(477)  评论(0)    收藏  举报