Closed zdzDesigner closed 1 month ago
@zdzDesigner If I am understanding correctly, you spawn 2 threads which uses the same connection? If that is the case then it is expected. The operations on a connection are not thread safe.
I added logs for the thread IDs, but they don't seem to be from the same connection
myzql:thread_id:3511020
myzql:thread_id:3511021
ping .......ok!
thread_id:3511020
SQL:select id,user_id,stage_id,update_time,parent_id,title,data from stage
ping .......ok!
thread_id:3511021
SQL:select id,user_id,stage_id,update_time,parent_id,title,data from stage
thread 3511020 panic: integer overflow
/home/zdz/Documents/Try/Zig/fork/myzql/src/protocol/packet_reader.zig:96:23: 0x14c789d in expandBufIfNeeded (bitou)
if (p.buf.len - p.len >= req_n) {
^
/home/zdz/Documents/Try/Zig/fork/myzql/src/protocol/packet_reader.zig:66:32: 0x14c8b08 in readToBufferAtLeast (bitou)
try p.expandBufIfNeeded(at_least);
^
/home/zdz/Documents/Try/Zig/fork/myzql/src/protocol/packet_reader.zig:51:42: 0x14c9437 in readPacket (bitou)
try p.readToBufferAtLeast(payload_length - n_valid_unread);
^
@zdzDesigner Couple of questions to understand this better:
Conn
in src/conn.zig
?If you have same sample code to show how the library is used, it will be helpful too.
I think a minimal test demo is needed.
You are right. I wrote a minimal test demo, and everything is working fine.
const std = @import("std");
const mem = std.mem;
const myzql = @import("myzql");
const Conn = myzql.conn.Conn;
const ResultSet = myzql.result.ResultSet;
const TextResultRow = myzql.result.TextResultRow;
const BinaryResultRow = myzql.result.BinaryResultRow;
const ResultRowIter = myzql.result.ResultRowIter;
const TextElems = myzql.result.TextElems;
const PreparedStatement = myzql.result.PreparedStatement;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const thread = try std.Thread.spawn(.{}, fetchData, .{allocator});
const thread2 = try std.Thread.spawn(.{}, fetchData, .{allocator});
const thread3 = try std.Thread.spawn(.{}, fetchData, .{allocator});
const thread4 = try std.Thread.spawn(.{}, fetchData, .{allocator});
thread.join();
thread2.join();
thread3.join();
thread4.join();
std.time.sleep(std.time.ns_per_s * 3);
}
fn fetchData(allocator: mem.Allocator) !void {
var client = try init(allocator);
const pre_res = try client.prepare(allocator, "select id,user_id,stage_id,update_time,parent_id,title,data from stage");
defer pre_res.deinit(allocator);
// exec ===================
const res = try client.executeRows(&try pre_res.expect(.stmt), .{});
const rows: ResultSet(BinaryResultRow) = try res.expect(.rows);
const rows_iter: ResultRowIter(BinaryResultRow) = rows.iter();
var rets = std.ArrayList(Stage).init(allocator);
while (try rows_iter.next()) |row| {
const op = try row.structCreate(Stage, allocator);
try rets.append(op.*); // 拷贝[]const u8
}
std.debug.print("rets.items.len:{d}\n", .{rets.items.len});
}
fn init(allocator: mem.Allocator) !Conn {
// const bef_time = std.time.microTimestamp();
var client = try Conn.init(allocator, &.{
.username = "xxx",
.password = "xxx",
.database = "xxx",
});
std.debug.print("ping .......", .{});
try client.ping();
std.debug.print("ok!\n", .{});
// const aft_time = std.time.microTimestamp();
// std.debug.print("time:{d},{d}\n", .{ std.time.microTimestamp(), aft_time - bef_time });
return client;
}
pub const Stage = struct {
id: u32 = 0,
user_id: u32 = 0,
stage_id: u32 = 0,
update_time: u32 = 0,
parent_id: u32,
title: []const u8,
data: []const u8,
};
Maybe it's an issue with the arena allocator I'm using
init
, which returns a new Conn for each thread, so this is fine.@zdzDesigner I'm not sure if zig's general purpose allocator is thread-safe based on your machine. When initializing, you may do: var gpa = std.heap.GeneralPurposeAllocator(.{ .thread_safe = true }){};
to enforce thread safety
@speed2exe Thanks a lot. I allocated a GeneralPurposeAllocator separately when calling myzql, and everything worked fine.
like this :
However, concurrent queries on different tables work fine.