elr*_*anu 111 sql-server best-practices transaction
总是创建交易是一种不好的做法吗?
例如,为一个简单的SELECT?
在没有必要的情况下创建交易的成本是多少?
即使您使用的是像 那样的隔离级别READ UNCOMMITTED,这是否是一种不好的做法?
Kin*_*hah 116
总是创建交易是一种不好的做法吗?
这取决于您在这里谈论的上下文。如果是更新,那么我强烈建议明确使用 TRANSACTIONS。如果它是一个 SELECT 则 NO(明确地)。
但是等等,首先要了解更多:sql server 中的所有内容都包含在一个事务中。
当会话选项IMPLICIT_TRANSACTIONS是OFF并且您明确指定时begin tran,commit/rollback这通常称为显式事务。否则你会得到一个自动提交事务。
当 IMPLICIT_TRANSACTIONS被ON一个隐性事务执行的书网上的文章(如记录的类型的语句时,会自动启动SELECT/ UPDATE/ CREATE),它必须被提交或回滚明确。BEGIN TRAN在这种模式下执行 a将增加@@TRANCOUNT并启动另一个“嵌套”事务)
要切换您所处的模式,您可以使用
SET IMPLICIT_TRANSACTIONS ON
Run Code Online (Sandbox Code Playgroud)
或者
SET IMPLICIT_TRANSACTIONS OFF
select @@OPTIONS & 2
Run Code Online (Sandbox Code Playgroud)
如果上面返回 2,则您处于隐式事务模式。如果它返回 0,则您处于自动提交状态。
在不需要时创建交易的成本是多少?
需要事务将数据库从一种一致状态带入另一种一致状态。交易没有成本,因为没有交易的替代品。参考:使用基于行版本控制的隔离级别
即使您使用的是 read_uncomitted 隔离级别。是不好的做法吗?因为它不应该有锁定问题。
READ_UNCOMMITED 隔离级别根据定义将允许脏读,即一个事务将能够看到其他事务所做的未提交更改。这个隔离级别的作用是,它放宽了锁的开销——获取锁以保护数据库并发的方法。
您可以在连接/查询级别使用它,这样它就不会影响其他查询。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
Run Code Online (Sandbox Code Playgroud)
找到了Jeff Atwood 的一篇有趣的文章,该文章描述了由于 Dining Philosophers Puzzle 导致的死锁,并描述了 读提交的快照隔离级别。
出于好奇,我做了一些测试,用 Perfmon 计数器(如 Log Bytes Flushed/Sec、Log Flush Waits/Sec(每秒等待 LOG 刷新发生的提交数)测量对 T-log 的影响,如下图:

示例代码:
create table testTran (id int, Name varchar(8))
go
-- 19 sec
-- Autocommit transaction
declare @i int
set @i = 0
while @i < 100000
begin
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
---------------------------------------------------
-- 2 sec
-- Implicit transaction
SET IMPLICIT_TRANSACTIONS ON
declare @i int
set @i = 0
while @i < 100000
begin
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
COMMIT;
SET IMPLICIT_TRANSACTIONS OFF
----------------------------------------------------
-- 2 sec
-- Explicit transaction
declare @i int
set @i = 0
BEGIN TRAN
WHILE @i < 100000
Begin
INSERT INTO testTran values (1,'Kin Shah')
set @i = @i+1
End
COMMIT TRAN
Run Code Online (Sandbox Code Playgroud)
自动提交交易:(编辑为@TravisGan 突出显示)
隐式和显式事务:
有一个 DMV sys.dm_tran_database_transactions将在数据库级别返回有关事务的信息。
显然,这更像是一种显示影响的简单测试。其他因素,如磁盘子系统、数据库自动增长设置、数据库的初始大小、在同一服务器\数据库上运行的其他进程等也会产生影响。
从上面的测试来看,隐式和显式交易几乎没有区别。
感谢@TravisGan 帮助添加更多答案。
And*_*mar 40
SQL 语句始终在事务中运行。如果不显式启动,每条 SQL 语句都将在其自身的事务中运行。
唯一的选择是是否在一个事务中捆绑多个语句。跨越多个语句的事务会留下损害并发性的锁。所以“总是”创建交易不是一个好主意。您应该平衡成本与收益。
| 归档时间: |
|
| 查看次数: |
76853 次 |
| 最近记录: |