多个 Npsql 连接
Multiple Npsql connections
我正在尝试创建一个简单的服务器 (.Net Core 5.0),它通过 Npgsql + Npgsql.EntityFramework.
与 PostgreSQL DB (v 13.1) 通信
我有创建新用户、授予某些权限和检索 OID 的代码:
string connString =
String.Format(
"Server={0};Username={1};Database={2};Port={3};Password={4};SSLMode=Prefer",
PSqlHost, User, DBname, PSqlPort, Password);
NpgsqlConnection psqlConnection = null;
try
{
using (psqlConnection = new NpgsqlConnection(connString))
{
psqlConnection.Open();
StringBuilder cmdBuilder = new StringBuilder();
cmdBuilder.Append(string.Format("CREATE USER {0} WITH LOGIN PASSWORD '{1}';\r\n", signIn.Login, signIn.Pass));
cmdBuilder.Append(string.Format("GRANT SELECT ON ALL TABLES IN SCHEMA public TO {0};\r\n", signIn.Login));
cmdBuilder.Append(string.Format("GRANT SELECT, UPDATE ON ALL TABLES IN SCHEMA users TO {0};\r\n", signIn.Login));
cmdBuilder.Append(string.Format("SELECT oid FROM pg_catalog.pg_authid WHERE rolname='{0}';\r\n", signIn.Login));
using (var pgCmd = psqlConnection.CreateCommand())
{
pgCmd.CommandText = cmdBuilder.ToString();
if (!pgCmd.IsPrepared) pgCmd.Prepare();
using (var reader = pgCmd.ExecuteReader())
{
if (!reader.HasRows) return TcpMessageSpec.Fail;
if (!reader.IsOnRow) reader.Read();
var oid = (uint)reader.GetValue(0);
}
}
}
return TcpMessageSpec.OK;
}
catch (PostgresException ex)
{
Log.Exception(ex.MessageText);
if (ex.SqlState == PostgresErrorCodes.InvalidPassword) return TcpMessageSpec.AuthFailed;
else if (ex.SqlState == PostgresErrorCodes.DuplicateObject) return TcpMessageSpec.UserExists;
return TcpMessageSpec.ConnectionFailed;
}
catch (Exception ex)
{
Log.Exception(ex.InnerException);
return TcpMessageSpec.ConnectionFailed;
}
finally
{
}
此代码在单线程中完美运行,但我希望它在多线程中运行。
当我 运行 来自五个或更多线程的代码时,我捕获 PostgresException: "XX000: tuple concurrently updated"
。然而,一些线程成功了(无一例外,OID被检索)。
尝试解决(但结果相同):
- 我试过 NPSql 的异步版本
- 使用的 NpgsqlConnection 事务
- Batched/Not 批量命令查询
- 我看过类似的问题
但是我还是不明白我的错误在哪里。
tuple concurrently updated
是一个错误 PostgreSQL 有时 returns 当并发执行某些 DDL 操作时(参见 this discussion)。这与 Npgsql 没有任何关系——您可能必须使用同步来确保这些 DDL 操作不会并行发生。
我正在尝试创建一个简单的服务器 (.Net Core 5.0),它通过 Npgsql + Npgsql.EntityFramework.
与 PostgreSQL DB (v 13.1) 通信我有创建新用户、授予某些权限和检索 OID 的代码:
string connString =
String.Format(
"Server={0};Username={1};Database={2};Port={3};Password={4};SSLMode=Prefer",
PSqlHost, User, DBname, PSqlPort, Password);
NpgsqlConnection psqlConnection = null;
try
{
using (psqlConnection = new NpgsqlConnection(connString))
{
psqlConnection.Open();
StringBuilder cmdBuilder = new StringBuilder();
cmdBuilder.Append(string.Format("CREATE USER {0} WITH LOGIN PASSWORD '{1}';\r\n", signIn.Login, signIn.Pass));
cmdBuilder.Append(string.Format("GRANT SELECT ON ALL TABLES IN SCHEMA public TO {0};\r\n", signIn.Login));
cmdBuilder.Append(string.Format("GRANT SELECT, UPDATE ON ALL TABLES IN SCHEMA users TO {0};\r\n", signIn.Login));
cmdBuilder.Append(string.Format("SELECT oid FROM pg_catalog.pg_authid WHERE rolname='{0}';\r\n", signIn.Login));
using (var pgCmd = psqlConnection.CreateCommand())
{
pgCmd.CommandText = cmdBuilder.ToString();
if (!pgCmd.IsPrepared) pgCmd.Prepare();
using (var reader = pgCmd.ExecuteReader())
{
if (!reader.HasRows) return TcpMessageSpec.Fail;
if (!reader.IsOnRow) reader.Read();
var oid = (uint)reader.GetValue(0);
}
}
}
return TcpMessageSpec.OK;
}
catch (PostgresException ex)
{
Log.Exception(ex.MessageText);
if (ex.SqlState == PostgresErrorCodes.InvalidPassword) return TcpMessageSpec.AuthFailed;
else if (ex.SqlState == PostgresErrorCodes.DuplicateObject) return TcpMessageSpec.UserExists;
return TcpMessageSpec.ConnectionFailed;
}
catch (Exception ex)
{
Log.Exception(ex.InnerException);
return TcpMessageSpec.ConnectionFailed;
}
finally
{
}
此代码在单线程中完美运行,但我希望它在多线程中运行。
当我 运行 来自五个或更多线程的代码时,我捕获 PostgresException: "XX000: tuple concurrently updated"
。然而,一些线程成功了(无一例外,OID被检索)。
尝试解决(但结果相同):
- 我试过 NPSql 的异步版本
- 使用的 NpgsqlConnection 事务
- Batched/Not 批量命令查询
- 我看过类似的问题
但是我还是不明白我的错误在哪里。
tuple concurrently updated
是一个错误 PostgreSQL 有时 returns 当并发执行某些 DDL 操作时(参见 this discussion)。这与 Npgsql 没有任何关系——您可能必须使用同步来确保这些 DDL 操作不会并行发生。