
GaussDB(DWS)在并发执行DDL过程中,会涉及元数据失效的问题,那么语句执行线程如何及时通知其他线程元数据失效呢?答案是共享消息队列。共享消息队列主要用于存储失效消息,当线程执行DDL后,会将本地的失效消息提交到到共享消息队列中,并通知其他线程处理元数据失效。在本文中,将详细说明共享消息队列实现机制。在讲解过程中,大家有任何建议,欢迎留言讨论!

共享消息队列是什么?
共享消息队列存储结构

共享消息队列接口实现

若共享内存中线程对应的hasMessage为True,则表示有失效消息需要读取,否则直接返回,无新的失效消息。 读取失效消息过程中,需要持有读共享锁,以保证读取的消息不会被清理掉。 若读取失效消息过程中,发现resetState被置为True,说明该线程已经无法使用共享消息队列中的消息进行追增,需要对缓存进行全失效。缓存全失效相当于追增全部数据,需要将nextMsgNum置为maxMsgNum。缓存全失效将严重降低SQL执行性能,尽量减少缓存全失效的发生频率。 在追增数据过程中,会推进线程自身的nextMsgNum,以标记数据追增位置。

如图所示,为失效消息写入过程。有以下几个关键点:
写入失效消息过程,需要调用清理共享消息队列接口,以保证有足够多的空位写入失效消息。 在写入失效消息过程中,会更新maxMsgNum。 写入失效消息完毕以后,需要将其他线程的hasMessage标记为True。 写入失效消息过程,需要持排他写锁,阻塞其他线程写操作,但不阻塞读。

如图所示,清理共享消息队列过程中,有以下几个关键点:
清理共享消息队列需要持有排他读锁和排他写锁,阻塞读过程。其主要原因是,清理共享消息队列会推进minMsgNum,若不持读锁,可能导致nextMsgNum读取过期数据。
清理共享消息队列会推进minMsgNum。
清理共享消息队列过程,会将所有没有及时追增失效消息的线程执行全失效。
在清理共享消息队列最后步骤,会对距离minMsgNum最近的线程,发送追增信号,以确保不会频繁发生全失效。该步骤主要考虑的情况是,若线程长时间处于idle状态,需要外部信号触发其及时追增消息。
NOTE:清理共享消息队列过程,实际上是推进minMsgNum的过程,同时对所有没有及时追增失效消息的线程执行全失效。根据以上共享消息队列接口可知,读取共享消息队列主要负责推进各个线程自身的nextMsgNum;写入失效消息主要负责推进maxMsgNum;清理共享消息队列主要负责推进minMsgNum。通过共享消息队列,可有效实现各个线程之间的数据同步。

文章转载自GaussDB DWS,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。






