C 驱动连接 OceanBase 数据库

本文介绍了如何通过 OceanBase Connector/C 驱动连接并使用 OceanBase 数据库。

前提条件

在安装使用 OceanBase Connector/C 前请确保设置了基本的数据库开发环境,要求如下:

  • GCC 版本为 3.4.6 及以上,推荐使用 4.8.5 版本。

  • CMake 版本为 2.8.12 及以上。

C 驱动连接 OceanBase 数据库

步骤一:获取数据库连接参数

参考 获取连接参数 文档,获取相应的租户连接参数,例如:

$ obclient -hxxx.xxx.xxx.xxx -P3306 -u a**** -p****** -Dtest

数据库连接参数包含了访问数据库所需的参数信息,在验证示例代码前,可通过数据库连接参数验证登录数据库,保证信息正确。

参数说明:

  • -h:OceanBase 数据库连接的域名。

  • -P:OceanBase 数据库连接端口,MySQL 模式租户默认是 3306。

  • -u:租户的连接账号。

  • -p:账号密码。

  • -D:数据库名称。

步骤二:安装 OceanBase Connector/C 驱动

通过 rpm 安装

获取 OceanBase Connector/C 安装包(即 LibOBClient)和 OBClient 安装包。更多版本的安装包,请参考 镜像站,根据自身的系统版本在镜像库中找到需要的安装包。

说明

由于 OBClient 依赖于 LibOBClient,所以需要先安装 LibOBClient。

  1. 安装 LibOBClient。

    $ sudo rpm -ivh libobclient-xx.x86_64.rpm
  2. 安装 OBClient。

    $ sudo rpm -ivh obclient-xx.x86_64.rpm

从源码编译

OceanBase 数据库的 Github 仓库提供的最新开发版本的源代码(包含子库),参见 obclient

  1. 安装依赖工具。

    $ sudo yum install -y git cmake gcc make openssl-devel ncurses-devel rpm-build  gcc-c++ bison bison-devel zlib-devel gnutls-devel libxml2-devel openssl-devel \libevent-devel libaio-devel
  2. 代码编译及打包

    1. 下载 obclient 源代码(包含子库)。

      $ git clone --recurse-submodules https://github.com/oceanbase/obclient 
    2. 进入 obclient/libmariadb 目录。

      $ cd obclient/libmariadb
    3. 执行 LibOBClient 编译。

      $ sh build.sh
    4. 打包 LibOBClient 的 RPM 安装包。

      $ sh rpm/libobclient-build.sh
    5. 回到 obclient 目录。

      $ cd ..
    6. 执行 OBClient 编译。

      $ sh build.sh
    7. 打包 OBClient 的 RPM 安装包。

      $ sh rpm/obclient-build.sh
  3. 安装 LibOBClient。

    $ sudo rpm -ivh /libmariadb/rpmlibobclient-xx.x86_64.rpm

    安装 OBClient。

    $ sudo rpm -ivh rpm/obclient-xx.x86_64.rpm
    说明

    由于 OBClient 依赖于 LibOBClient,所以需要先安装 LibOBClient。

步骤三:编写代码示例

通过 OceanBase Connector/C 与数据库服务器 OBServer 节点交互的基本方式如下:

  1. 调用mysql_library_init()初始化 MySQL 库。

    mysql_library_init(0, NULL, NULL);
  2. 调用mysql_init()初始化一个连接句柄。

    MYSQL *mysql = mysql_init(NULL);
  3. 调用mysql_real_connect()连接到 OBServer 节点。

    mysql_real_connect (mysql, host_name, user_name, password,
    db_name, port_num, socket_name, CLIENT_MULTI_STATEMENTS)
  4. 调用mysql_real_query()mysql_query()向 OBServer 节点发送 SQL 语句。

    mysql_query(mysql,"sql_statement");
  5. 调用mysql_store_result()mysql_use_result()处理其结果。

    result=mysql_store_result(mysql);
  6. 调用mysql_free_result()释放内存。

    mysql_free_result(result);
  7. 调用mysql_close()关闭与 OBServer 节点的连接。

    mysql_close(mysql);
  8. 调用mysql_library_end()结束 LibOBClient 的使用。

    mysql_library_end();

