Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【腾讯犀牛鸟开源课题实战】对接mysql sdk #188

Open
wants to merge 48 commits into
base: main
Choose a base branch
from

Conversation

PoloDyBala
Copy link

KosmosFult and others added 30 commits October 8, 2024 04:44
error message and truncate need to be complete.
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Add MysqlResultsOption for init buffer size
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
Signed-off-by: yuan cr <2637554776@qq.com>
#### class MysqlResults\<IterMode\>
```c++
class MysqlResult<IterMode>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

模版参数类型有差别,前面的NativeString、vector类型,都指都是数据行类型,这里迭代器类型和数据行类型差别还是挺大的,可以考虑单独封装一个迭代器类型

for (auto row : res) {
// type row: MysqlRow
for (unsigned int i = 0; i < row.NumFields(); i++)
if(!row.IsFieldNull[i])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里为啥是[i],而不是 (i)

proxy->Execute(client_context, exec_res,
"insert into users (username)"
"values (?)", "Jack");
if(exe_res.IsSuccess())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsSuccess接口名可以换成 OK

"insert into users (username)"
"values (?)", "Jack");
if(exe_res.IsSuccess())
size_t n_rows = exec_res.GetAffectedRows()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetAffectedRowNum

}
```

尽管其它Mode的结果集本身也是 `std::vector` 容器,这里也给出了一个单独的迭代模式的抽象,分为行迭代器 `MysqlRowIterator` 和字段迭代器`MysqlFieldIterator`。且在该模式下 `GetResultSet()` 获取的是 `std::vector<MysqlRow>` 。注意:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个迭代器的用法,和NativeString貌似没有本质差别?

迭代器底层也是一次获取所有的响应吧

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NativeString的返回结果本身就是一个vector的迭代器

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

那个迭代器感觉是没什么必要,因为之前Nativestring是返回string,是对原数据的拷贝,想用一个专门的迭代器模式在原始数据上迭代,就有了那个itermode。后来改成stringview感觉就没什么用了

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

那把迭代器模式相关代码去掉,减少复杂性

auto& res_set = query_res.GetResultSet();
int id = std::get<0>(res_set[0]);
std::string email = std::get<1>(res_set[1]);
MysqlTime mtime = std::get<2>(res_set[1]);
Copy link
Contributor

@weimch weimch Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MysqlTime是libmysqlclient提供的?常见的类型及用法也可以列出在文档的表格里,方便检索

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本身不是,简单封装了一下,主要是不想暴露库里原始的类型

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里可以加个注释,提示用户MysqlTime的用法在下面能找到

使用类型绑定,如果模板指定为除 `OnlyExec`,`NativeString`,`IterMode` 之外的其它类型,则结果集的每一行是一个tuple,注意模板参数需要和查询结果匹配:
- 如果模板参数个数与实际查询结果字段个数不一致(因此不能用于 "select *"),则可以通过 `GetAffectedRows()` 返回错误
- 如果模板参数的类型和实际字段类型不匹配(例如用int去接受MySQL的字符串),则**目前运行时不会抛出错误(待后续更新)**,用户需要自行保证类型匹配。
Copy link
Contributor

@weimch weimch Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不抛出错误也没有日志打印吗?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里看下,一般错误得有日志提示,如果没有得简单说下原因

