
# Linux下配置数据源
ODBC连接数据库之前需要准备好所需资源。连接数据库是通过配置ODBC数据源，使用ODBC API或者相应的驱动程序，实现应用程序与数据库之间的通信和交互。本节介绍如何在Linux系统下配置数据源并连接到数据库。
#### 操作步骤
1. 安装unixODBC（默认unixODBC源码包已在环境准备中获取）。如果机器上已经安装了其他版本的unixODBC，可以直接覆盖安装。 
   以unixODBC-2.3.7版本为例，在客户端执行如下命令安装unixODBC。
   ```
   tar zxvf unixODBC-2.3.7.tar.gz
   cd unixODBC-2.3.7
   ./configure --enable-gui=no #如果要在ARM服务器上编译，请追加一个configure参数： --build=aarch64-unknown-linux-gnu 
   make
   #安装可能需要root权限
   make install
   ```
   ![](https://support.huaweicloud.com/centralized-devg-v2-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
   - 目前不支持unixODBC-2.2.1版本。
   
   - 默认安装到"/usr/local"目录下，生成数据源文件到 "/usr/local/etc"目录下，库文件生成在"/usr/local/lib"目录。
   
   - 通过编译带有--enable-fastvalidate=yes选项的unixODBC来获得更高性能。但此选项可能会导致向ODBC API传递无效句柄的应用程序发生故障，而不是返回SQL_INVALID_HANDLE错误。
    
   
   
2. 替换客户端GaussDB驱动程序。 
   将GaussDB-Kernel-数据库版本号-操作系统信息-64bit-Odbc.tar.gz解压。解压后会得到两个文件夹：lib与odbc，在odbc文件夹中还会有一个lib文件夹。将解压后得到的/lib文件夹与/odbc/lib文件夹中的所有动态库都复制到"/usr/local/lib"目录下。
   
   
3. 配置数据源。 
   1. 配置ODBC驱动文件。 在"/usr/local/etc/odbcinst.ini"文件中追加以下内容。
      ```
      [GaussMPP]
      Driver64=/usr/local/lib/psqlodbcw.so
      setup=/usr/local/lib/psqlodbcw.so
      ```
      odbcinst.ini文件中的配置参数说明如[表1]所示。
       表1odbcinst.ini文件配置参数 
      | **参数**         | **描述**                     | **示例**                               |
      |:---|:---|:---|
      | \[DriverName\] | 驱动器名称，对应数据源DSN中的驱动名。       | \[GaussMPP\]                         |
      | Driver64       | 驱动动态库的路径。                  | Driver64=/usr/local/lib/psqlodbcw.so |
      | setup          | 驱动安装路径，与Driver64中动态库的路径一致。 | setup=/usr/local/lib/psqlodbcw.so    |
         
      
   
   2. 配置数据源文件。 在"/usr/local/etc/odbc.ini"文件中追加以下内容。
      ```
      [gaussdb]
      Driver=GaussMPP
      Servername=127.0.0.1 #数据库Server IP
      Database=postgres  #数据库名
      Username=omm  #数据库用户名
      Password=  #数据库用户密码
      Port=8000  #数据库侦听端口
      Sslmode=allow
      ```
      odbc.ini文件配置参数说明如[表2]所示。
       表2odbc.ini文件配置参数 
      | **参数**                | **描述**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | **示例**                    |
      |:---|:---|:---|
      | \[DSN\]               | 数据源的名称。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | \[gaussdb\]               |
      | Driver                | 驱动名，对应odbcinst.ini中的DriverName。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Driver=GaussMPP           |
      | Servername            | 服务器的IP地址。可配置多个IP地址。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | Servername=127.0.0.1      |
      | Database              | 要连接的数据库的名称。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Database=postgres         |
      | Username              | 数据库用户名称。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Username=omm              |
      | Password              | 数据库用户密码。 说明： ODBC驱动本身已经对内存密码进行过清理，以保证用户密码在连接后不会再在内存中保留。 但是如果配置了此参数，由于UnixODBC对数据源文件等进行缓存，可能导致密码长期保留在内存中。 推荐在应用程序连接时，将密码传递给相应API，而非写在数据源配置文件中。同时连接成功后，应当及时清理保存密码的内存段。 须知： 配置文件中填写密码时，需要遵循http规则： 1. 字符应当采用URL编码规范，如"!"应写作"%21"，"%"应写作"%25"，因此应当注意特殊处理%。  2. "+"会被替换为空格" "。   | Password=\*\*\*\*\*\*\*\* |
      | Port                  | 服务器的端口号。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Port=8000                 |
      | Sslmode               | 开启SSL模式 说明： 关于Sslmode的选项的允许值，具体信息如[表3]所示。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | Sslmode=allow             |
      | Debug                 | 是否启用调试模式。 取值范围：0 \~ INT_MAX - 设置为0时表示不开启。  - 设置为大于0时表示将会打印psqlodbc驱动的mylog，日志生成目录为/tmp/。   默认值为0。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | Debug=1                   |
      | UseServerSidePrepare  | 是否开启数据库端扩展查询协议。 取值范围：0，1 - 取值为0表示不开启。  - 取值为1表示开启。   默认值为1。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | UseServerSidePrepare=1    |
      | UseBatchProtocol      | 是否开启批量查询协议（打开可提高DML性能）。 取值范围：0，1 - 取值为0时，不使用批量查询协议（主要用于与早期数据库版本通信兼容）。  - 取值为1，并且数据库support_batch_bind参数存在且为on时，将打开批量查询协议。   默认值为1。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | UseBatchProtocol=1        |
      | ForExtensionConnector | 此开关控制着savepoint是否发送，savepoint相关问题可以注意此开关， 取值范围：0，1 - 取值为0时表示发送savepoint。  - 取值为1时表示不发送savepoint。   默认值为1。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | ForExtensionConnector=1   |
      | ConnectionExtraInfo   | GUC参数connection_info中显示驱动部署路径和进程属主用户的开关。 取值范围：0，1 - 取值为0时表示不打开此开关。  - 取值为1时表示打开此开关。   默认值为0。 说明： 默认值为0。当设置为1时，ODBC驱动会将当前驱动的部署路径、进程属主用户上报到数据库中，记录在connection_info参数里；同时可以在[PG_STAT_ACTIVITY](https://support.huaweicloud.com/centralized-devg-v2-gaussdb/gaussdb_42_0855.html#ZH-CN_TOPIC_0000002186016914)中查询到。                                                                                                                                                   | ConnectionExtraInfo=1     |
      | BoolsAsChar           | 是否将布尔值作为字符处理。 取值范围：0，1 - 取值为0时表示Bools值将会映射为SQL_BIT。  - 取值为1时表示Bools值将会映射为SQL_CHAR。   默认值为1。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | BoolsAsChar = 1           |
      | RowVersioning         | 是否在更新一行数据时，允许应用检测数据有没有被其他用户进行修改。 取值范围：0，1 - 取值为0时表示不允许应用检测。  - 取值为1时表示允许应用检测。   默认值为0。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | RowVersioning=1           |
      | ShowSystemTables      | 是否将默认系统表格视为普通SQL表格。 取值范围：0，1 - 取值为0时驱动不会将默认系统表格视为普通SQL表格。  - 取值为1时驱动将默认系统表格视为普通SQL表格。   默认值为0。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | ShowSystemTables=1        |
      | TcpUserTimeout        | 在支持TCP_USER_TIMEOUT套接字选项的操作系统上，指定传输的数据在TCP连接被强制关闭之前可以保持未确认状态的最大时长。 取值范围：0 \~ INT_MAX 默认值为0。 说明： 0表示使用系统缺省。通过Unix域套接字做的连接忽略这个参数。单位为毫秒。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | TcpUserTimeout=5000       |
         
      其中关于Sslmode的选项的允许值，具体信息见下表：
       表3Sslmode的可选项及其描述 
      | Sslmode     | 是否会启用SSL加密 | 描述                                                                    |
      |:---|:---|:---|
      | disable     | 否          | 不使用SSL安全连接。                                                           |
      | allow       | 可能         | 如果数据库服务器要求使用，则可以使用SSL安全加密连接，但不验证数据库服务器的真实性。                           |
      | prefer      | 可能         | 如果数据库支持，那么建议使用SSL安全加密连接，但不验证数据库服务器的真实性。                               |
      | require     | 是          | 必须使用SSL安全连接，但是只做了数据加密，而并不验证数据库服务器的真实性。                                |
      | verify-ca   | 是          | 必须使用SSL安全连接，并且验证数据库是否具有可信证书机构签发的证书。                                   |
      | verify-full | 是          | 必须使用SSL安全连接，在verify-ca的验证范围之外，同时验证数据库所在主机的主机名是否与证书内容一致。GaussDB不支持此模式。 |
         
      ![](https://support.huaweicloud.com/centralized-devg-v2-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
      用户通过ODBC连接GaussDB服务器时，可以通过开启SSL加密客户端和服务器之间的通讯。在使用SSL时，默认用户已经获取了服务端和客户端所需要的证书和私钥文件，关于证书等文件的获取请参考Openssl相关文档和命令。
      
   
   
   
   
4. 在客户端配置环境变量。 
   ```
   vim ~/.bashrc
   ```
   在配置文件中追加以下内容。
   ```
   export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH
   export ODBCSYSINI=/usr/local/etc
   export ODBCINI=/usr/local/etc/odbc.ini
   ```
   
   
5. 执行如下命令使设置生效。 
   ```
   source ~/.bashrc
   ```
   
   
6. 测试连接。 
   安装后/usr/bin下面会存放生成的二进制，可执行isql -v gaussdb（数据源名称）命令。
   - 如果显示如下信息，表明配置正确，连接成功。
     ```
     +---------------------------------------+
     | Connected!                            |
     |                                       |
     | sql-statement                         |
     | help [tablename]                      |
     | quit                                  |
     |                                       |
     +---------------------------------------+
     ```
     
   
   - 若显示ERROR信息，则表明配置错误。请检查上述配置步骤是否正确执行。
   
   
   ![](https://support.huaweicloud.com/centralized-devg-v2-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
   目前通过ODBC连接数据库时，会如下设置内核参数：
   ```
   SET extra_float_digits = 2;
   SET DateStyle = 'ISO';
   ```
   这些参数可能会导致ODBC客户端的行为与gsql客户端的行为不一致，例如，Date数据显示方式、浮点数精度表示。如果实际期望和这些配置不符，建议在ODBC应用代码中显式设定这些参数。
   
   
 
#### 常见问题处理
- \[UnixODBC\]\[Driver Manager\]Can't open lib 'xxx/xxx/psqlodbcw.so' : file not found. 此问题的可能原因：
  - odbcinst.ini文件中配置的路径不正确 确认方法：执行ls命令查询错误信息中的路径，以确保该psqlodbcw.so文件存在，同时具有执行权限。
    
  
  - psqlodbcw.so的依赖库不存在，或者不在系统环境变量中 确认方法：执行ldd查询误信息中的路径，如果是缺少libodbc.so.1等UnixODBC的库，那么按照"操作步骤"中的方法重新配置UnixODBC，并确保它的安装路径下的lib目录添加到了LD_LIBRARY_PATH中；如果是缺少其他库，请将ODBC驱动包中的lib目录添加到LD_LIBRARY_PATH中。如果缺少其他标准库，请自行安装。
    
   
- \[UnixODBC\]connect to server failed: no such file or directory 此问题可能的原因：
  - 配置了错误的/不可达的数据库地址，或者端口 请检查数据源配置中的Servername及Port配置项。
    
  
  - 服务器侦听不正确 如果确认Servername及Port配置正确，请根据"操作步骤"中数据库服务器的相关配置，确保数据库侦听了合适的网卡及端口。
    
  
  - 防火墙及网闸设备 请确认防火墙设置，将数据库的通信端口添加到可信端口中。
    如果有网闸设备，请确认相关的设置。
    
   
- \[unixODBC\]The password-stored method is not supported. 此问题可能原因：
  数据源中未配置sslmode配置项。
  解决办法：
  请配置该选项至allow或以上选项。此配置的更多信息，请参见[表3]。
  
- Server common name "xxxx" does not match host name "xxxxx" 此问题的原因：
  使用了SSL加密的"verify-full"选项，驱动程序会验证证书中的主机名与实际部署数据库的主机名是否一致。
  解决办法：
  碰到此问题可以使用"verify-ca"选项，不再校验主机名；或者重新生成一套与数据库所在主机名相同的CA证书。
  
- Driver's SQLAllocHandle on SQL_HANDLE_DBC failed 此问题的可能原因：
  可执行文件（比如UnixODBC的isql，以下都以isql为例）与数据库驱动（psqlodbcw.so）依赖于不同的odbc的库版本：libodbc.so.1或者libodbc.so.2。此问题可以通过如下方式确认：
  ```
  ldd `which isql` | grep odbc
  ldd psqlodbcw.so | grep odbc
  ```
  这时，如果输出的libodbc.so最后的后缀数字不同或者指向不同的磁盘物理文件，那么基本就可以断定是此问题。isql与psqlodbcw.so都会要求加载libodbc.so，这时如果它们加载的是不同的物理文件，便会导致两套完全同名的函数列表，同时出现在同一个可见域里（UnixODBC的libodbc.so.\*的函数导出列表完全一致），产生冲突，无法加载数据库驱动。
  解决办法：
  确定一个要使用的UnixODBC，然后卸载另外一个（比如卸载库版本号为.so.2的UnixODBC），然后将剩下的.so.1的库，新建一个同名但是后缀为.so.2的软链接，便可解决此问题。
  
- FATAL: Forbid remote connection with trust method! 由于安全原因，数据库主节点禁止数据库内部其他节点无认证接入。
  如果要在数据库内部访问数据库主节点，请将ODBC程序部署在数据库主节点所在机器，服务器地址使用"127.0.0.1"。建议业务系统单独部署在数据库外部，否则可能会影响数据库运行性能。
  
- \[unixODBC\]\[Driver Manager\]Invalid attribute value 有可能是unixODBC的版本并非推荐版本，建议通过"odbcinst --version"命令排查环境中的unixODBC版本。
  
- authentication method 10 not supported. 使用开源客户端碰到此问题，可能原因：
  数据库中存储的口令校验只存储了SHA256格式哈希，而开源客户端只识别MD5校验，双方校验方法不匹配报错。
  ![](https://support.huaweicloud.com/centralized-devg-v2-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 数据库并不存储用户口令，只存储用户口令的哈希码。
  
  - 当用户更新用户口令或者新建用户时，数据库会同时存储两种格式的哈希码，这时将兼容开源的认证协议。
  
  - 但是当旧版本升级到新版本时，由于哈希的不可逆性，所以数据库无法还原用户口令，进而生成新格式的哈希，所以仍然只保留了SHA256格式的哈希，导致仍然无法使用MD5做口令认证。
  
  - MD5加密算法安全性低，存在安全风险，建议使用更安全的加密算法。
   
  要解决该问题，可以更新用户口令（参见[ALTER USER](https://support.huaweicloud.com/centralized-devg-v2-gaussdb/gaussdb_42_0385.html#ZH-CN_TOPIC_0000002186175778)）；或者新建一个用户（参见[CREATE USER](https://support.huaweicloud.com/centralized-devg-v2-gaussdb/gaussdb_42_0431.html#ZH-CN_TOPIC_0000002221381877)），赋予同等权限，使用新用户连接数据库。
  
- unsupported frontend protocol 3.51: server supports 1.0 to 3.0 目标数据库版本过低，或者目标数据库为开源数据库。
  请使用对应版本的数据库驱动连接目标数据库。
  
- FATAL: GSS authentication method is not allowed because XXXX user password is not disabled. 目标数据库主节点的pg_hba.conf里配置了当前客户端IP使用"gss"方式来做认证，该认证算法不支持用作客户端的身份认证，请修改到"sha256"后再试。
  
- isql：error while loading shared libraries:xxx 环境缺少该动态库，需要自行安装对应的库。
  
 