示例代码

以 mysql_test.c 文件为例,代码如下:

#include "mysql.h"
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
  mysql_library_init(0, NULL, NULL);
  MYSQL *mysql = mysql_init(NULL);
  char* host_name = "xxx.xxx.xxx.xxx";//set your mysql host
  char* user_name = "a****"; //set your user_name
  char* password = "******"; //set your password
  char* db_name = "test"; //set your databasename
  int port_num = 3306; //set your mysql port
  char* socket_name = NULL;
  MYSQL_RES* result;
  MYSQL_FIELD* fields;
  MYSQL_ROW row;
  int status = 0;
  /* connect to server with the CLIENT_MULTI_STATEMENTS option */
  if (mysql_real_connect (mysql, host_name, user_name, password,
    db_name, port_num, socket_name, CLIENT_MULTI_STATEMENTS) == NULL)
  {
    printf("mysql_real_connect() failed\n");
    mysql_close(mysql);
    exit(1);
  }

  /* execute multiple statements */
  status = mysql_query(mysql, "DROP TABLE IF EXISTS test_table;");
                      
  if (status)
  {
    printf("Could not execute statement(s)");
    mysql_close(mysql);
    exit(0);
  }

  status = mysql_query(mysql, "CREATE TABLE test_table(id INT,name varchar(24));");
  status = mysql_query(mysql, "INSERT INTO test_table VALUES(10,'hangzhou'),(20,'shanghai');");
  status = mysql_query(mysql, "UPDATE test_table SET id=20 WHERE id=10;");
  status = mysql_query(mysql, "SELECT * FROM test_table;");

  /* did current statement return data? */
  result = mysql_store_result(mysql);

  if (result)
  {
    /* yes; process rows and free the result set */
    //process_result_set(mysql, result);

    int num_fields = mysql_num_fields(result);
    int num_rows = mysql_num_rows(result);

    printf("result: %d rows %d fields\n", num_rows, num_fields);
    printf("---------------------\n");

    fields = mysql_fetch_fields(result);

    for (int i = 0; i < num_fields; ++i)
    {
      printf("%s\t", fields[i].name);
    }

    printf("\n---------------------\n");

    while ((row = mysql_fetch_row(result)))
    {
      for (int i = 0; i < num_fields; ++i)
      {
        printf("%s\t", row[i] ? row[i] : "NULL");
      }

      printf("\n");
    }

    printf("---------------------\n");

    mysql_free_result(result);
  }
  else          /* no result set or error */
  {
    if (mysql_field_count(mysql) == 0)
     {
       printf("%lld rows affected\n",
            mysql_affected_rows(mysql));
     }
     else  /* some error occurred */
     {
       printf("Could not retrieve result set\n");
     }
  }
  
  status = mysql_query(mysql, "DROP TABLE test_table;");

  mysql_close(mysql);
  return 0;
}

修改代码中的数据库连接参数。参考如下字段,对应的值,则取自步骤一获取的数据库连接参数。

  • host_name:取自 -h 参数,OceanBase 数据库连接的域名。

  • user_name:取自 -u 参数,租户的连接账号

  • password:取自 -p 参数,账号密码。

  • db_name:取自 -D 参数,数据库名称。

  • port_num:取自 -P 参数,OceanBase 数据库连接端口,MySQL 模式租户默认是 3306。

步骤四:运行示例

代码编辑完成后,可以通过如下命令进行编译:

说明

obclient 安装的默认路径为 /u01/obclient

$ g++ -I/u01/obclient/include/ -L/u01/obclient/lib -lobclnt mysql_test.c -o mysql_test

编译完成后,通过如下命令运行示例。

  1. 指定运行路径。

    $ export LD_LIBRARY_PATH=/u01/obclient/lib
  2. 运行 mysql_test。

    $ ./mysql_test
  3. 输出如下结果,说明数据库连接成功,示例语句正确执行。

    ---------------------
    id      name
    ---------------------
    20      hangzhou
    20      shanghai
    ---------------------