### 获取 MysqlServiceProxy 实例
获取一个下游服务的访问代理对象,类型 trpc::redis::RedisServiceProxy。推荐使用 TrpcClient::GetProxy 方式获取。如果你希望单独使用实例,请注意手动初始化,参考 [mysql_service_proxy_test.cc](../../trpc/client/mysql/mysql_service_proxy_test.cc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

文本打错了,应该使用MysqlServiceProxy

client:
service:
- name: mysql_server
protocol: trpc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protocol这里得改成mysql

timeout: 3000
network: tcp
conn_type: long
is_conn_complex: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mysql下,应该不支持连接复用吧?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

对,这里这个选项是无效的,后续删一下

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

无用配置都可以删掉,只保留必要配置

max_conn_num: 16
idle_time: 40000
mysql:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的mysql配置只是一个proxy独占的吧?如果是的话,yaml注释里说明一下

num_shard_group: 2 # 默认为4,设置连接队列shard的组数
thread_num: 6 # 默认为4,查询任务IO线程池的线程数
thread_bind_core: true # 默认true
enable: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为啥要加个enable?protocol里填mysql应该就算开启了

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

收到 后续删一下

dbname: "test" # 数据库名,一个服务对应一个数据库
num_shard_group: 2 # 默认为4,设置连接队列shard的组数
thread_num: 6 # 默认为4,查询任务IO线程池的线程数
thread_bind_core: true # 默认true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

绑核一般不默认开启,因为云容器下,一个核心会被多个普通容器进程使用,除非是容器本身开启核心独占

password: "abc123" # 用户密码
dbname: "test" # 数据库名,一个服务对应一个数据库
num_shard_group: 2 # 默认为4,设置连接队列shard的组数
thread_num: 6 # 默认为4,查询任务IO线程池的线程数
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

默认多少,这里的数值就填多少


#### 访问过程

1. 获取proxy, 使用 `::trpc::GetTrpcClient()->GetProxy<HttpServiceProxy>(...)`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MysqlServiceProxy

1. 获取proxy, 使用 `::trpc::GetTrpcClient()->GetProxy<HttpServiceProxy>(...)`

```c++
::trpc::ServiceProxyOption option;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

通过ServiceOption创建proxy的例子可以不用提供,因为在其他文档里已经描述比较清楚了,这里不用重复描述

```c++
MysqlResults<int, std::string> res;
auto status = proxy->Query(ctx, res,
"select id, username from users where id = ? and username = ?",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sql的模版用法,也可以开一个章节单独描述下,应该有一些比较高级的用法,试试能不能找得到


| | **描述** |
| ------------------------------------------------------ | ------------------------------------------------------------ |
| `bool OK()` | 查询是否成功。 |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MysqlResult.OK() 和 status.OK() 有啥区别?

| | **描述** |
| ------------------------------------------------------ | ------------------------------------------------------------ |
| `bool OK()` | 查询是否成功。 |
| `const std::string& GetErrorMessage()` | 如果查询有错误,返回错误原因,否则为空。 |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果出错了,status里有错误信息吗?

如果status的错误码和错误信息与MysqlResult是一样的,那看起来没必要给MysqlResult增加这两个接口?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

最初是executor和result不要过多的依赖其他组件,所以让mysqlresult多一个错误接口。目前是trpc status返回出了查询错误之外的其他框架内的错误,mysqlresult返回mysql的查询相关的错误。那之后还是改成把错误也返回给status

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是不是只需要有trpc status就好了?

// example
MysqlResults<OnlyExec> exec_res;
proxy->Execute(client_context, exec_res,
"insert into users (username)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果我这里的SQL语句是select,能执行成功吗?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

能,之前是区别开的,现在已经没区别了

class MysqlResults<OnlyExec>

// example
MysqlResults<OnlyExec> exec_res;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在OnlyExec模式下,GetResultSet、GetFieldsName会返回啥,如果和其他模式有区别,得在上面接口用法里描述清楚

| `Execute`(事务支持) | 在事务中执行 SQL 查询。 | `context`: 客户端上下文; `handle`: 事务句柄; `res`: 用于返回查询结果的 MysqlResults 对象; `sql_str`: 带有占位符 "?" 的 SQL 查询字符串; `args`: 输入参数,可以为空 | `Status` | |
| `AsyncQuery`(事务支持) | 异步在事务中执行 SQL 查询。 | `context`: 客户端上下文; `handle`: 事务句柄 ; `sql_str`: 带有占位符 "?" 的 SQL 查询字符串; `args`: 输入参数,可以为空 | `Future<TransactionHandle, MysqlResults>` | |
| `AsyncExecute`(事务支持) | 异步在事务中执行 SQL 查询。 | `context`: 客户端上下文 ; `handle`: 事务句柄; `sql_str`: 带有占位符 "?" 的 SQL 查询字符串; `args`: 输入参数,可以为空 | `Future<TransactionHandle, MysqlResults>` | |
| `Begin` | 开始一个事务。 | `context`: 客户端上下文; `handle`: 空事务句柄 | `Status` | |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

两个事务,并行修改一个同一行的同一列值,有测过吗?测试效果应该是第一个事务提交了,第二个事务才开始执行

## 错误信息

- 同步接口的 `Status` 返回框架错误,`MysqlResult` 通过 `OK` 和 `GetErrorMessage` 以字符串形式描述MySQL查询错误。因此 `Status` 正常时并不表示 MySQL 查询无错误(例如Timeout)。
- 异步接口如果出错,会返回的 exception future 对象,因为异常future不包含值,因此无法通过 future 里面的 value 即 `MysqlResults` 对象获取MySQL查询错误。因此在异步接口中,不管是框架错误还是MySQL查询错误,均是以异常future的exception返回。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

异步接口,在fiber和线程模式下都能测试ok吧?


创建一个 `TransactionHandle` 变量,作为 `Begin`参数,来开始一个事务。

2. **在事务中执行查询**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我看例子是修改,这个标题得修改下。

另外,事务里也可以查询吧?


和select使用方法相同,只是插入和更新语句由于不返回结果集,请使用 `MysqlResult<OnlyExec>`。同样,也可以使用占位符,对应的参数也支持 `MysqlBlob` 和 `MysqlTime` 。

### 事务
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

缺少在执行事务过程中,有哪些错误,以及出现错误之后如何做的描述

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants