本文主要介绍使用SQLServer时的注意事项。如果你想成为一名高级程序员,你必须知道如何使用数据库。数据库使用的熟练程度也体现了一个开发的水平。下面介绍在使用和设计SQLServer过程中的注意事项。SQLServer注意事项Sql事务启动语句启动事务:BEGINTRANSACTION提交事务:COMMITTRANSACTION回滚事务:ROLLBACKTRANSACTION相关注意事项保持事务短,事务越短越不容易造成阻塞。尽量避免在事务中使用while循环和游标,避免使用访问大量行的语句。不要在交易中要求用户输入。在开始交易之前完成所有计算和查询。避免在同一事务中交错读取和更新。可以使用表变量预先存储数据。即存储过程中的查询和更新是使用两个事务实现的。超时会阻止事务回滚,如果客户端在超时后关闭连接,sqlserver会自动回滚事务。如果不关闭,会造成数据丢失,其他事务会在这个未关闭的连接上执行,造成资源锁,甚至服务器停止响应。避免超时后,也可以开启事务SETXACT_ABORTON统计信息来优化查询速度,准确的统计信息可以避免查询扫描,直接进行索引查找。sp_updatestats可以将统计信息更新到最新。内存不足会导致未被客户端连接的查询计划被清除。修改表结构和修改索引后,查询计划会被清空,修改后可以多次运行查询。DDLDML交错和查询内部SET选项将重新编译查询计划。orderby影响查询速度。where中使用的函数会调用filter进行scan,scantable应该尽量避免。updlock和holdlock可以同时使用,锁定后面需要更新的资源,保持资源完整性,避免冲突。如果不需要使用临时表的统计信息进行大数据查询,表变量是更好的选择。事务使用注意事项设置事务隔离级别(uncommittedread,readdirty),相当于(NOLOCK)语句:SETTRANSACTIONISOLATIONLEVELREADUNCOMMITTED隔离级别说明如下:1.READUNCOMMITTEDREADUNCOMMITTED:未提交读,读取脏数据。默认读取操作:需要申请共享锁,允许其他东西读取锁定的数据但不能修改它。READUNCOMMITTED:读操作不申请锁,允许读取未提交的修改,即允许读取脏数据,读操作不会影响写操作请求独占锁。2、READCOMMITTEDREADCOMMITTED(提交读)是SQLSERVER默认的隔离级别,可以避免读取未提交的数据。隔离级别高于READUNCOMMITTED未提交读;这种隔离级别是在读操作之前先申请并获得共享锁,允许其他读操作读取锁定的数据,但是写操作必须等待锁被释放。一般情况下,读操作完成后会立即释放共享锁。3、REPEATABLEREADREPEATABLEREAD(可重复读):保证在一个事务的两次读操作之间,其他事务不能修改当前事务读取的数据,该级别的事务在获取数据之前必须先获取共享锁。共享锁不会立即释放,共享锁会一直保持到事务完成,所以在这个隔离级别查询和提交事务是非常重要的。4、SERIALIZABLESERIALIZABLE(可序列化),对于前面的REPEATABLEREAD可以保证事务可以被重复读取,但是事务只对第一次运行查询时获取到的数据资源(数据行)加锁,而不能加锁行除了查询结果。是数据表中原本不存在的数据。因此,在一个事务中,当第一次查询和第二次查询过程之间,其他事务进行了插入操作,并且插入的数据满足第一次查询读过滤器的条件,那么在第二次查询的结果中就会有这些新插入的数据数据,这会使两次查询的结果不一致。这种读操作称为幻读。为了避免幻读,需要将隔离级别设置为SERIALIZABLE5,SNAPSHOTTSSNAPSHOT快照:SNAPSHOT和READCOMMITTEDSNAPSHOT两种隔离(可以将事务已经提交的行的前一个版本保存在TEMPDB数据库中)SNAPSHOT隔离级别在逻辑上类似于SERIALIZABLEREADCOMMITTEDSNAPSHOT隔离级别在逻辑上类似于READCOMMITTED,但是在快照隔离级别下,读操作不需要申请共享锁,所以即使数据已经有了排他锁,读取操作不会受到影响。而且您仍然可以获得类似于SERIALIZABLE和READCOMMITTED隔离级别的一致性;如果当前版本与预期版本不一致,读取操作可以从TEMPDB中获取预期版本。如果启用任何基于快照的隔离级别,DELETE和UPDATE语句将在进行修改之前将行的当前版本复制到TEMPDB,而INSERT语句不需要在TEMPDB中进行版本控制,因为还没有行。无论对旧数据启用哪种基于快照的隔离级别,都会对更新和删除操作的性能产生负面影响,但有利于提高读取操作的性能,因为读取操作不需要获取共享锁;5.1SNAPSHOTSNAPSHOT在SNAPSHOT隔离级别下,当读取数据时,可以保证操作读取的行是事务开始时可用的最后提交版本。同时SNAPSHOT隔离级别也满足了之前提交读、可重复读、无幻读;这个隔离级别对共享锁不实用,但是使用SNAPSHOT隔离级别的Row版本控制首先需要在数据库级别设置相关选项5.2READCOMMITTEDSNAPSHOTREADCOMMITTEDSNAPSHOT也是基于行版本控制,但是READ的隔离级别COMMITTEDSNAPSHOT是读操作前的最后一个committed版本,不是事务前提交的版本有点类似于前面的READCOMMITTED,可以保证committedread,但是不能保证repeatablereading,也不能避免幻读,但是更高于READCOMMITTED隔离级别。您可以在不获取共享锁的情况下读取数据。SQLServer[Lock]注意事项1.页锁示例T1:select*fromtable(paglock)T2:updatetablesetcolumn1='hello'其中id>10表示执行T1时,先锁住第一页,然后读完第一页一页后,释放锁,然后锁定第二页,以此类推。假设前10行记录恰好是一页(当然一般不可能一页只有10行记录),那么T1执行到第一页的查询时,不会阻塞更新T2。--------------------2.行锁实例T1:select*fromtable(rowlock)T2:updatetablesetcolumn1='hello'whereid=10说明T1执行时,每行加一个共享锁,读取,然后释放,再锁下一行;T2执行时,会尝试锁定id=10的行,只要该行没有被T1锁定,T2就可以顺利执行更新操作。------------------3.全表锁例子T1:select*fromtable(tablock)T2:updatetablesetcolumn1='hello'其中id=10表示T1执行,给整个表加一个共享锁。在允许T2锁定并开始更新之前,必须完全查询T1。
