
# Linux下配置数据源
将DWS提供的ODBC DRIVER（psqlodbcw.so）配置到数据源中便可使用。配置数据源需要配置"odbc.ini"和"odbcinst.ini"两个文件（在编译安装unixODBC过程中生成且默认放在etc目录下），并在服务器端进行配置。
#### 操作步骤
1. 获取unixODBC源码包。 
   获取参考地址：<https://sourceforge.net/projects/unixodbc/files/unixODBC/2.3.0/unixODBC-2.3.0.tar.gz/download>
   
   
2. 目前不支持unixODBC-2.2.1版本。以unixODBC-2.3.0版本为例，在客户端执行如下命令安装unixODBC。安装时通过--prefix=\[your_path\]指定安装目录，生成数据源文件到 "\[your_path\]/etc"目录下，库文件生成在"\[your_path\]/lib"目录。 
   ```
   tar zxvf unixODBC-2.3.0.tar.gz
   cd unixODBC-2.3.0
   #修改configure文件(如果不存在，那么请修改configure.ac)，找到LIB_VERSION
   #将它的值修改为"1:0:0"，这样将编译出*.so.1的动态库，与psqlodbcw.so的依赖关系相同。
   vim configure
   ./configure --enable-gui=no --prefix=[your_path] #如果要在ARM服务器上编译，请追加一个configure参数： --build=aarch64-unknown-linux-gnu 
   make
   make install
   ```
   安装unixODBC。如果机器上已经安装了其他版本的unixODBC，可以直接覆盖安装。
   
   
3. 替换客户端DWS驱动程序。 
   将dws_8.x.x_odbc_driver_for_xxx_xxx.zip解压，在"/dws_8.x.x_odbc_driver_for_xxx_xxx/odbc/lib"目录下得到"psqlodbcw.la"和"psqlodbcw.so"两个文件。
   
   
