来源: SqlServer性能优化 提高并发性能(八) – 孙丽媛 – 博客园
并发访问:
当多个线程访问同一个资源,会产生并发性问题
并发控制与处理:
乐观并发控制:一种方式是“后来的更新者获胜” 这意味着先来的用户提交的值会在没有察觉的情况下丢失。
为记录加锁以阻止其他事物访问某些记录,是避免产生并发冲突的一种技术
悲观并发控制:
1.一个线程操作表,造成整个表被锁定
2.其他线程访问与操作任何记录都被阻止
3.其他线程可以添加记录
4.最小的吞吐量、最差的性能
事物恢复与检查点:
事物指南:
1.事物尽量简单
2.事物尽量只包含必要的语句;验证与查询等语句放置在事物之外
3.避免事物与用户的交互
避免锁的问题:
1.丢失的更新
2.脏读
3.不一致性分析
4.幻象集
锁的粒度:
锁的类型:
平衡乐观与悲观并发访问:
1.建立合适的索引
2.操作语句尽量放到短事物中
3.操作语句尽量指定特定的筛选条件、窄的访问列
4.索引查询提示
5.应用程序访问模式
创建表:
1
2
3
4
5
6
7
8
|
create table Employee(id int identity(1,1),name varchar(500),age int ) insert Employee values( 'caochao' ,34) insert Employee values( 'ligang' ,28) insert Employee values( 'zhangqing' ,36) insert Employee values( 'huang' ,23) go begin tran update Employee set age=age+1 where age>=30 |
新建一个查询窗口:
1
|
select * from Employee |
访问就被阻塞掉了。没有结果。
执行删改查的方法都没什么用。
1
2
3
4
|
select * from Employee where age>30 select * from name,age from employee where age<30 update employee set age=age+1 where age<30 delete employee where age=20 |
添加是可以的:
1
|
insert Employee values( 'xili' ,50) |
查看锁的命令:
1
|
sp_lock |
进行回滚把锁释放:
1
|
rollback tran |
没有排他锁:
创建非聚簇索引:
1
|
create nonclustered index nc_Employee_age on Employee(age) include(name) |
模拟开启事物不结束:
1
2
|
begin tran update Employee set age=age+1 where age>=30 |
锁的情况:
访问如下两个语句不行:
1
2
|
select * from Employee select * from Employee where age>30 |
这条语句可以访问(锁住的行不能访问,不锁的是可以访问的):
1
|
select name,age from employee where age<30 |
在非聚集的索引页面进行了age进行了物理排序,访问的是在被锁住行排序的上面。并不需要穿透锁住的行
这句语句是不能执行的:(无法穿透>30的记录)
1
|
select * from Employee where age<20 |
在执行跟新语句:
1
|
update employee set age=age+1 where age<30 |
无法执行,查看执行计划,直接进行了表扫描:
在执行一条查询语句:执行的表扫描 不能进行查询
1
|
select * from Employee where age<30 |
执行删除语句:(可以) 执行的是非聚集索引
1
|
delete employee where age=20 |
应用索引提示的方法:
1
|
select * from employee with(index=nc_Employee_age) where age<30 |
查看执行计划:
update 不能用索引提示:
硬性访问: readpast 绕过被排他锁锁住的行,直接往下面进行访问
1
|
select * from Employee with(readpast) |
结果:(只能访问不被锁住的)