<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael</title>
    <description>The latest articles on DEV Community by Michael (@michaelfv).</description>
    <link>https://dev.to/michaelfv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3830930%2F34d5c2f8-f162-4df3-865b-34a96a64ac17.png</url>
      <title>DEV Community: Michael</title>
      <link>https://dev.to/michaelfv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michaelfv"/>
    <language>en</language>
    <item>
      <title>Pure Shell Script to Expand IPv6 Addresses</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Tue, 07 Jul 2026 13:33:45 +0000</pubDate>
      <link>https://dev.to/michaelfv/pure-shell-script-to-expand-ipv6-addresses-1g72</link>
      <guid>https://dev.to/michaelfv/pure-shell-script-to-expand-ipv6-addresses-1g72</guid>
      <description>&lt;p&gt;When deploying a &lt;strong&gt;gbase database&lt;/strong&gt; cluster, you often need to handle IPv6 addresses in configuration files. Many tools require the full 8‑segment, 4‑digit hexadecimal format, while real‑world addresses often come in compressed notation (e.g., &lt;code&gt;2001:db8::1&lt;/code&gt;). This article presents a pure Bash script that expands any compressed IPv6 address to the complete, canonical form, with built‑in validation and prefix handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Expands any compressed IPv6 address (including &lt;code&gt;::&lt;/code&gt; zero‑compression) into 8 segments of 4 lowercase hex digits&lt;/li&gt;
