锁定:通俗的讲就是加锁。锁定是 Microsoft SQL Server 数据库引擎用来同步多个用户同时对同一个数据块的访问的一种机制。
定义:当有事务操作时,数据库引擎会要求不同类型的锁定,如相关数据行、数据页或是整个数据表,当锁定运行时,会阻止其他事务对已经锁定的数据行、数据页或数据表进行操作。只有在当前事务对于自己锁定的资源不在需要时,才会释放其锁定的资源,供其他事务使用。
一、锁的种类与范围(如下表)
锁类型
说明
共享 (S)
用于不更改或不更新数据的读取操作,如 SELECT 语句。
更新 (U)
用于可更新的资源中。 防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。
独占(也可称排他)(X)
用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。 确保不会同时对同一资源进行多重更新。
意向
用于建立锁的层次结构。 意向锁包含三种类型:意向共享 (IS)、意向排他 (IX) 和意向排他共享 (SIX)。
架构
在执行依赖于表架构的操作时使用。 架构锁包含两种类型:架构修改 (Sch-M) 和架构稳定性 (Sch-S)。
大容量更新 (BU)
在向表进行大容量数据复制且指定了 TABLOCK 提示时使用。
键范围
当使用可序列化事务隔离级别时保护查询读取的行的范围。 确保再次运行查询时其他事务无法插入符合可序列化事务的查询的行。
(一)共享锁
共享锁(S 锁)允许并发事务在封闭式并发控制下读取 (SELECT) 资源。
当查询(SELECT)某条记录时,SQL SERVER 会尝试取得该条记录的上存在共享锁(S 锁),或无法获取,就必须等待别人释放对该记录中某几种与共享锁互斥的锁,才能在设置共享锁之后,获取该条记录。
举例来说:当某人查询某张表的一条记录时,就会在该记录上放置共享锁,在而其他人也要查询这张表的此记录时,因为共享锁彼此不互斥,所以也可以再次放置共享锁,也就是说SQL SERVER允许不同连接同时读取相同的数据。如果此时有人要更新此记录,因为独占锁与共享锁互斥,所以无法放置独占锁,要等到所有读取此记录的人都读取完毕,释放了共享锁,更新数据的人才能对该记录设置独占锁,并进一步更新数据。一般情况下,在默认的事务隔离级别下,当数据读取完毕,SQL SERVER就会释放共享锁,除非有特别的设置。
(二)更新锁
更新锁是一种中继锁。当同一项资源从原来的查询操作转换为更新操作时,锁定机制会从共享锁变为更新锁,再进一步变成独占锁。
在可重复读或可序列化事务中,此事务读取数据 [获取资源(页或行)的共享锁(S 锁)],然后修改数据 [此操作要求锁转换为独占锁(X 锁)]。 如果两个事务获得了资源上的共享模式锁,然后试图同时更新数据,则一个事务尝试将锁转换为独占锁(X 锁)。 共享模式到独占锁的转换必须等待一段时间,因为一个事务的独占锁与其他事务的共享模式锁不兼容;发生锁等待。 第二个事务试图获取独占锁(X 锁)以进行更新。 由于两个事务都要转换为独占锁(X 锁),并且每个事务都等待另一个事务释放共享模式锁,因此发生死锁。
若要避免这种潜在的死锁问题,请使用更新锁(U 锁)。 一次只有一个事务可以获得资源的更新锁(U 锁)。 如果事务修改资源,则更新锁(U 锁)转换为独占锁(X 锁)。
例如,当查询一条记录后,要将此内容更新(Update语句加上Where条件),一定会先查找记录,在查找的过程中就会对相关的记录放置共享锁,等找到相应的记录之后,SQL SERVER 会先对记录放置更新锁,以避免发生死锁。因为共享锁与更新锁并不互斥,如果两个人同时对同一条记录放置共享锁,先进行更新的人,可以在别人也对同一条记录放置了共享锁时,继续放
对于一个软件企业来说,源代码就是公司全体智慧的结晶,绝不能有任何闪失。但对于公司产品的基石数据库怎么来进行统一管理呢?通常,是直接备份数据库文件的方式,或者生成数据库的部署脚本,来重复的备份。这个方法可行,却有些值得改进的地方。首先,太繁琐了,浪费精神;其二,不方便和其它项目同时管理。下面,就介绍我偶然看到的方法,当然,可能有很多人已经这么做了,但分享给那些还不知道的人。
大体思路:
本示例采用VisualSVN-Server(Subversion 服务器)、AnkhSvn(VS 2010的Svn 插件)、SQL Server2005、VS 2010,示例数据库为AdventureWorks。
因为安装的是英文版的VS2010,大家就对应着中文的看吧。
第一步:通过VS 2010 创建数据库项目。打开VS 2010,File->New->Project,在Recent Templates中选中Database->SQL Server,并在右面的项目类型中选中SQL Server 2005 Database Project,输入项目名称,并点击OK。
第二步:在新建的ExampleSystemSQL项目上点右键,选中菜单中的Import Database Objects and Settings,
会弹出一个对话框,让我们选择数据库。可以通过Tools->Connect to Database创建。为了简单,就直接选已有的AdventureWorks连接。
单击Start就开始将SQLServer2005中数据库AdventureWorks的定义取回到项目中来。
点击Finish,就可以看到AdventureWorks的定义了。
第三步,将整个项目添加到版本管理中。事先已在一台服务器上安装了VisualSVN-Server-2.5.8,并创建了一个库叫Unique,SVN地址是:https://server2003/svn/unique。同样,选中ExampleSystemSQ项目点右键,选择里面的Add Sulution to Subversion…
在弹出的对话框中输入Repository Url,https://server2003/svn/unique,如下图,并点击OK。如果需要认证的话,就输入在VisualSVN-Server中建立的用户名和密码。
在弹出的日志输入对话框中直接点击OK。刚才的步骤只是把项目添加的svn副本的本地,还没有提交,所以需要再次在解决方案上点右键,选中Commit Solution Changes,输入日志,点击OK,就行了。
至此,我们为AdventureWorks数据库创建了版本管理,那如果我们修改了AdventureWorks呢,该怎么实现同步呢,下面,就是VS 2010的强大之处了。首先,在AdventureWorks中创建了一个新表名字叫dbo.Table_1。再打开VS 2010中的Data->Schema Compare(架构比较)-> New Schema Comparison,配置源数据库和目标项目,如下图所示。Source Schema选择数据库,Target Schema 选择Project ExampleSystemSQL项目。
点击OK,VS 2010就开始进行架构比较,结果如下图:
可以看到刚刚新建的表Table_1,在空白处,点击右键,选择Write Updates,在确认对话框中点击OK,就会把新建表Table_1的定义保存到项目中。
马上,就可以在VS项目中看到新添加的Table_1的SQL脚本文件了。
接下来,就可以将更新的脚本提交到SVN中,与普通的C#项目没什么差别。
值得注意的一点是,在VS 2010 项目ExampleSystemSQL中,可以直接添加新表的定义,再同步到AdventureWorks数据库中,也是通过Data->Schema Compare(架构比较)->New Schema Compasion来实现的。同步是双向的。VS 2010 可以对ExampleSystemSQL项目生成部署脚本。
转载请注明作者博客地址:http://www.cnblogs.com/ProJKY
本文链接
第一种方法:
select *from ( select Url,case when Month=01 then '1月' when Month=02 then '2月' when Month=03 then '3月' when Month=04 then '4月' when Month=05 then '5月' when Month=06 then '6月' when Month=07 then '7月' when Month=08 then '8月' when Month=09 then '9月' when Month=10 then ' 10月' when Month=11 then '11月' when Month=12 then ' 12月'
end month,Quality from (
select Url,DATENAME(M,AuditingTime)Month,SUM(Quality) Quality from tb_order as a left join tb_WebSiteInfo as b on a.WebSiteInfoID=b.ID left join tb_OrderList as c on c.OrderID=a.ID where AuditingTime>'2013-01-01' and b.ID>0 and Auditing=2
group by Url,DATENAME(M,AuditingTime) )as h ) as hh
pivot ( sum(Quality) for month in([1月],[2月],[3月],[4月],[5月],[6月],[7月],[8月],[9月],[10月],[11月],[12月])) as a
第二种方法:
declare @sql varchar(8000)
select @sql = isnull(@sql + ',' , '') + '['+CONVERT(varchar(7),AuditingTime,20)+']'
from tb_order as a left join tb_WebSiteInfo as b on a.WebSiteInfoID=b.ID left join tb_OrderList as c on c.OrderID=a.ID where AuditingTime>'2013-01-01' and b.ID>0 and Auditing=2
group by CONVERT(varchar(7),AuditingTime,20) print @sql declare @sql2 varchar(8000)='' set @sql2=' select *from (
select Url, CONVERT(varchar(7),AuditingTime,20) AuditingTime,SUM(Quality) Quality from tb_order as a left join tb_WebSiteInfo as b on a.WebSiteInfoID=b.ID left join tb_OrderList as c on c.OrderID=a.ID where b.ID>0 and Auditing=2
group by Url, CONVERT(varchar(7),AuditingTime,20)
) as hh pivot (sum(Quality) for AuditingTime in (' + @sql + ')) b'
print @sql2
exec(@sql2)
本文链接