Made with Remarkable!
SYBASE ASE15.7 锁定和并发控制学习
锁介绍
粒度
- 表锁
- 页锁
- 行锁
较高粒度的锁定,可以减少获取和管理锁的开销,但是大范围的锁会导致性能的降低。
细粒度的锁定,可以使其他用户访问更多的数据,但是也会增加维护和协调锁的开销,从而降低性能。
若要获取最佳性能,锁定方案必须在并发性和管理开销之间找到平衡。
锁方案
锁定方案指可以通过sp_helpconfig 'lock scheme' 和 sp_configure 'lock scheme','allpages|datapages|datarows'查看和设置的值
- 所有页锁定(allpages) 锁定对象:数据页和索引页 持续时间:整个事务 性能问题:索引键很短,索引页会包含很多键,锁定的行数大大多于数据页,锁竞争激烈。
- 数据页锁定(datapages) 锁定对象:数据页。索引页使用闩锁 持续时间:数据页:整个事务。索引页:物理更改期间 性能问题:闩锁
- 数据行锁(datarows) 锁定对象:数据行。数据页使用闩锁、索引页使用闩锁 持续时间: 数据行:整个事务。数据页:物理更改期间。索引页:物理更改期间 性能问题:闩锁
锁级别
- 数据页或所有页锁表:页锁或表锁
- 数据行锁表:行锁或者表锁
页锁行锁数量超过sp_setpglockpromote 设定阀值,尝试升级表锁,释放行锁页锁。
锁类型
- 页锁和行锁类型: 共享锁、排他锁、更新锁
- 表锁类型: 意图锁、共享锁、排他锁
锁阻塞
共享锁允许共享锁,阻塞排他锁。排他锁阻塞共享锁和排他锁。
锁和事务隔离级别
数据库在并发情况下,可能会造成数据的"更新丢失"、"脏读"、"不可重复读"、"幻读"。sybase 使用两阶段锁协议保证事务的隔离性和一致性,两阶段协议指锁的获取阶段和释放阶段,获取阶段包括读取数据时对数据加共享锁,更新数据时加排他锁,释放阶段指共享锁和排他锁的释放阶段。数据库的隔离级别影响着共享锁的 释放时机 。
- 更新丢失: 一个事务对数据的更改被另外一个事务覆盖。
- 脏读: 一个事务读取到另外一个事务未提交的更改。
- 不可重复读: 一个事务内查询两次的结果不一致。
-
幻读:
一个事务内查询到另一个事务未提交的插入。
sybase 支持四中隔离级别:
- 级别0: 更新数据时加排他锁,读取数据不加锁。不会出现"更新丢失",会出现"脏读"、"不可重复读"、"幻读"
- 级别1: 更新数据时加排他锁,读取数据加共享锁,读取完数据释放共享锁。不会出现"更新丢失"、"脏读",会出现"不可重复读"、"幻读"。
- 级别2: 更新数据加时排他锁,读取数据加共享锁,事务结束释放共享锁。不会出现"更新丢失"、"脏读"、"不可重复读",会出现"幻读"。
-
级别3:
更新数据加时排他锁和范围锁,读取数据加共享锁,事务结束释放共享锁,。不会出现"更新丢失"、"脏读"、"不可重复读"、"幻读"。
数据库的隔离级别越高并发性能越低。
查看锁工具
常用的查看锁的工具有"sp_lock"和"sp_who"、sp_sysmon ,查看锁定对象、类型、级别和spid,但是对象id和spid不容易查看出是哪个应用,哪个ip锁定的哪张表。
sp_object_stats '00:05:00':可以监控特定时间段内锁授予次数、争用最激烈的对象。
查看锁详细信息的另外一种方式:
select pr.spid ,
pr.ipaddr,
pr.program_name,
pr.cmd,
db_name(lc.dbid) as dbname,
obj.objname as tbname,
pr.blocked as lock_spid,
locktype.lockname,
locktype.locktype
from master..syslocks lc
left join master..sysprocesses pr on lc.spid = pr.spid
left join (
select id objid,name objname,db_id('YWST') dbid from YWST..sysobjects
union all
select id objid,name objname,db_id('DB_ATY') dbid from DB_ATY..sysobjects
union all
select id objid,name objname,db_id('DB_ZGZXLCJDDJ_TASK') dbid from DB_ZGZXLCJDDJ_TASK..sysobjects
union all
select id objid,name objname,db_id('JCSZ') dbid from JCSZ..sysobjects
union all
select id objid,name objname,db_id('YYFZ') dbid from YYFZ..sysobjects
) obj on lc.id = obj.objid and lc.dbid = obj.dbid
left join (
select 1 as locktype,'排他表锁' as lockname
union all
select 2 as locktype,'共享表锁' as lockname
union all
select 3 as locktype,'排他意向锁' as lockname
union all
select 4 as locktype,'共享意图锁' as lockname
union all
select 5 as locktype,'排他页锁' as lockname
union all
select 6 as locktype,'共享页锁' as lockname
union all
select 7 as locktype,'更新页锁' as lockname
union all
select 8 as locktype,'排他行锁' as lockname
union all
select 9 as locktype,'共享行锁' as lockname
union all
select 10 as locktype,'更新行锁' as lockname
union all
select 11 as locktype,'共享下一键锁' as lockname
union all
select 256 as locktype,'锁阻塞另一进程' as lockname
union all
select 512 as locktype,'请求锁' as lockname
) locktype on lc.type = locktype.locktype
思考
在排查NP问题中发现,锁定的"粒度"、"类型"、"级别",严重影响后着系统的性能,我们是否可以通过锁原理的应用来解决问题呢?
例如:
- ddts 大量的删除插入在没有索引的情况下会造成排他表锁,有索引的情况下也会应为锁过多而升级成表锁,导致查询和更新阻塞,是否可以设置锁升级阀值来缓解问题呢?
- 在没有做读写分离的省份,统计分析和综合统计等查询类应用会造成业务表上加长时间的共享锁,从而阻塞案件的保存操作,是否可以通过设置查询类应用的隔离级别为0,来避免长时间的共享锁呢?