4. 配置数据源。 
   1. 配置ODBC驱动文件。 在"\[your_path\]/etc/odbcinst.ini"文件中追加以下内容。
      ```
      [GaussMPP]
      Driver64=[your_path]/lib/odbc/psqlodbcw.so
      setup=[your_path]/lib/odbc/psqlodbcw.so
      ```
      odbcinst.ini文件中的配置参数说明如[表1]所示。
       表1odbcinst.ini文件配置参数 
      | **参数**         | **描述**                     | **示例**                                   |
      |:---|:---|:---|
      | \[DriverName\] | 驱动器名称，对应数据源DSN中的驱动名。       | \[DRIVER_N\]                             |
      | Driver64       | 驱动动态库的路径。                  | Driver64=/xxx/odbc/lib/odbc/psqlodbcw.so |
      | setup          | 驱动安装路径，与Driver64中动态库的路径一致。 | setup=/xxx/odbc/lib/odbc/psqlodbcw.so    |
         
      
   
   2. 配置数据源文件。 在"\[your_path\]/etc/odbc.ini "文件中追加以下内容。
      ```
      [MPPODBC]
      Driver=GaussMPP
      Servername=10.10.0.13（数据库Server IP）
      Database=gaussdb  （数据库名）
      Username=dbadmin  （数据库用户名）
      Password=  （数据库用户密码）
      Port=8000 （数据库监听端口）
      Sslmode=allow
      ```
      odbc.ini文件配置参数说明如[表2]所示。
       表2odbc.ini文件配置参数 
      | **参数**                | **描述**                                                                                                                                                                                                                    | **示例**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
      |:---|:---|:---|
      | \[DSN\]               | 数据源的名称。                                                                                                                                                                                                                   | \[MPPODBC\]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
      | Driver                | 驱动名，对应odbcinst.ini中的DriverName。                                                                                                                                                                                           | Driver=DRIVER_N                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
      | Servername            | 服务器的IP地址。                                                                                                                                                                                                                 | Servername=10.145.130.26                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
      | Database              | 要连接的数据库的名称。                                                                                                                                                                                                               | Database=gaussdb                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
      | Username              | 数据库用户名称。                                                                                                                                                                                                                  | Username=dbadmin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
      | Password              | 数据库用户密码。                                                                                                                                                                                                                  | Password= 说明： ODBC驱动本身已经对内存密码进行过清理，以保证用户密码在连接后不会再在内存中保留。 但是如果配置了此参数，由于UnixODBC对数据源文件等进行缓存，可能导致密码长期保留在内存中。 推荐在应用程序连接时，将密码传递给相应API，而非写在数据源配置文件中。同时连接成功后，应当及时清理保存密码的内存段。                                                                                              |
      | Port                  | 服务器的端口号。                                                                                                                                                                                                                  | Port=8000                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
      | Sslmode               | 开启SSL模式。                                                                                                                                                                                                                  | Sslmode=allow                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
      | UseServerSidePrepare  | 是否开启数据库端扩展查询协议。 可选值0或1，默认为1，表示打开扩展查询协议。                                                                                                                                   | UseServerSidePrepare=1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
      | UseBatchProtocol      | 是否开启批量查询协议（打开可提高DML性能）；可选值0或者1，默认为1。 当此值为0时，不使用批量查询协议（主要用于与早期数据库版本通信兼容）。 当此值为1，并且数据库support_batch_bind参数存在且为on时，将打开批量查询协议。   | UseBatchProtocol=1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
      | ConnectionExtraInfo   | GUC参数connection_info（参见[connection_info](https://support.huaweicloud.com/devg-dws/dws_04_0889.html#ZH-CN_TOPIC_0000001764491936__section4834457114318)）中显示驱动部署路径和进程属主用户的开关。                                               | ConnectionExtraInfo=1 说明： 默认值为1。当设置为0时，ODBC驱动会将当前驱动的名称、驱动版本上报到数据库中；当设置为1时，ODBC驱动会将当前驱动的名称、部署路径、进程属主用户上报到数据库中，记录在connection_info参数（参见[connection_info](https://support.huaweicloud.com/devg-dws/dws_04_0889.html#ZH-CN_TOPIC_0000001764491936__section4834457114318)）里；同时可以在[PG_STAT_ACTIVITY](https://support.huaweicloud.com/devg-dws/dws_04_0755.html)和[PGXC_STAT_ACTIVITY](https://support.huaweicloud.com/devg-dws/dws_04_0820.html)中查询到。 |
      | ForExtensionConnector | ETL工具性能优化参数，可进行内存优化，降低对端的CN内存占用，避免因CN内存使用过多导致系统不稳定。 可选值0或者1，默认为0，表示不开启优化项。 请勿在数据库系统之外的其他业务中配置此参数，以免影响业务的正确性。                      | ForExtensionConnector=1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
      | KeepDisallowPremature | 当UseDeclareFetch=1时，应用程序调用SQLPrepare后调用SQLNumResultCols、SQLDescribeCol或SQLColAttribute获取结果集列信息时，SQL语句中的游标是否具有with hold属性。 可选值0或者1，0表示具有with hold属性，1表示不具有with hold属性，默认为0。 | KeepDisallowPremature=1 说明： UseServerSidePrepare=1时，KeepDisallowPremature参数不生效，使用时需要指定UseServerSidePrepare为0，例如：UseDeclareFetch=1 KeepDisallowPremature=1 UseServerSidePrepare=0                                                                                                                                                                |
         
      其中关于sslmode的选项的允许值，具体信息见下表：
       表3sslmode的可选项及其描述 
      | sslmode     | 是否会启用SSL加密 | 描述                                                                |
      |:---|:---|:---|
      | disable     | 否          | 不使用SSL安全连接。                                                       |
      | allow       | 可能         | 如果数据库服务器要求使用，则可以使用SSL安全加密连接，但不验证数据库服务器的真实性。                       |
      | prefer      | 可能         | 如果数据库支持，那么首选使用SSL安全加密连接，但不验证数据库服务器的真实性。                           |
      | require     | 是          | 必须使用SSL安全连接，但是只做了数据加密，而并不验证数据库服务器的真实性。                            |
      | verify-ca   | 是          | 必须使用SSL安全连接，并且验证数据库是否具有可信证书机构签发的证书。                               |
      | verify-full | 是          | 必须使用SSL安全连接，在verify-ca的验证范围之外，同时验证数据库所在主机的主机名是否与证书内容一致。DWS不支持此模式。 |
         
      
   
   
   
   
5. SSL模式 
   如果需要使用SSL证书连接，那么请将DWS安装包中的SSLCERT的证书包解压，在shell环境下，执行"source sslcert_env.sh"，即在**当前会话**完成证书的默认位置的部署。
   或者手动声明如下环境变量，同时保证client.key\*系列文件为600权限：
   ```
   export PGSSLCERT="/YOUR/PATH/OF/client.crt" #请修改该路径到client.crt的绝对路径
   export PGSSLKEY="/YOUR/PATH/OF/client.key"  #请修改该路径到client.key的绝对路径
   ```
   同时将数据源中的Sslmode选项调整至"verify-ca"。
   
   
6. 将客户端所在主机的IP网段加入DWS的安全组规则，确保客户端主机与DWS网络互通。
7. 配置环境变量。 
   ```
   vim ~/.bashrc
   ```
   在配置文件中追加以下内容。
   ```
   export LD_LIBRARY_PATH=[your_path]/lib/:$LD_LIBRARY_PATH
   export ODBCSYSINI=[your_path]/etc
   export ODBCINI=[your_path]/etc/odbc.ini
   ```
   ![](https://support.huaweicloud.com/devg-dws/public_sys-resources/note_3.0-zh-cn.png)
   麒麟OS环境中，此处不建议追加LD_LIBRARY_PATH，可能造成libssl.so动态库冲突。集群9.1.0最新版本中已增加rpath，不需要LD_LIBRARY_PATH即可找到依赖。
   
   
8. 执行如下命令使设置生效。 
   ```
   source ~/.bashrc
   ```
   
   
 
#### 测试数据源配置
执行isql -v GaussODBC(数据源名称)命令。
- 如果显示如下信息，表明配置正确，连接成功。
  ```
  +---------------------------------------+
  | Connected!                            |
  |                                       |
  | sql-statement                         |
  | help [tablename]                      |
  | quit                                  |
  |                                       |
  +---------------------------------------+
  SQL>
  ```
  
- 如果显示ERROR信息，则表明配置错误。请检查上述配置是否正确。
#### 常见问题处理
- \[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中。或者将psqlodbcw.so的依赖库放到psqlodbcw.so的rpath对应的路径中，通过readelf -d可查看rpath。
    
   
- \[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! 由于安全原因，数据库CN禁止集群内部其他节点无认证接入。
  如果要在集群内部访问CN，请将ODBC程序部署在CN所在机器，服务器地址使用"127.0.0.1"。建议业务系统单独部署在集群外部，否则可能会影响数据库运行性能。
  
- \[unixODBC\]\[Driver Manager\]Invalid attribute value 在使用SQL on other GaussDB功能时碰到此问题，有可能是unixODBC的版本并非推荐版本，建议通过"odbcinst --version"命令排查环境中的unixODBC版本。
  
- authentication method 10 not supported. 使用开源客户端碰到此问题，可能原因：
  数据库中存储的口令校验只存储了SHA256格式哈希，而开源客户端只识别MD5校验，双方校验方法不匹配报错。
  ![](https://support.huaweicloud.com/devg-dws/public_sys-resources/note_3.0-zh-cn.png)
  - 数据库并不存储用户口令，只存储用户口令的哈希码。
  
  - 早期版本（V100R002C80SPC300之前的版本）的数据库只存储了SHA256格式的哈希，并未存储MD5的哈希，所以无法使用MD5做用户口令校验。
  
  - 新版本（V100R002C80SPC300及之后版本）的数据库当用户更新用户口令或者新建用户时，会同时存储两种格式的哈希码，这时将兼容开源的认证协议。
  
  - 但是当老版本升级到新版本时，由于哈希的不可逆性，所以数据库无法还原用户口令，进而生成新格式的哈希，所以仍然只保留了SHA256格式的哈希，导致仍然无法使用MD5做口令认证。
   
  要解决该问题，可以更新用户口令；或者新建一个用户，赋予同等权限，使用新用户连接数据库。
  
- unsupported frontend protocol 3.51: server supports 1.0 to 3.0 目标数据库版本过低，或者目标数据库为开源数据库。请使用对应版本的数据库驱动连接目标数据库。
  
 
