zoukankan      html  css  js  c++  java
  • sybase锁机制以及死锁避免

    在数据库实现中,通过锁定机制控制数据库的并发访问,保证数据库访问的正确性。根据定义:

    锁定是一种并发控制机制:它可以确保数据在同一事务中和不同事务之间保持一致。在多用户环境中,由于几个用户可能会在同一时间使用同一数据,因此需要锁定功能。

    sybase锁分类

    按照锁性质可以分为共享锁,排他锁。当在数据库事务中,读取信息时,会对数据库添加共享锁。当修改信息时,会添加排他锁。

    按照锁的粒度,可以分为行锁,页锁,表锁等。

    sybase隔离级别

    sybase分为0,1,2,3四个隔离级别。

    0  读取未提交的,允许事务读取未提交的数据更改,排他锁在对数据库进行写操作后立即释放,不会持有到事务提交或回滚。
    1 读取已提交的,仅允许事务读取已提交的数据更改,排他锁持有到事务提交或回滚,但共享锁在加载数据到内存后立即释放。
    2 可重复读取事务可重复同一查询,事务读取过的任何行都不会被更新或删除,排它锁和共享锁都会持有到事务结束,查询结果集不可以删除和修改,但是可以插入。
    3 可串行化读取事务可重复同一查询,且得到完全相同的结果。不能插入任何将出现在结果集中的行,排它锁和共享锁都会持有到事务结束,查询结果集不可以增删改。

    可以使用select @@isolation语句查看数据库的隔离级别。

    sybase数据库通常隔离界别设置为1,值得注意的是使用WAS通过jdbc连接数据库上,经常会将隔离级别提升为2。在使用E-SQL编译时,通常将隔离级别提升为3。

    sybase死锁

    sybase数据库出现死锁,即处于死锁中的各事务,都持有锁,但又都在等待其他锁,从而组成一个环,造成死锁。

    最简单的死锁情况,事务T1,T2,执行顺序相反,会造成死锁,情形如下:

    执行顺序

    T1 T2
    1 排他锁A  
    2   排他锁B
    3 排他锁B  
    4   排他锁A

    这时候,会出现事务T1持有排他锁A,同时等待排他锁B,事务T2持有排他锁B,等待排他锁A。这是就造成了T1等待T2释放排他锁B,T2等待T1释放排他锁A,形成一个死锁环。

    多个事务出现死锁时,情形与两个事务死锁相比,只是环更大了一些,环上的节点多了一些。其本质仍然是形成一个等待环。

    隔离级别对死锁的影响

    隔离级别同样会对锁定有很大的影响,例如,

    情形一、

    执行顺序

    T1 T2
    1 排他锁A  
    2   排他锁B
    3 共享锁B  
    4   共享锁A

    当隔离级别为0时,不会出现死锁。当隔离界别为1,2,3时,则会发生死锁。

    情形二、

    执行顺序

    T1 T2
    1 共享锁A  
    2   共享锁B
    3 排他锁B  
    4   排他锁A

    当隔离级别为0,1时,不会出现死锁。当隔离界别为2,3时,会发生死锁。

    情形三、

    该情况是最近在系统中发现的一个死锁问题。程序从文件导入数据到数据库中,每次导入一条记录时,首先尝试以update的方式导入一条记录,当找到记录为空时,则将该条记录更改为以insert的方式导入到数据库中。

    同时,导入过程是由多个进程共同完成的,每个进程导入一个文件,多个进程同时工作,然而当程序运行时,多个进程同时导入出现死锁。

    通过监控sybase日志,发现死锁都是发生在insert时,出现next-key lock。sybase日志保存在安装目录下,例如安装目录为/sybase/ASE-12_5,日志文件为/sybase/ASE-12_5/install/db_name.log。

    通过检查数据库的隔离级别,为1,没有发现异常,百思不得其解。

    后在程序中添加查询数据库隔离级别语句,以检查在程序运行中到底隔离级别是多少?

    经检查,隔离级别为3,也就是说在事务中,不能插入任何将出现在结果集中的行,下面分析一下出现死锁的原因。

    当两个进程同时插入记录到同一个间隙中时,每个事务可能由两个操作组成

    1.update

    2.insert,当update结果集为空时,则转为insert。

    其执行过程中,两个进程可能出现以下运行情况

    执行顺序

    T1 T2
    1 共享锁A  
    2   共享锁B
    3 排他锁B  
    4   排他锁A

    例如,目前数据库只有一条记录,主键为5,此时T1,T2分别插入主键为3,4的数据,由于两个事务都在运行之中,因此T1,T2都会尝试在5之前插入数据,首先其在update时,会产生共享锁,由于隔离级别为3,此时两个事务尝试插入时都会失败,要解决这种死锁,可以在程序中显式设置隔离级别为1。

    sybase锁升级

    sybase同时提供锁升级的功能,例如将行锁升级为页锁,将页锁升级为行锁。具体参数可以进行设置。

    例如当某一页中90%的行都被锁定,那么此时sybase可能将这些多个行锁升级为一个页锁,锁定整个页。这也是造成死锁一个重要的原因。

    有时,根据判断,不会产生死锁。

    执行顺序

    T1 T2
    1 行级排他锁A  
    2   行级排他锁B
    3 行级排他锁C  
    4   行级排他锁D

    在上述情况中,如果没有锁升级机制,是无论如何也不会产生死锁的。但是当有了锁升级机制之后,可能T1在将行级锁A升级为页锁Pa,T2将行锁B升级为页锁Pb,而T1需要访问的行C在页Pb中,T2需要访问的D在也Pa中,这时就会构成一个锁定环,构成死锁。

    总结

    在软件系统实现中,经常会采用数据库。使用数据库时死锁问题是大家通常都会遇到的,遇到死锁首先需要分析原因,定位问题,这也是最关键的一步。

    出现死锁的原因很多,但本质一定是多个进程出现了相互等待,而每个进程又都持有锁,从而形成了一个依赖关系环,因此问题最关键的就是找到这个依赖关系,以及是哪几个事务,哪几个锁导致了死锁,只要确定了这几点,死锁问题将迎刃而解。

  • 相关阅读:
    Hadoop 实现 TFIDF 计算
    关于Elasticsearch 使用 MatchPhrase搜索的一些坑
    SpringBoot jar包中资源加载问题
    gradle 将依赖打入Jar包的方法
    ES 在聚合结果中进行过滤
    Java c# 跨语言Json反序列化首字母大小写问题
    hadoop is running beyond virtual memory limits问题解决
    hadoop环境运行程序出现 Retrying connect to server 问题
    CSS的初步认识,基本选择器(CSS day1)
    day19 time模块
  • 原文地址:https://www.cnblogs.com/glorey/p/1777832.html
Copyright © 2011-2022 走看看