使用服务代理时写入数据库的奇怪行为
Strange behaviour on writing to db while using service broker
我正在测试服务代理外部激活器和基于轮询的客户端,代表每个客户端的处理速度性能。
对于外部激活器,我构建了一个命令行应用程序,当某些 table 发生任何更改时会收到通知并写入同一个数据库。 exe里面的代码如下
private static void ProcessRequest()
{
using (var connection = new SqlConnection(ServiceConstant.ConnectionString))
{
connection.Open();
do
{
using (var tran = connection.BeginTransaction())
{
//Get a message from the queue
byte[] message = QueueProcessorUtil.GetMessage(ServiceConstant.QueueName, connection, tran, ServiceConstant.WaitforTimeout);
if (message != null)
{
MessageReceiving = true;
try
{
//Write it to the db
ProcessMessage(message);
}
catch (Exception ex)
{
logger.Write("Fail: " + ex);
}
tran.Commit();
}
else
{
tran.Commit();
MessageReceiving = false;
}
}
}
while (MessageReceiving);
}
}
当我向队列中插入 20 条消息时,所有消息的插入总持续时间约为 10 毫秒
当我提取上面的 ProcessMessage
函数时,它将消息写入数据库到另一个单独的控制台应用程序,然后如下调用此函数 20 次,这次大约需要 50 毫秒
class Program
{
static void Main(string[] args)
{
for (var i = 1; i <= 20; i++)
{
string message = "mm";
ProcessMessaage(message);
}
}
}
ProcessMessage
函数
string sql = @"INSERT INTO [Workflow].[dbo].[TestOrderLog]([OrderId],[RecordTime])
VALUES (@orderId, GETDATE()) SELECT SCOPE_IDENTITY()";
using (SqlConnection con = new SqlConnection(ConfigurationManager.AppSettings["SqlConnection"].ToString()))
using (SqlCommand com = new SqlCommand(sql, con))
{
con.Open();
com.CommandType = CommandType.Text;
com.Parameters.AddWithValue("@orderId", 1);
try
{
var result = com.ExecuteScalar();
var id = (result != null) ? Convert.ToInt32(result) : 0;
}
catch (Exception ex)
{
throw ex;
}
con.Close();
}
虽然在外部激活代码的循环中有昂贵的处理块(查询消息),但我不明白并感到惊讶,但在控制台应用程序代码中编写 db 比纯循环要快。
为什么在循环中纯插入比在外部激活器 exe 实例的代码中插入要慢?
旁注,在 EAService.config 文件中,<Concurrency min="1" max="1" />
这是我的一个荒谬的错误,第一个是编译部署运行代码
第二个是 visual studio 内部的 运行 调试器,因此间隔在 运行 外部调试器中变得正常。
我正在测试服务代理外部激活器和基于轮询的客户端,代表每个客户端的处理速度性能。
对于外部激活器,我构建了一个命令行应用程序,当某些 table 发生任何更改时会收到通知并写入同一个数据库。 exe里面的代码如下
private static void ProcessRequest()
{
using (var connection = new SqlConnection(ServiceConstant.ConnectionString))
{
connection.Open();
do
{
using (var tran = connection.BeginTransaction())
{
//Get a message from the queue
byte[] message = QueueProcessorUtil.GetMessage(ServiceConstant.QueueName, connection, tran, ServiceConstant.WaitforTimeout);
if (message != null)
{
MessageReceiving = true;
try
{
//Write it to the db
ProcessMessage(message);
}
catch (Exception ex)
{
logger.Write("Fail: " + ex);
}
tran.Commit();
}
else
{
tran.Commit();
MessageReceiving = false;
}
}
}
while (MessageReceiving);
}
}
当我向队列中插入 20 条消息时,所有消息的插入总持续时间约为 10 毫秒
当我提取上面的 ProcessMessage
函数时,它将消息写入数据库到另一个单独的控制台应用程序,然后如下调用此函数 20 次,这次大约需要 50 毫秒
class Program
{
static void Main(string[] args)
{
for (var i = 1; i <= 20; i++)
{
string message = "mm";
ProcessMessaage(message);
}
}
}
ProcessMessage
函数
string sql = @"INSERT INTO [Workflow].[dbo].[TestOrderLog]([OrderId],[RecordTime])
VALUES (@orderId, GETDATE()) SELECT SCOPE_IDENTITY()";
using (SqlConnection con = new SqlConnection(ConfigurationManager.AppSettings["SqlConnection"].ToString()))
using (SqlCommand com = new SqlCommand(sql, con))
{
con.Open();
com.CommandType = CommandType.Text;
com.Parameters.AddWithValue("@orderId", 1);
try
{
var result = com.ExecuteScalar();
var id = (result != null) ? Convert.ToInt32(result) : 0;
}
catch (Exception ex)
{
throw ex;
}
con.Close();
}
虽然在外部激活代码的循环中有昂贵的处理块(查询消息),但我不明白并感到惊讶,但在控制台应用程序代码中编写 db 比纯循环要快。
为什么在循环中纯插入比在外部激活器 exe 实例的代码中插入要慢?
旁注,在 EAService.config 文件中,<Concurrency min="1" max="1" />
这是我的一个荒谬的错误,第一个是编译部署运行代码 第二个是 visual studio 内部的 运行 调试器,因此间隔在 运行 外部调试器中变得正常。