&lt;li&gt;Handles addresses with prefixes (e.g., &lt;code&gt;2001:db8::1/64&lt;/code&gt;), with an option to preserve or strip the prefix&lt;/li&gt;
&lt;li&gt;Built‑in validation: illegal characters, &lt;code&gt;::&lt;/code&gt; occurrence count, segment length, and hex validity&lt;/li&gt;
&lt;li&gt;Pure Shell implementation; relies only on standard tools (&lt;code&gt;bc&lt;/code&gt;, &lt;code&gt;printf&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;SCRIPT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

show_help&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
Usage: &lt;/span&gt;&lt;span class="nv"&gt;$SCRIPT_NAME&lt;/span&gt;&lt;span class="sh"&gt; [options] &amp;lt;IPv6 address&amp;gt;

Expands a compressed IPv6 address to the full 8‑segment, 4‑digit format.
Supports address validation and prefix handling.

Options:
    -h, --help      Show this help message and exit
    -p, --prefix    Preserve the prefix (e.g., 2001:db8::1/64); by default only the address part is expanded

Examples:
    &lt;/span&gt;&lt;span class="nv"&gt;$SCRIPT_NAME&lt;/span&gt;&lt;span class="sh"&gt; 2001:db8::1
    &lt;/span&gt;&lt;span class="nv"&gt;$SCRIPT_NAME&lt;/span&gt;&lt;span class="sh"&gt; -p ::1/128
    &lt;/span&gt;&lt;span class="nv"&gt;$SCRIPT_NAME&lt;/span&gt;&lt;span class="sh"&gt; fe80::1234:5678:9abc:def0
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

validate_ipv6_chars&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^[0-9a-fA-F:/]+&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: IPv6 address contains illegal characters (only 0-9/a-f/A-F/:/ allowed)"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
        &lt;span class="nb"&gt;exit &lt;/span&gt;1
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

expand_ipv6_core&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;pure_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;expanded_segments&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;

    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;colon_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"::"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pure_addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$colon_count&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; 1 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Invalid IPv6 address (:: can appear only once)"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
        &lt;span class="nb"&gt;exit &lt;/span&gt;1
    &lt;span class="k"&gt;fi

    if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pure_addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"::"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"0000:0000:0000:0000:0000:0000:0000:0000"&lt;/span&gt;
        &lt;span class="k"&gt;return
    fi

    &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;temp_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pure_addr&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;::/:__ZERO__:&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;segments&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;
    &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;: &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-ra&lt;/span&gt; segments &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$temp_addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;filtered_segments&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;seg &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;filtered_segments+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;fi
    done
    &lt;/span&gt;&lt;span class="nv"&gt;segments&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;filtered_segments&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;zero_pos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-1&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;seg_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;!segments[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__ZERO__"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nv"&gt;zero_pos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;
            &lt;span class="nb"&gt;break
        &lt;/span&gt;&lt;span class="k"&gt;fi
    done

    &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;new_segments&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$zero_pos&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;fill_zeros&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;seg_count &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$fill_zeros&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: IPv6 address has too many segments (more than 8)"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
            &lt;span class="nb"&gt;exit &lt;/span&gt;1
        &lt;span class="k"&gt;fi
        for&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; i&amp;lt;zero_pos&lt;span class="p"&gt;;&lt;/span&gt; i++&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
            &lt;/span&gt;new_segments+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;done
        for&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; i&amp;lt;fill_zeros&lt;span class="p"&gt;;&lt;/span&gt; i++&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
            &lt;/span&gt;new_segments+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;done
        for&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;zero_pos+1&lt;span class="p"&gt;;&lt;/span&gt; i&amp;lt;seg_count&lt;span class="p"&gt;;&lt;/span&gt; i++&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
            &lt;/span&gt;new_segments+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;done
    else
        &lt;/span&gt;&lt;span class="nv"&gt;new_segments&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;new_segments&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 8 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: IPv6 address segment count wrong (must be exactly 8 when no ::)"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
            &lt;span class="nb"&gt;exit &lt;/span&gt;1
        &lt;span class="k"&gt;fi
    fi

    for &lt;/span&gt;seg &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_segments&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;expanded_segments+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"0000"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue
        fi

        if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;seg&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; 4 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: IPv6 segment '&lt;/span&gt;&lt;span class="nv"&gt;$seg&lt;/span&gt;&lt;span class="s2"&gt;' too long (max 4 digits)"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
            &lt;span class="nb"&gt;exit &lt;/span&gt;1
        &lt;span class="k"&gt;fi

        if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^[0-9a-fA-F]&lt;span class="o"&gt;{&lt;/span&gt;1,4&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: IPv6 segment '&lt;/span&gt;&lt;span class="nv"&gt;$seg&lt;/span&gt;&lt;span class="s2"&gt;' contains illegal characters"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
            &lt;span class="nb"&gt;exit &lt;/span&gt;1
        &lt;span class="k"&gt;fi

        &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;seg_upper&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'a-f'&lt;/span&gt; &lt;span class="s1"&gt;'A-F'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;seg_10&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ibase=16; &lt;/span&gt;&lt;span class="nv"&gt;$seg_upper&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | bc&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;seg_4digit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"%04x"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seg_10&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'A-F'&lt;/span&gt; &lt;span class="s1"&gt;'a-f'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
        expanded_segments+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$seg_4digit&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;done

    &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;expanded_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;expanded_segments&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$expanded_addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

expand_ipv6&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;keep_prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;pure_addr
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ / &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;pure_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;%/*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nv"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;#*/&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$prefix&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^[0-9]+&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$prefix&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$prefix&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-gt&lt;/span&gt; 128 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Invalid IPv6 prefix '&lt;/span&gt;&lt;span class="nv"&gt;$prefix&lt;/span&gt;&lt;span class="s2"&gt;' (must be 0‑128)"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
            &lt;span class="nb"&gt;exit &lt;/span&gt;1
        &lt;span class="k"&gt;fi
    else
        &lt;/span&gt;&lt;span class="nv"&gt;pure_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi

    &lt;/span&gt;validate_ipv6_chars &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pure_addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;expanded_addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;expand_ipv6_core &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pure_addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$keep_prefix&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$prefix&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;expanded_addr&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;prefix&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$expanded_addr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;KEEP_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
&lt;span class="nv"&gt;IPV6_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-gt&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="nt"&gt;-h&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nt"&gt;--help&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            show_help
            &lt;span class="nb"&gt;exit &lt;/span&gt;0
            &lt;span class="p"&gt;;;&lt;/span&gt;
        &lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;KEEP_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
            &lt;span class="nb"&gt;shift&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
        &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IPV6_ADDR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;&lt;span class="nv"&gt;IPV6_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
                &lt;span class="nb"&gt;shift
            &lt;/span&gt;&lt;span class="k"&gt;else
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Extra argument '&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
                show_help &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
                &lt;span class="nb"&gt;exit &lt;/span&gt;1
            &lt;span class="k"&gt;fi&lt;/span&gt;
            &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done

if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IPV6_ADDR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: IPv6 address is required"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    show_help &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;expand_ipv6 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IPV6_ADDR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$KEEP_PREFIX&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the Script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ipv6_expand.sh &lt;span class="nt"&gt;-p&lt;/span&gt; 2001:1::5:0:0:8/64
2001:0001:0000:0000:0005:0000:0000:0008/64
&lt;span class="nv"&gt;$ &lt;/span&gt;./ipv6_expand.sh 2001:1::5:0:0:8
2001:0001:0000:0000:0005:0000:0000:0008
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When configuring inter‑node communication in a &lt;strong&gt;gbase database&lt;/strong&gt; cluster that involves IPv6, this script helps you normalize addresses — ensuring they are consistently written in configuration files and simplifying address comparisons during automated deployments.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>shell</category>
      <category>operations</category>
    </item>
    <item>
      <title>Who Decides the SSH Cipher? Why the Client's Preference Matters</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Mon, 06 Jul 2026 12:43:24 +0000</pubDate>
      <link>https://dev.to/michaelfv/who-decides-the-ssh-cipher-why-the-clients-preference-matters-1j52</link>
      <guid>https://dev.to/michaelfv/who-decides-the-ssh-cipher-why-the-clients-preference-matters-1j52</guid>
      <description>&lt;p&gt;A common misconception is that the SSH server unilaterally chooses the encryption algorithm for a connection. In reality, the negotiation follows a strict rule: &lt;strong&gt;the server picks the first algorithm from the client's list that it also supports&lt;/strong&gt;. This means the client's preference order directly determines the final cipher — and putting the best algorithm first can significantly improve performance in your &lt;strong&gt;gbase database&lt;/strong&gt; environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Standards Say
&lt;/h2&gt;

&lt;p&gt;The OpenSSH documentation states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The first algorithm in the list (that the client offers to the server) that matches an offer from the server, is what will be selected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;RFC 4253, the SSH Transport Layer Protocol, is even more explicit:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The first algorithm on the client's name-list that satisfies the requirements and is also supported by the server &lt;strong&gt;MUST&lt;/strong&gt; be chosen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How It Plays Out
&lt;/h2&gt;

&lt;p&gt;Imagine a client sends this cipher list (in order of preference): &lt;code&gt;A, B, C, D, E&lt;/code&gt;&lt;br&gt;
The server supports these ciphers: &lt;code&gt;B, C, D, E, A&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Both sides support &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt;. According to the rule, the &lt;strong&gt;first match in the client's list&lt;/strong&gt; is &lt;code&gt;A&lt;/code&gt; — so &lt;code&gt;A&lt;/code&gt; becomes the session cipher. The server's own preferred order (&lt;code&gt;B&lt;/code&gt; first) is irrelevant; the decision is client‑driven.&lt;/p&gt;
&lt;h2&gt;
  
  
  Practical Impact for GBase 8a
&lt;/h2&gt;

&lt;p&gt;In a GBase 8a cluster, SSH underpins remote management and SFTP data loading. If you want to prioritise a modern, fast cipher like &lt;code&gt;chacha20-poly1305@openssh.com&lt;/code&gt; or &lt;code&gt;aes128-ctr&lt;/code&gt; over slower legacy ones, adjust the &lt;code&gt;Ciphers&lt;/code&gt; directive in your client's &lt;code&gt;~/.ssh/config&lt;/code&gt; or &lt;code&gt;/etc/ssh/ssh_config&lt;/code&gt; and place the preferred algorithm &lt;strong&gt;first&lt;/strong&gt;. This simple ordering can measurably improve throughput for large data transfers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host *
    Ciphers chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By controlling the cipher preference on the client side, you keep your &lt;strong&gt;gbase database&lt;/strong&gt; operations both secure and fast — no server‑side changes required.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>数据库</category>
      <category>performance</category>
    </item>
    <item>
      <title>Quick Diagnostic Commands for GBase 8a Cluster Glitches</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 05 Jul 2026 15:43:00 +0000</pubDate>
      <link>https://dev.to/michaelfv/quick-diagnostic-commands-for-gbase-8a-cluster-glitches-4e25</link>
      <guid>https://dev.to/michaelfv/quick-diagnostic-commands-for-gbase-8a-cluster-glitches-4e25</guid>
      <description>&lt;p&gt;When a &lt;strong&gt;gbase database&lt;/strong&gt; cluster experiences sporadic slowdowns, the cause is often isolated to a single unhealthy node. These commands form a rapid triage flow — from cluster‑wide status down to a specific node's operating system resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Cluster Health Check
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;gcadmin&lt;/code&gt; at the OS prompt. Look for any node in &lt;code&gt;CLOSE&lt;/code&gt; or &lt;code&gt;OFFLINE&lt;/code&gt; state. If everything is &lt;code&gt;OPEN&lt;/code&gt; and the cluster is &lt;code&gt;ACTIVE&lt;/code&gt;, the problem lies deeper.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Find the Longest‑Running SQL on Coordinators
&lt;/h2&gt;

&lt;p&gt;Identify queries that have been executing far longer than normal. This is the first suspect list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;COORDINATOR_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COORDINATORS_TASK_INFORMATION&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Pinpoint the Straggling Data Node
&lt;/h2&gt;

&lt;p&gt;Cross‑reference with the data‑node task view. If a query shows 3,600 seconds at the coordinator level but 2,900 seconds on a single data node, that node is your bottleneck.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;NODE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GNODES_TASK_INFORMATION&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'%information_schema.processlist%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;node_name&lt;/code&gt; value (e.g., &lt;code&gt;node3&lt;/code&gt;) can be matched to the &lt;code&gt;Nodename&lt;/code&gt; field in &lt;code&gt;gcadmin showcluster&lt;/code&gt; to obtain the actual IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Log into the Suspicious Node and Inspect
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Operating System Errors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dmesg &lt;span class="nt"&gt;-T&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for hardware faults, filesystem issues, or OOM events.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Disk I/O Saturation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iostat &lt;span class="nt"&gt;-xdc&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;%util&lt;/code&gt; is pegged at 100% or the &lt;code&gt;await&lt;/code&gt; column exceeds 200, the node is almost certainly I/O‑bound.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 Memory and SWAP Pressure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;top
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;High SWAP usage combined with low free memory will cripple query performance instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Check Data Loading Throughput
&lt;/h2&gt;

&lt;p&gt;If import speed is the concern, query the real‑time load status view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;tb_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ELAPSED_TIME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;avg_speed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;total_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loaded_size&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_status&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;avg_speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a rule of thumb, SFTP load speeds should stay above &lt;strong&gt;8 MB/s&lt;/strong&gt;, while FTP typically reaches &lt;strong&gt;40–100 MB/s&lt;/strong&gt;. Values far below these thresholds suggest network issues, misconfigured load parameters, or disk bottlenecks on the target node.&lt;/p&gt;

&lt;p&gt;Keep these commands in your toolkit and you'll turn vague "the cluster feels slow" reports into precise, actionable diagnostics for your &lt;strong&gt;gbase database&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>数据库</category>
      <category>performance</category>
    </item>
    <item>
      <title>Demystifying SSH with -vvv: How GBase 8a's Underlying Connection Negotiates Encryption</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 05 Jul 2026 14:39:00 +0000</pubDate>
      <link>https://dev.to/michaelfv/demystifying-ssh-with-vvv-how-gbase-8as-underlying-connection-negotiates-encryption-4m0g</link>
      <guid>https://dev.to/michaelfv/demystifying-ssh-with-vvv-how-gbase-8as-underlying-connection-negotiates-encryption-4m0g</guid>
      <description>&lt;p&gt;SSH is the backbone of GBase 8a cluster management, powering everything from remote commands to SFTP data loading. When connection behavior seems sluggish or you need to optimize transport performance, understanding the protocol's inner workings becomes invaluable. This guide walks through the complete SSH connection lifecycle using the verbose &lt;code&gt;ssh -vvv&lt;/code&gt; output, revealing how the server and client agree on encryption—and why that matters for your &lt;strong&gt;gbase database&lt;/strong&gt; environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking Down the Connection
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The Handshake: TCP Connection
&lt;/h3&gt;

&lt;p&gt;The client resolves the target IP, loads its configuration, and completes a standard TCP three-way handshake on port 22.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;debug1&lt;/span&gt;: Connecting to &lt;span class="m"&gt;10&lt;/span&gt;.0.2.201 [10.0.2.201] port &lt;span class="m"&gt;22&lt;/span&gt;.
&lt;span class="k"&gt;debug1&lt;/span&gt;: Connection established.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Identity File Scan
&lt;/h3&gt;

&lt;p&gt;SSH tries public‑key authentication first, scanning common private‑key paths. When none are found, it silently falls back to password authentication later.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Protocol Version Agreement
&lt;/h3&gt;

&lt;p&gt;Both sides exchange their software version strings to ensure they speak the same &lt;code&gt;SSH-2.0&lt;/code&gt; protocol. No mismatches found here — good to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;debug1&lt;/span&gt;: Local version string SSH-2.0-OpenSSH_7.4
&lt;span class="k"&gt;debug1&lt;/span&gt;: Remote protocol version &lt;span class="m"&gt;2&lt;/span&gt;.0, remote software version OpenSSH_7.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Cipher Suite Negotiation (The Critical Part)
&lt;/h3&gt;

&lt;p&gt;This is where performance and security intersect. The client sends its list of supported ciphers in order of preference; the server replies with its own list; then &lt;strong&gt;the server makes the final call&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client's proposal&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;debug2&lt;/span&gt;: ciphers ctos: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Server's capabilities&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;debug2&lt;/span&gt;: ciphers ctos: chacha20-poly1305@openssh.com,aes128-ctr,...,blowfish-cbc,3des-cbc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The server's final selection&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;debug1&lt;/span&gt;: kex: server-&amp;gt;client cipher: chacha20-poly1305@openssh.com MAC: &amp;lt;implicit&amp;gt; compression: &lt;span class="no"&gt;none&lt;/span&gt;
&lt;span class="k"&gt;debug1&lt;/span&gt;: kex: client-&amp;gt;server cipher: chacha20-poly1305@openssh.com MAC: &amp;lt;implicit&amp;gt; compression: &lt;span class="no"&gt;none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the client prioritized &lt;code&gt;chacha20-poly1305@openssh.com&lt;/code&gt; and the server supports it, this modern, high‑performance authenticated cipher is chosen. The built‑in Poly1305 MAC means no separate message authentication algorithm is needed—hence &lt;code&gt;&amp;lt;implicit&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Host Authentication
&lt;/h3&gt;

&lt;p&gt;The client verifies the server's ECDSA host key against its &lt;code&gt;known_hosts&lt;/code&gt; file. If the fingerprint matches, the connection is trusted; otherwise, SSH warns of a potential man‑in‑the‑middle attack.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Session Key Generation
&lt;/h3&gt;

&lt;p&gt;Using the negotiated key‑exchange algorithm, both sides independently compute a symmetric session key. From this point forward, all traffic is encrypted with the agreed &lt;code&gt;chacha20-poly1305&lt;/code&gt; cipher.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. User Authentication
&lt;/h3&gt;

&lt;p&gt;The client now tries to log in, cycling through available methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GSSAPI (Kerberos) – failed, no credentials&lt;/li&gt;
&lt;li&gt;Public key – failed, no private key files found&lt;/li&gt;
&lt;li&gt;Password – prompts the user for the password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This explains why your server may still ask for a password even when you haven't explicitly configured one—it's the fallback after preferred methods fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Your GBase 8a Cluster
&lt;/h2&gt;

&lt;p&gt;When transferring large datasets via SFTP or running heavy remote commands, the negotiated cipher directly impacts throughput. The &lt;code&gt;-vvv&lt;/code&gt; output gives you an instant view of which algorithm is in use. If you see an outdated cipher like &lt;code&gt;aes128-cbc&lt;/code&gt; or &lt;code&gt;3des-cbc&lt;/code&gt;, it may be time to adjust the &lt;code&gt;Ciphers&lt;/code&gt; directive in &lt;code&gt;sshd_config&lt;/code&gt; to prefer modern, faster algorithms like &lt;code&gt;chacha20-poly1305&lt;/code&gt; or &lt;code&gt;aes128-ctr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A smooth, high‑performance SSH layer is the first step toward reliable operations in any &lt;strong&gt;gbase database&lt;/strong&gt; environment. Next time a connection feels slow, don't guess—run &lt;code&gt;ssh -vvv&lt;/code&gt; and read the negotiation line.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>数据库</category>
      <category>security</category>
    </item>
    <item>
      <title>Database Industry Trends and Technical Observations</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 05 Jul 2026 14:37:06 +0000</pubDate>
      <link>https://dev.to/michaelfv/database-industry-trends-and-technical-observations-43ii</link>
      <guid>https://dev.to/michaelfv/database-industry-trends-and-technical-observations-43ii</guid>
      <description>&lt;h1&gt;
  
  
  Database Industry Trends and Technical Observations
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In a recent GBASE Tech Cloud Talk, Jiang Chunyu, an industry expert, provided an in-depth analysis of the database industry landscape and emerging technical trends. The talk highlighted the rapid evolution of database technologies and the shifting market dynamics globally and in China.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Industry Trends
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Global Market Growth
&lt;/h3&gt;

&lt;p&gt;The database market continues to expand, driven by digital transformation across industries. Cloud databases are becoming the dominant deployment model, with cloud-native architectures gaining traction.&lt;/p&gt;

&lt;h3&gt;
  
  
  China's Database Ecosystem
&lt;/h3&gt;

&lt;p&gt;China's database industry is experiencing significant growth, fueled by government policies and increasing demand for domestic solutions. The market is witnessing a surge in new database products and startups, focusing on both relational and NoSQL databases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Trends
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Multi-Model Convergence
&lt;/h3&gt;

&lt;p&gt;Modern databases are increasingly supporting multiple data models (relational, document, graph, etc.) within a single system. This reduces complexity for developers and improves operational efficiency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud-Native Architecture
&lt;/h3&gt;

&lt;p&gt;Cloud-native databases leverage containerization, microservices, and serverless computing to provide elasticity, scalability, and cost efficiency. They are well-suited for dynamic workloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Integration
&lt;/h3&gt;

&lt;p&gt;Artificial intelligence is being integrated into database management systems for autonomous tuning, query optimization, and anomaly detection. This trend is expected to accelerate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The database industry is at a pivotal moment, with rapid innovation in both technology and business models. Staying updated with these trends is crucial for developers and enterprises alike.&lt;/p&gt;

</description>
      <category>database</category>
      <category>cloudnative</category>
      <category>ai</category>
      <category>datamanagement</category>
    </item>
    <item>
      <title>GBase 8s Kernel Evolution: Expressing User Understanding Through Product</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 05 Jul 2026 14:29:06 +0000</pubDate>
      <link>https://dev.to/michaelfv/gbase-8s-kernel-evolution-expressing-user-understanding-through-product-j6d</link>
      <guid>https://dev.to/michaelfv/gbase-8s-kernel-evolution-expressing-user-understanding-through-product-j6d</guid>
      <description>&lt;h1&gt;
  
  
  GBase 8s Kernel Evolution: Expressing User Understanding Through Product
&lt;/h1&gt;

&lt;p&gt;GBase 8s, a database product, is undergoing a kernel-level evolution that reflects a profound understanding of its users. This article explores how the product's core advancements are driven by user needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Philosophy
&lt;/h2&gt;

&lt;p&gt;The evolution of GBase 8s is not just about technical upgrades; it's about aligning the product with real-world user scenarios. By focusing on kernel-level changes, the product aims to deliver better performance, stability, and usability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Improvements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance Optimization&lt;/strong&gt;: Kernel enhancements ensure faster query processing and data management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stability Enhancements&lt;/strong&gt;: Core system improvements reduce downtime and increase reliability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-Centric Design&lt;/strong&gt;: Every change is rooted in understanding user pain points and requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;GBase 8s's kernel evolution is a testament to how a product can evolve by truly listening to its users. This approach sets a benchmark for database technology development.&lt;/p&gt;

</description>
      <category>gbase8s</category>
      <category>database</category>
      <category>kernelevolution</category>
      <category>userexperience</category>
    </item>
    <item>
      <title>GBase 8a: A Decade of Iteration, Empowering Digital Business</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 05 Jul 2026 14:13:24 +0000</pubDate>
      <link>https://dev.to/michaelfv/gbase-8a-a-decade-of-iteration-empowering-digital-business-24i3</link>
      <guid>https://dev.to/michaelfv/gbase-8a-a-decade-of-iteration-empowering-digital-business-24i3</guid>
      <description>&lt;h3&gt;
  
  
  GBase 8a: A Decade of Iteration, Empowering Digital Business
&lt;/h3&gt;

&lt;p&gt;In the rapidly evolving landscape of data analytics, GBase 8a by Nandu General stands out as a homegrown MPP (Massively Parallel Processing) analytical database that has undergone over ten years of continuous technical iteration. From its early standalone version to the current cloud-native data warehouse and lakehouse architecture, GBase 8a has consistently adapted to meet the growing demands of modern enterprises.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Evolution Path
&lt;/h4&gt;

&lt;p&gt;GBase 8a's journey began as a single-node analytical database, designed to handle structured data with high performance. Over time, it evolved into a distributed MPP system, enabling parallel processing across multiple nodes for faster query execution. The next leap was the integration with cloud environments, resulting in a cloud data warehouse that offers elasticity and scalability. Most recently, GBase 8a adopted a lakehouse architecture, bridging the gap between data lakes and warehouses by supporting both structured and unstructured data, while maintaining ACID transactions and real-time analytics.&lt;/p&gt;

&lt;h4&gt;
  
  
  Introducing DataAgent: The Intelligent Agent
&lt;/h4&gt;

&lt;p&gt;The latest version of GBase 8a introduces DataAgent, an intelligent agent capability that automates data management tasks. DataAgent can monitor system health, optimize query performance, and even predict resource needs based on historical patterns. This feature reduces the operational burden on DBAs and enhances overall system efficiency.&lt;/p&gt;

&lt;h4&gt;
  
  
  Real-World Deployments
&lt;/h4&gt;

&lt;p&gt;GBase 8a has been deployed at scale in critical sectors such as finance, telecommunications, and government. For instance, in financial services, it supports real-time risk analysis and fraud detection on petabytes of transaction data. In telecom, it powers customer analytics and network optimization. Government agencies use it for smart city initiatives and public data services.&lt;/p&gt;

&lt;h4&gt;
  
  
  Core Value in Digital Transformation
&lt;/h4&gt;

&lt;p&gt;As organizations accelerate their digital transformation, GBase 8a provides a robust foundation for data-driven decision-making. Its ability to handle PB-level data with real-time analytics, combined with cost-effective scalability, makes it a key enabler for businesses seeking to leverage data as a strategic asset.&lt;/p&gt;

&lt;p&gt;In summary, GBase 8a's continuous innovation—from standalone to cloud, lakehouse, and AI-powered agents—demonstrates its commitment to meeting the evolving needs of digital business. For developers and data engineers, it offers a reliable, high-performance platform for building next-generation analytics applications.&lt;/p&gt;

</description>
      <category>gbase8a</category>
      <category>mpp</category>
      <category>dataanalytics</category>
      <category>clouddatawarehouse</category>
    </item>
    <item>
      <title>How GBase 8a Handles Masked Columns in WHERE, GROUP BY, and Projections</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 05 Jul 2026 13:55:00 +0000</pubDate>
      <link>https://dev.to/michaelfv/how-gbase-8a-handles-masked-columns-in-where-group-by-and-projections-3c8f</link>
      <guid>https://dev.to/michaelfv/how-gbase-8a-handles-masked-columns-in-where-group-by-and-projections-3c8f</guid>
      <description>&lt;p&gt;GBase 8a supports data masking to protect sensitive information. But when a masked column appears in a &lt;code&gt;WHERE&lt;/code&gt; clause, a &lt;code&gt;GROUP BY&lt;/code&gt;, an &lt;code&gt;ORDER BY&lt;/code&gt;, or when its data is copied to another column — does the database operate on the original values or the masked values? This article clarifies the behaviour through a set of direct tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Setup
&lt;/h2&gt;

&lt;p&gt;Create a table with a default masking policy on an integer column and insert sample data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"testmask"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="n"&gt;MASKED&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;FUNCTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'DEFAULT()'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Tests and Findings
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Projection Returns Masked Values
&lt;/h3&gt;

&lt;p&gt;A user without unmask privileges sees all &lt;code&gt;id&lt;/code&gt; values replaced by the default mask &lt;code&gt;0&lt;/code&gt;. This is the basic masking behaviour.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- All five rows show id = 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. WHERE Filter Uses Original Values
&lt;/h3&gt;

&lt;p&gt;A query with &lt;code&gt;WHERE id = 1&lt;/code&gt; returns exactly one row. Although the projected &lt;code&gt;id&lt;/code&gt; still displays the masked value &lt;code&gt;0&lt;/code&gt;, the filter condition operates on the original data. The user can infer that a row with &lt;code&gt;id = 1&lt;/code&gt; exists, but the actual value is never revealed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- One row returned; projected id is 0, but the predicate matched the original value 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. GROUP BY Uses Original Values
&lt;/h3&gt;

&lt;p&gt;When grouping on a masked column, the aggregation is performed on the original data. The modulo operation &lt;code&gt;id % 3&lt;/code&gt; correctly reflects the distribution of the original values 1, 2, 3, 4, and 99.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt; &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Grouping is based on the original id values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. ORDER BY Uses Original Values
&lt;/h3&gt;

&lt;p&gt;Sorting on a masked column also uses the original data. Observing the &lt;code&gt;rowid&lt;/code&gt; alongside the result confirms that rows are ordered by the original &lt;code&gt;id&lt;/code&gt; descending, not by the uniform masked value &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;rowid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Ordering is based on the original id values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Data Migration Writes Masked Values
&lt;/h3&gt;

&lt;p&gt;When a masked column's data is moved — either via &lt;code&gt;UPDATE&lt;/code&gt; to another column, or via &lt;code&gt;INSERT SELECT&lt;/code&gt; into a new table — &lt;strong&gt;the physical data written is the masked value&lt;/strong&gt;. The target column or table does not inherit the masking policy; it simply stores the already‑masked &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- UPDATE migration&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;id2&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;id2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- id2 is all 0, and id2 column has no mask&lt;/span&gt;

&lt;span class="c1"&gt;-- INSERT SELECT migration&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;testmask2&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;testmask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;testmask2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- both id and id2 are all 0, no mask defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The behaviour of data masking in a &lt;strong&gt;gbase database&lt;/strong&gt; follows a clear principle:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Uses Masked Data&lt;/th&gt;
&lt;th&gt;Uses Original Data&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Projection (returned to client)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data migration (UPDATE / INSERT SELECT)&lt;/td&gt;
&lt;td&gt;✅ (writes masked value)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WHERE filtering&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GROUP BY aggregation&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ORDER BY sorting&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Masking is applied &lt;strong&gt;only when the column is projected&lt;/strong&gt; — either returned to the application or copied to another storage location. When the column participates in filtering, grouping, or sorting, the engine operates on the original, unmasked values. This behaviour aligns with Oracle Data Redaction policies and is essential to understand when designing secure, yet performant, queries in GBASE's GBase 8a.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>数据库</category>
      <category>sql</category>
    </item>
    <item>
      <title>GBase 8a Performance Anomaly Case Study: How a Single Parameter Change Sparked a Chain Reaction</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 05 Jul 2026 13:25:04 +0000</pubDate>
      <link>https://dev.to/michaelfv/gbase-8a-performance-anomaly-case-study-how-a-single-parameter-change-sparked-a-chain-reaction-1epa</link>
      <guid>https://dev.to/michaelfv/gbase-8a-performance-anomaly-case-study-how-a-single-parameter-change-sparked-a-chain-reaction-1epa</guid>
      <description>&lt;p&gt;One seemingly innocent parameter adjustment — increasing &lt;code&gt;group_concat_max_len&lt;/code&gt; to accommodate a business requirement — caused a cascade of performance degradation across a GBase 8a production cluster. A simple TOP‑N query that normally completed in seconds suddenly ran for over three hours, and multiple other queries on the same node slowed to a crawl. This article reconstructs the full investigation, from identifying the bottlenecked node to uncovering the hidden chain that turned a 200,000‑row sort into a 10 TB disk write storm.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Symptom: One Node’s I/O Pegged at 100%
&lt;/h2&gt;

&lt;p&gt;Monitoring showed several queries exceeding 10,000 seconds of execution time. Cross‑referencing the coordinator‑level task view and the data‑node task view revealed that &lt;strong&gt;all slow queries were pinned to node3&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Coordinators&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;COORDINATOR_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COORDINATORS_TASK_INFORMATION&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Data nodes – all problematic queries on node3&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;NODE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="k"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GNODES_TASK_INFORMATION&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'%information_schema.processlist%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On node3, the &lt;code&gt;iostat&lt;/code&gt; output showed disk utilisation at a flat 100%, with write rates hitting &lt;strong&gt;900 MB/s&lt;/strong&gt;. OS monitoring logs confirmed the spike started exactly when the slow queries began. Digging into the database temporary directory, we found thousands of files with a total size exceeding &lt;strong&gt;10 TB&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pinpointing the Culprit Query and Intermediate Results
&lt;/h2&gt;

&lt;p&gt;The slowest query followed a pattern of three subqueries &lt;code&gt;LEFT JOIN&lt;/code&gt;-ed together, with an outer &lt;code&gt;ORDER BY … LIMIT 1000&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;xxxx&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;xxx&lt;/span&gt;
&lt;span class="k"&gt;limit&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To rule out a Cartesian product, we materialised each subquery into a temporary table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subquery a: grouped 2 billion rows → 200,000 rows&lt;/li&gt;
&lt;li&gt;Subquery b: distinct on a dimension → 2,000 rows&lt;/li&gt;
&lt;li&gt;Subquery c: two‑table LEFT JOIN + group by → about 20,000 rows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simplified &lt;code&gt;SELECT COUNT(*)&lt;/code&gt; tests confirmed the joins produced exactly 200,000 rows, each completing in under 10 seconds. A sorted output of 200,000 rows with a &lt;code&gt;LIMIT&lt;/code&gt; should never require terabytes of temp space — so something else was at play.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Root Cause: A Parameter Setting Inflated Column Width, Then Disk Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Find the “Heavy” Column
&lt;/h3&gt;

&lt;p&gt;When we replaced the &lt;code&gt;COUNT(*)&lt;/code&gt; with the original projection columns one by one, one column — originating from subquery c — caused the query to stall immediately. Inspecting the structure of the temporary table for subquery c revealed its data type: &lt;strong&gt;LONGTEXT&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Why LONGTEXT?
&lt;/h3&gt;

&lt;p&gt;The original expression for that column was &lt;code&gt;group_concat(xxx)&lt;/code&gt;. The cluster‑level parameter &lt;code&gt;group_concat_max_len&lt;/code&gt; had been changed from the default 32 KB to &lt;strong&gt;1 MB&lt;/strong&gt; to satisfy another business module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;show&lt;/span&gt; &lt;span class="n"&gt;variables&lt;/span&gt; &lt;span class="k"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'%group_concat_max_len%'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- returned 1048576 (1 MB)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When GBase 8a creates an intermediate table (e.g., &lt;code&gt;CREATE TABLE tmp AS SELECT …&lt;/code&gt;), it must determine the column width &lt;strong&gt;before&lt;/strong&gt; executing the query. Because the parameter was set to 1 MB — far exceeding &lt;code&gt;VARCHAR&lt;/code&gt;’s maximum 32 KB — the optimiser conservatively typed the intermediate column as &lt;code&gt;LONGTEXT&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 The Disk Sort Disaster
&lt;/h3&gt;

&lt;p&gt;In version 8.6.2, a sort operation materialises all projection columns. For a &lt;code&gt;LONGTEXT&lt;/code&gt; column, the engine pre‑allocates memory based on the &lt;strong&gt;maximum possible length of 64 MB per row&lt;/strong&gt;. With 200,000 rows, that equates to 200,000 × 64 MB ≈ 12.2 TB. Memory cannot hold that, so the data is spilled to disk, producing the observed 10 TB+ of temporary sort files on node3, sustaining &amp;gt;900 MB/s writes for hours.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4 Why Only Node3?
&lt;/h3&gt;

&lt;p&gt;The main table was randomly distributed. The query’s &lt;code&gt;GROUP BY&lt;/code&gt; columns were &lt;code&gt;clttime&lt;/code&gt; (low cardinality) and &lt;code&gt;cell_id&lt;/code&gt; (high cardinality). During hash redistribution, the first column was chosen as the distribution key, concentrating all intermediate data on a single node. Placing &lt;code&gt;cell_id&lt;/code&gt; first or enabling multi‑column hash redistribution would avoid such skew.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: Rewrite the SQL (Immediate Fix)
&lt;/h3&gt;

&lt;p&gt;Wrap the &lt;code&gt;group_concat&lt;/code&gt; call with a &lt;code&gt;substr&lt;/code&gt; to cap the expected output width. The optimiser will then type the intermediate column as &lt;code&gt;VARCHAR&lt;/code&gt;, eliminating the pre‑allocation problem entirely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xxx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The customer applied this change; the same query finished within 30 seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Use a Hint to Override the Parameter Per‑Query
&lt;/h3&gt;

&lt;p&gt;GBase 8a supports hints that temporarily set session‑level parameters for a single statement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="cm"&gt;/*+group_concat_max_len(3000)*/&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 3: Upgrade to Version 9.5
&lt;/h3&gt;

&lt;p&gt;Version 9.5 improves the materialisation strategy — memory is no longer allocated based on the maximum theoretical column size, but adaptively based on actual data, preventing this entire class of problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Key Takeaways
&lt;/h2&gt;

&lt;p&gt;A global parameter adjustment can trigger a hidden cascade: “parameter → column‑width estimation → materialisation pre‑allocation → massive disk spill → node‑wide I/O starvation.” When a single parameter cannot satisfy all workloads, &lt;strong&gt;use statement‑level hints&lt;/strong&gt; to give critical queries their own safe configuration, rather than applying a global value that may silently cripple other operations. In a &lt;strong&gt;gbase database&lt;/strong&gt;, understanding how the optimiser interprets parameters is just as important as tuning the parameters themselves.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>数据库</category>
    </item>
    <item>
      <title>High-Performance SFTP Loading in GBase 8a: New Parameter Configuration</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Tue, 30 Jun 2026 15:57:23 +0000</pubDate>
      <link>https://dev.to/michaelfv/high-performance-sftp-loading-in-gbase-8a-new-parameter-configuration-2fd6</link>
      <guid>https://dev.to/michaelfv/high-performance-sftp-loading-in-gbase-8a-new-parameter-configuration-2fd6</guid>
      <description>&lt;p&gt;In environments with strict security requirements, SFTP is the most common protocol for loading data into a &lt;strong&gt;gbase database&lt;/strong&gt; cluster. The latest versions of GBase 8a introduce configurable parameters that can significantly boost SFTP loading throughput. This guide explains how to assess your current load speed and apply the new parameters for optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Consider Tuning SFTP Load Performance
&lt;/h2&gt;

&lt;p&gt;If your current loading speed already meets business requirements, keep the default settings. When speed is lower than expected, first check the per‑node load rates via the &lt;code&gt;information_schema.load_status&lt;/code&gt; table. Compare the aggregate cluster load speed against the raw SFTP transfer speed (e.g., a simple &lt;code&gt;sftp get&lt;/code&gt; test on a single node). If the cluster’s total load speed is well below 30% of the raw SFTP speed, the parameters described below may help.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Parameters
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;gbase_use_ssh_sftp&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default&lt;/strong&gt;: &lt;code&gt;0&lt;/code&gt; (legacy SFTP loading method)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;1&lt;/code&gt;&lt;/strong&gt;: Enable the new high‑performance loading mechanism&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope&lt;/strong&gt;: Session‑level
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;gbase_use_ssh_sftp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;gbase_use_ssh_sftp_algorithm&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default&lt;/strong&gt;: Empty (auto‑negotiation of encryption algorithm)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage&lt;/strong&gt;: Specify the encryption algorithm(s) for SFTP transfer, separated by commas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope&lt;/strong&gt;: Session‑level
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;gbase_use_ssh_sftp_algorithm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'aes128-ctr'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: The chosen algorithm must be supported by the SSH daemon on the data source side, otherwise the connection will fail. Select a faster algorithm from the list of those supported by the server’s &lt;code&gt;sshd&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Validate the performance gain in a test environment or via session‑level settings first.&lt;/li&gt;
&lt;li&gt;Once the improvement is confirmed, write the parameters into the configuration file for global effect.&lt;/li&gt;
&lt;li&gt;The new method will increase CPU, network, and disk consumption; ensure sufficient resources.&lt;/li&gt;
&lt;li&gt;An incorrectly configured encryption algorithm will cause SFTP negotiation to fail immediately — choose carefully.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By applying these settings in your &lt;strong&gt;gbase database&lt;/strong&gt; environment, you can overcome SFTP loading bottlenecks while maintaining secure data transfer. Always test first and monitor resource usage after rolling out to production.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>数据库</category>
      <category>security</category>
    </item>
    <item>
      <title>Scaling the GBase 8a gcware Management Cluster: Adding and Removing Nodes</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Tue, 30 Jun 2026 15:54:29 +0000</pubDate>
      <link>https://dev.to/michaelfv/scaling-the-gbase-8a-gcware-management-cluster-adding-and-removing-nodes-4g37</link>
      <guid>https://dev.to/michaelfv/scaling-the-gbase-8a-gcware-management-cluster-adding-and-removing-nodes-4g37</guid>
      <description>&lt;p&gt;The gcware component in GBase 8a is responsible for cluster state management and consistency arbitration. It's typically deployed on an odd number of nodes (3 or 5). While the number of management nodes rarely changes during a cluster's lifetime, there are scenarios — migrating from a trial to a full production environment, significant data growth, online hardware replacement, or cluster downsizing — that require expanding or shrinking the gcware cluster. This article demonstrates the commands and procedures for scaling gcware in your &lt;strong&gt;gbase database&lt;/strong&gt; environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the Number of Management Nodes
&lt;/h2&gt;

&lt;p&gt;Management nodes do not store user data; they handle coordination. Always deploy an &lt;strong&gt;odd number&lt;/strong&gt; (3 or 5) to maintain quorum. For small clusters (fewer than 20 nodes with 1+1 replica), 3 gcware nodes suffice. For larger clusters (over 50 nodes or 3‑replica setups), 5 nodes are recommended.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Scale gcware
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Moving from a pilot (1–2 nodes) to a full production deployment.&lt;/li&gt;
&lt;li&gt;Significant business growth requiring more management capacity.&lt;/li&gt;
&lt;li&gt;Replacing aging hardware: add new gcware nodes, let data naturally redistribute, then decommission the old ones.&lt;/li&gt;
&lt;li&gt;Reducing cluster footprint when business shrinks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Version Restrictions
&lt;/h2&gt;

&lt;p&gt;Not all GBase 8a versions support gcware scaling. Check with GBASE support whether your version allows it, or request a version that does. Manual workarounds are not recommended for production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expanding gcware (Single Node → Three Nodes)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Initial state&lt;/strong&gt;: a single gcware node at 10.0.2.151. We'll add 10.0.2.152 and 10.0.2.153.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stop all management, coordinator, and data node services.&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;code&gt;gcware/gcware_server&lt;/code&gt; directory under the installation prefix and run:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gcserver.py &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/gbase &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.0.2.152,10.0.2.153 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--dbaPwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;111111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After confirmation, the script automatically expands the cluster and restarts the services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: &lt;code&gt;gcadmin&lt;/code&gt; now shows three gcware nodes, all with status &lt;code&gt;OPEN&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shrinking gcware (Three Nodes → Two Nodes)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: The shrink command &lt;strong&gt;must not be executed on the node being removed&lt;/strong&gt;. Run it from a remaining node, using the &lt;code&gt;-u&lt;/code&gt; flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python gcserver.py &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/gbase &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.0.2.151 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--dbaPwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;111111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After confirmation, the script removes the specified node.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: &lt;code&gt;gcadmin&lt;/code&gt; shows the gcware cluster reduced to two nodes, still functional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Scaling the gcware management cluster is rare but can be a necessity. GBase 8a provides scripted, automated operations in select versions, eliminating the need for error‑prone manual steps. If your environment requires this capability, verify version support and plan the change window accordingly, keeping your &lt;strong&gt;gbase database&lt;/strong&gt; cluster stable throughout the process.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>数据库</category>
      <category>operations</category>
    </item>
    <item>
      <title>GBase 8a Cluster Installation in Practice: From Environment Setup to Health Checks</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Tue, 23 Jun 2026 15:44:00 +0000</pubDate>
      <link>https://dev.to/michaelfv/gbase-8a-cluster-installation-in-practice-from-environment-setup-to-health-checks-3fia</link>
      <guid>https://dev.to/michaelfv/gbase-8a-cluster-installation-in-practice-from-environment-setup-to-health-checks-3fia</guid>
      <description>&lt;p&gt;The success of a GBase 8a cluster installation often hinges not on the install commands themselves, but on the pre‑installation environment preparation and post‑installation validation. This guide focuses on critical prerequisites — networking, SSH, system limits, and firewall settings — and walks through a verified workflow for verifying cluster state and distribution configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Node Planning and Component Roles
&lt;/h2&gt;

&lt;p&gt;A GBase 8a cluster consists of three component types: gcware (management nodes, 3 or 5 recommended), gcluster (coordinators), and gnode (data nodes). Plan the roles of each node before starting. Here is a sample 3‑node layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;198.51.100.21  management + coordinator + data node
198.51.100.22  management + coordinator + data node
198.51.100.23  management + coordinator + data node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. System Prerequisites to Address Before Installation
&lt;/h2&gt;

&lt;p&gt;Nodes must use static IPs, have full network connectivity between them, and have hostname resolution properly configured.&lt;/p&gt;

&lt;h3&gt;
  
  
  Network and SSH Checks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Node connectivity&lt;/span&gt;
ping 198.51.100.22
ping 198.51.100.23

&lt;span class="c"&gt;# SSH connectivity&lt;/span&gt;
ssh root@198.51.100.22
ssh root@198.51.100.23
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Firewall and SELinux Checks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl status firewalld
sestatus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Handling Non‑Default SSH Ports
&lt;/h2&gt;

&lt;p&gt;If SSH is not running on port 22, specify the custom port either through user‑level SSH configuration or the installation options file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A: User‑level SSH config&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/config
Host 198.51.100.22 198.51.100.23
    Port 22022
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option B: Install options file&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# install.options
&lt;/span&gt;&lt;span class="py"&gt;sshPort&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;22022&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Adjust ulimit and systemd Limits Early
&lt;/h2&gt;

&lt;p&gt;Insufficient file handles or process limits will cause instability under concurrency and batch workloads. Address this across systemd, profile, and limits simultaneously.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# /etc/systemd/system.conf&lt;/span&gt;
&lt;span class="nv"&gt;DefaultLimitNOFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;655350
&lt;span class="nv"&gt;DefaultLimitNPROC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;655350
systemctl daemon-reexec
systemctl restart sshd

&lt;span class="c"&gt;# Also update /etc/profile and /etc/security/limits.conf with appropriate nofile settings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Key Installation Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create the operating system user and directories&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;useradd gbaseadm
passwd gbaseadm
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /data/gbase8a
&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; gbaseadm:gbaseadm /data/gbase8a
&lt;span class="nb"&gt;chown &lt;/span&gt;gbaseadm:gbaseadm /tmp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Extract the package and run the environment setup script&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /data
&lt;span class="nb"&gt;tar &lt;/span&gt;xfj GBase8a_MPP_Cluster-NoLicense-FREE-9.5.3-demo-redhat7-x86_64.tar.bz2
python SetSysEnv.py &lt;span class="nt"&gt;--dbaUser&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gbaseadm &lt;span class="nt"&gt;--installPrefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/data/gbase8a &lt;span class="nt"&gt;--cgroup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write the installation configuration file &lt;code&gt;install.options&lt;/code&gt;&lt;/strong&gt;, specifying the install directory, coordinator hosts, data hosts, management hosts, user credentials, and SSH port.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the silent installation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gcinstall.py &lt;span class="nt"&gt;--silent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;install.options
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Validate Cluster Health Immediately After Installation
&lt;/h2&gt;

&lt;p&gt;A completed install script does not guarantee a healthy cluster. Always run &lt;code&gt;gcadmin&lt;/code&gt; to verify that the cluster state is &lt;code&gt;ACTIVE&lt;/code&gt; and that all gcware, coordinator, and data node roles show &lt;code&gt;OPEN&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Configure and Verify Distribution Settings
&lt;/h2&gt;

&lt;p&gt;Prepare a distribution XML file, apply it with &lt;code&gt;gcadmin distribution&lt;/code&gt;, and inspect the result with &lt;code&gt;gcadmin showdistribution node&lt;/code&gt;. This step directly determines how data is placed across nodes and how the load is balanced.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Parameter Tuning Recommendations
&lt;/h2&gt;

&lt;p&gt;Avoid changing many parameters at once. Prioritise based on symptom category: for connection and timeout issues, check &lt;code&gt;max_connections&lt;/code&gt; and &lt;code&gt;connect_timeout&lt;/code&gt; first; for concurrency and thread pool pressure, look at &lt;code&gt;gbase_parallel_degree&lt;/code&gt;; for loading bottlenecks, examine &lt;code&gt;gcluster_loader_max_data_processors&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A smooth GBase 8a installation relies on getting the basics right before running any installer. When the network, SSH, system limits, and cluster health checks are all solid, the rest of the &lt;strong&gt;gbase database&lt;/strong&gt; operations become far more predictable.&lt;/p&gt;

</description>
      <category>gbase</category>
      <category>database</category>
      <category>数据库</category>
      <category>operations</category>
    </item>
  </channel>
</rss>
