正如先前的Stack Overflow问题(TransactionScope和连接池以及SqlConnection如何管理IsolationLevel?)所证明的那样,事务隔离级别在SQL Server和ADO.NET(也是System.Transactions和EF)的池化连接中泄漏,因为它们建立在ADO.NET).
这意味着,在任何应用程序中都可能发生以下危险事件序列:
问题:防止这种情况的最佳方法是什么?现在到处都需要使用显式交易吗?
这是一个独立的复制品.您将看到第三个查询将继承第二个查询中的Serializable级别.
class Program
{
static void Main(string[] args)
{
RunTest(null);
RunTest(IsolationLevel.Serializable);
RunTest(null);
Console.ReadKey();
}
static void RunTest(IsolationLevel? isolationLevel)
{
using (var tran = isolationLevel == null ? null : new TransactionScope(0, new TransactionOptions() { IsolationLevel = isolationLevel.Value }))
using (var conn = new SqlConnection("Data Source=(local); Integrated Security=true; Initial Catalog=master;"))
{
conn.Open();
var cmd = new SqlCommand(@"
select
case transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN …Run Code Online (Sandbox Code Playgroud) sp_reset_connection似乎由SQL Server连接池调用,以确保从池中重用的连接重置其大部分设置.有没有人确切地知道它做了什么但不做什么呢?
例如,我从这篇文章中看到它没有重置事务隔离级别
我的探查器跟踪显示exec sp_reset_connection在每个sql批处理或过程调用之间调用.这是有原因的,但是如果我确信没有必要提高性能,我可以阻止它被调用吗?
更新:我认为这可以提高性能的原因有两个:
exec sp_reset_connection,等待响应,然后发送它真正想要执行的任何sql.第二个好处是我感兴趣的那个,因为在我的架构中,客户端有时与数据库有一定距离.如果每个sql批处理或rpc都需要双向往返,则会使任何网络延迟的影响加倍.消除这种双重调用可能会提高性能.
是的,我可以做很多其他事情来改善性能,比如重新构建应用程序,我是解决问题根本原因的忠实粉丝,但在这种情况下我只想知道是否可以阻止sp_reset_connection被称为.然后我可以测试是否有任何性能改进,并正确评估不调用它的风险.
这提示了另一个问题:与sp_reset_connection的网络通信是否真的如上所述?即客户端是否发送exec sp_reset_connection,等待响应,然后发送真正的SQL?或者这一切都在一块?
我想为我的c#应用程序中的某些进程应用一些sql-session级别设置.
例如,我想DEADLOCK_PRIORITY为一些后台进程设置LOW.
问题是:
如果我打开一个新的SQL连接,那会启动一个新的sql-session吗?
sql-session会一直存在,直到连接关闭?如果我在SqlConnection打开后立即应用我的设置,它们是否对在相同的情况下执行的所有查询有效SqlConnection?
连接池怎么样?这可能是我的SET DEADLOCK_PRIORITY LOW设置将被我的系统中的其他进程(我不想要)重用,因为SqlConnection实际上并没有关闭(asp.net连接池决定重用它).
谢谢!
通常,在会话中创建的临时表会保留在该会话中,并在关闭连接时被删除.但是,由于我正在使用连接池,并且在java.sql.Connection.close()调用时实际上并未关闭物理连接,因此我发现临时表停留并影响下一个会话.
这会导致DB上的资源泄漏,因为临时表不会立即释放,以及由于表名冲突而导致的名称冲突.
直观地说,当我借用连接时,我期待一个干净的名单.如何实现这一目标?
sp_reset_connection.除临时表外,此问题还会影响:
我想知道使用EF上下文sp_getapplock和会话所有者类型的风险/安全性.基于文档,我的理解是会话所有者意味着如果在此之前没有明确释放,则会话结束时将释放锁定.我假设这也意味着连接结束.
我已经将这一切都用于事务拥有的锁,但这带来了其他问题和复杂性,所以我想知道如何使用会话拥有的锁以及它将如何或不会与行为DbContext及其连接发生冲突处理.
我不是100%确定DbContext默认情况下是如何工作的,无论是使用池还是每个上下文实例都打开并关闭它自己的连接(我读过的文档似乎暗示后者).对于这个问题,假设我没有做任何关于连接管理的事情(我很少这样做),所以EF正在处理它,或处理它的任何处理.
如果我创建一个DbContext实例,抓取连接,执行SQL来创建一个会话拥有的锁,正常使用上下文,不释放锁并处理上下文,这会正常工作吗?(实际上,这将是一个IDisposable包装,以防止这种情况,但问题仍然存在.)
为了说明不好:
using (var ctx = new MyContext()) {
var conn = ctx.Database.Connection.Open();
conn.ExecuteSqlSomehow("sp_getapplock blahblah");
try {
// Lots of queries, savechanges, etc.
} finally {
// Oops I forgot to conn.ExecuteSql("sp_release the lock");
}
}
await WatchMovieAsync();
using (var ctx = new MyContext()) {
// Can this reuse the same connection, session and/or lock?
}
Run Code Online (Sandbox Code Playgroud)
问题:
using块内? …如何将db_owner固定数据库角色的所有权限和特权授予应用程序角色?
命令:
GRANT CONTROL ON [DatabaseName] TO [ApplicationRoleName];
Run Code Online (Sandbox Code Playgroud)
将是我想要的,但它失败了:
消息 15151,级别 16,状态 1,第 23 行
找不到对象“DatabaseName”,因为它不存在或您没有权限。
我正在研究使用 SQL Server Application Roles。
连接到服务器后,您的应用程序将运行一个存储过程以作为应用程序“登录”自己:
EXECUTE sp_SetAppRole @rolename = 'Contoso.exe', @password =
'Tm8gaSBkaWRuJ3QganVzdCBiYXNlNjQgZW5jb2RlIGEgcGFzc3dvcmQuIEl0J3Mgb25seSBhbiBleGFtcGxlIQ==';
Run Code Online (Sandbox Code Playgroud)
通常,应用程序以作为db_owner固定角色成员的用户身份登录。该角色具有以下权限:db_owner
而同时:
您不能将应用程序角色置于数据库角色中
那么,问题来了:如何授予我的应用程序角色所有权限(即执行所有操作)?
因此,现在是向角色授予权限的时候了。按照此页面的建议:
GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO [Contoso.exe]; …Run Code Online (Sandbox Code Playgroud) sql-server security permissions sql-server-2005 application-role
由于我遇到的一些问题,我正在尝试使用.NET Framework 4中的连接池.使用SQL事件探查器,我可以看到每次从连接池中获取连接时,都会执行存储过程sp_reset_connection.
要摆脱这种重置(我实际上不需要sp_reset_connection).我已经尝试将连接字符串中的连接重置参数设置为false,但这似乎没有任何效果.我在想,也许我误解了Connection reset参数的用途.
我注意到http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring.aspx中没有记录Connection reset参数.但它在许多其他地方也有提及,例如http://www.techrepublic.com/article/educate-yourself-about-net-sql-server-connection-string-syntax/6084879.
如果我将Conection Reset标志设置为无效值(例如'hello'),则在打开连接时会出现异常,表明实际使用了连接重置标志.
ADO.NET是否真的关心连接重置标志?
我的代码如下:
static void Main(string[] args)
{
const string connectionString =
"Data Source=(local);Initial Catalog=MyDatabse;User ID=sa;Password=<removed>;Connection Timeout=5;Pooling=true;Min Pool Size=1; Max Pool Size=1; Enlist=false; Connection Reset=false;";
var connections = new List<SqlConnection>();
for (int i = 0; i < 1000000; i++)
{
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand command = new SqlCommand("SELECT * FROM DatabaseVersion", conn);
command.ExecuteNonQuery();
connections.Add(conn);
}
}
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试习惯使用C#中的"使用"块,但我很难理解何时应该使用它们.
这是一个例子.
我的原始代码,没有using块:
SqlConnection conn = new SqlConnection(cCon.getConn());
SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@x", xxx));
cmd.Parameters.Add(new SqlParameter("@ORG", ORG));
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{ }
finally
{
conn.Close();
}
Run Code Online (Sandbox Code Playgroud)
但我真的应该这样做吗?或者我应该使用(SqlConnection conn = new SqlConnection(cCon.getConn()))?请帮我理解这个.我最初这样做的方式错了吗?
SqlConnection conn = new SqlConnection(cCon.getConn());
using( SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@x", xxx));
cmd.Parameters.Add(new SqlParameter("@ORG", ORG));
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{ }
finally
{ …Run Code Online (Sandbox Code Playgroud) sql-server ×7
c# ×3
.net ×2
ado.net ×2
asp.net ×2
sql ×2
mysql ×1
performance ×1
permissions ×1
security ×1
t-sql ×1
transactions ×1