解决Sybase数据库死锁
- 格式:doc
- 大小:41.50 KB
- 文档页数:6
数据库死锁是指两个或多个事务在同时访问数据库时,因为资源竞争而导致的线程或进程的永久停滞现象。
死锁是数据库管理系统中常见的问题之一,它可能导致数据库系统性能下降或数据丢失。
常见的数据库死锁处理方法如下:
●预防性死锁:避免死锁发生的最佳方法是通过设计数据库系统来预防死锁。
●检测死锁:当死锁发生时,数据库管理系统应该能够检测到死锁并采取适当
的措施来解决问题。
●解除死锁:当死锁发生时,数据库管理系统应该能够找到死锁并采取适当的
措施来解决问题。
●中止事务:如果无法解除死锁,可以考虑中止其中一个或多个事务来解除死
锁。
●使用超时机制:在事务等待超过一定时间后自动中止事务,避免死锁的长时
间占用系统资源。
●使用锁粒度:缩小锁的粒度可以减小互相等待的可能性,减小死锁的发生。
数据库中解决死锁的常用方法在数据库管理系统中,死锁是一种常见但麻烦的问题。
当多个事务同时请求数据库中的资源,并且这些资源被彼此占用,但是又无法相互释放时,就会发生死锁。
死锁的出现可能导致系统性能下降,甚至是数据库崩溃。
因此,解决死锁问题是数据库管理人员需要重视和解决的重要任务。
那么,在数据库中,有哪些常用的方法来解决死锁问题呢?下面将为大家介绍几种常见且有效的死锁解决方法。
第一种方法是通过设置超时时间来解决死锁。
当一个事务请求某个资源时,如果在规定的超时时间内无法获取到该资源,系统就会自动中断这个事务,并回滚所有已经执行的操作。
这种方法虽然简单,但是可能会引起一些业务问题,因为这样做会导致一些事务被中断,可能需要重新执行。
第二种方法是通过死锁检测来解决死锁。
这种方法通常通过算法来检测死锁,并且在检测到死锁时采取一些措施来解决它。
常见的死锁检测算法有银行家算法和图论算法。
这些算法可以在死锁发生时,找到导致死锁的事务,并且选择一个事务进行回滚,从而解除死锁。
但是,这种方法需要消耗系统资源,可能会影响数据库的性能。
第三种方法是通过锁粒度的优化来解决死锁。
将原本被一次性锁住的资源拆分为多个资源,可以降低死锁的概率。
例如,如果一个事务需要修改多个记录,可以将这些记录分开,分别为每个记录加锁。
这样做可以减少死锁的发生,但是也增加了系统的复杂性。
第四种方法是通过加锁顺序的优化来解决死锁。
如果多个事务都会请求相同的资源集合,可以约定一个统一的加锁顺序。
例如,可以规定按照资源的唯一标识符进行加锁,这样不同的事务就会按照相同的顺序加锁,避免了死锁的发生。
这种方法适用于事务之间需要访问多个资源的情况。
第五种方法是通过动态资源分配来解决死锁。
在数据库管理系统中,可以通过动态分配资源的方式来避免死锁。
例如,可以实时监测事务的资源请求情况,并根据当前系统情况来决定是否分配资源。
如果系统资源紧张,可以选择不分配资源,以避免死锁的发生。
造成数据库表死锁的原因分析及解决⽅案在联机事务处理(OLTP)的数据库应⽤系统中,多⽤户、多任务的并发性是系统最重要的技术指标之⼀。
为了提⾼并发性,⽬前⼤部分RDBMS都采⽤加锁技术。
然⽽由于现实环境的复杂性,使⽤加锁技术⼜不可避免地产⽣了死锁问题。
因此如何合理有效地使⽤加锁技术,最⼩化死锁是开发联机事务处理系统的关键。
⼀、死锁产⽣的原因在联机事务处理系统中,造成死机主要有两⽅⾯原因。
⼀⽅⾯,由于多⽤户、多任务的并发性和事务的完整性要求,当多个事务处理对多个资源同时访问时,若双⽅已锁定⼀部分资源但也都需要对⽅已锁定的资源时,⽆法在有限的时间内完全获得所需的资源,就会处于⽆限的等待状态,从⽽造成其对资源需求的死锁。
另⼀⽅⾯,数据库本⾝加锁机制的实现⽅法不同,各数据库系统也会产⽣其特殊的死锁情况。
如在Sybase SQL Server 11中,最⼩锁为2K⼀页的加锁⽅法,⽽⾮⾏级锁。
如果某张表的记录数少且记录的长度较短(即记录密度⾼,如应⽤系统中的系统配置表或系统参数表就属于此类表),被访问的频率⾼,就容易在该页上产⽣死锁。
⼆、容易发⽣死锁的⼏种情况如下:1、不同的存储过程、触发器、动态SQL语句段按照不同的顺序同时访问多张表;2、在交换期间添加记录频繁的表,但在该表上使⽤了⾮群集索引(non-clustered);3、表中的记录少,且单条记录较短,被访问的频率较⾼;4、整张表被访问的频率⾼(如代码对照表的查询等)。
三、以上死锁情况的对应解决⽅案1、在系统实现时应规定所有存储过程、触发器、动态SQL语句段中,对多张表的操作总是使⽤同⼀顺序。
如:有两个存储过程proc1、proc2,都需要访问三张表zltab、z2tab和z3tab,如果proc1按照zltab、z2tab和z3tab的顺序进⾏访问,那么,proc2也应该按照以上顺序访问这三张表。
2、对在交换期间添加记录频繁的表,使⽤群集索引(clustered),以减少多个⽤户添加记录到该表的最后⼀页上,在表尾产⽣热点,造成死锁。
sqlite遇到databaseislocked问题的完美解决这两天在项⽬中⽤⼤强度⼤频率的⽅法测试时遇到sqlite报database is locked的问题,分析下来原因是sqlite对数据库做修改操作时会做(⽂件)锁使得其它进程同⼀时间使⽤时会报该错误(也就是SQLITE_BUSY),但如果仅是多进程或多线程查询sqlite是⽀持的。
(也有可能是做sql开启事务查询等发⽣异常,数据库没有关闭,然后再去打开就锁定了)解决⽅法有:1。
使⽤进程或线程间的同步机制以避免同时操作;如⽤信号量,互斥锁等(pthread_mutex_lock,pthread_mutex_unlock),如果你的项⽬⼯程较⼤要求较⾼的话建议⽤此⽅法⾃⾏封装函数处理同步2。
使⽤sqlite提供的两个busy handler函数,但对于⼀个连接来说,只能有⼀个busy handle,两个函数会相互影响,设置⼀个的同时会清除另⼀个,应根据需要来选择。
int sqlite3_busy_handler(sqlite3 *, int (*)(void *, int), void *)不注册此函数时默认回调函数为NULL,清除busy handle,申请不到锁直接返回;函数可以定义⼀个回调函数,当出现数据库忙时sqlite会调⽤该函数进⾏延时并返回⾮0会重试本次操作,回调函数的第⼆个参数会被传递为此次因BUSY忙事件⽽调⽤该函数的次数,因此你完全可以⾃⾏控制多少次后(也就是延时多少后)才真正返回BUSY;回调函数返回⾮0,数据库会重试当前操作,返回0则当前操作返回SQLITE_BUSY;int sqlite3_busy_timeout(sqlite3*, int ms);不注册此函数时默认超时等待为0,当ms<=0时,清除busy handle,申请不到锁直接返回;定义⼀个毫秒数,当未到达该毫秒数时,sqlite会sleep并重试当前操作,如果超过ms毫秒,仍然申请不到需要的锁,当前操作返回SQLITE_BUSY;很多⼈⽤这个函数没有成功,其实只要你仔细查看sqlite的源码就会发现,这个函数实际上注册了⼀个默认的sqlite3_busy_handler(sqliteDefaultBusyCallback),⽽这个回调函数在你的编译环境下可能使得第⼆个ms参数必需要⼤于1000且是他的整数倍才有意义,由于此默认callback函数延时较⼤,建议⾃⼰写回调函数然后⽤slite3_busy_handler注册,这样就可以⾃⼰⽤⾃⼰的延时函数或⽅法进⾏处理了.附:===================================================================static int sqliteDefaultBusyCallback(void *ptr, /* Database connection */int count /* Number of times table has been busy */){#if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP)static const u8 delays[] ={ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };static const u8 totals[] ={ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };# define NDELAY (sizeof(delays)/sizeof(delays[0]))sqlite3 *db = (sqlite3 *)ptr;int timeout = db->busyTimeout;int delay, prior;assert( count>=0 );if( count < NDELAY ){delay = delays[count];prior = totals[count];}else{delay = delays[NDELAY-1];prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));}if( prior + delay > timeout ){delay = timeout - prior;if( delay<=0 ) return 0;}sqlite3OsSleep(db->pVfs, delay*1000);return 1;#elsesqlite3 *db = (sqlite3 *)ptr;int timeout = ((sqlite3 *)ptr)->busyTimeout;if( (count+1)*1000 > timeout ){return 0;//1000>timeout,so timeout must bigger than 1000}sqlite3OsSleep(db->pVfs, 1000000);//1000msreturn 1;#endif}int sqlite3_busy_timeout(sqlite3 *db, int ms){if( ms>0 ){db->busyTimeout = ms;sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);}else{13-11-27 sqlite遇到database is locked问题的完美解决/content/10/1214/12/87000_77984300.shtml 2/2 sqlite3_busy_handler(db, 0, 0);}return SQLITE_OK;}3、解决⽅法⼆加上⼀个循环判断。
数据库死锁的检测与解决办法死锁是在并发环境下经常出现的一种资源竞争问题。
当多个进程或线程需要访问相同资源,但又无法获得对方所持有的资源时,就会导致死锁的发生。
数据库系统作为高效管理和组织数据的关键组件,也不能免于死锁问题的困扰。
本文将介绍数据库死锁的检测与解决办法,帮助管理员和开发人员更好地处理这一问题。
首先,我们需要了解死锁的产生原因。
在数据库系统中,数据访问和操作是通过事务来完成的。
事务是一组数据库操作,要么全部执行成功,要么全部回滚失败。
当多个事务同时进行并且涉及相同的数据时,就有可能出现死锁的情况。
数据库系统使用锁机制来管理并发访问,保证数据的一致性和完整性。
然而,死锁的发生可能是由于事务对锁的获取顺序不当或者资源竞争引起的。
因此,为了检测和解决死锁,我们可以采取以下几种策略:1. 死锁检测:死锁检测是通过系统周期性地对数据库资源进行扫描,检查是否存在死锁的情况。
常用的死锁检测算法有图检测算法、等待图算法和超时算法等。
其中,图检测算法是最常用的一种方法,它将事务和资源看作节点,并通过边来表示事务对资源的依赖关系。
如果图中存在环路,则表示发生了死锁。
系统可以根据这些算法提供的信息来处理死锁情况。
2. 死锁预防:死锁预防是通过约束系统资源的使用方式和事务的执行顺序来防止死锁的发生。
常见的死锁预防策略有资源有序分配法、资源抢占法和事务等待法等。
资源有序分配法要求系统为每个资源指定一个固定的获取顺序,使得事务按照相同的顺序请求资源,从而避免了死锁的产生。
资源抢占法则是在一个事务等待资源的时候,如果发现死锁可能发生,系统会选择抢占它正在使用的资源,从而打破死锁的循环。
事务等待法要求事务在获取资源之前释放已经持有的资源,避免了事务之间相互等待的情况。
3. 死锁恢复:当检测到死锁发生时,系统需要采取相应的措施来解决死锁问题。
常用的死锁恢复策略有回滚、终止和剥夺等。
回滚策略要求将所有涉及到死锁的事务回滚到某个安全点,从而解锁被死锁事务占用的资源。
数据库死锁与阻塞的识别与解决数据库系统作为现代信息管理和存储的核心组成部分,在各种应用场景下广泛使用。
然而,数据库操作中经常会遇到死锁和阻塞的问题,这些问题可能会导致系统性能下降,严重时甚至造成数据库服务崩溃。
因此,了解如何准确识别和解决数据库死锁与阻塞问题对于确保数据库系统的稳定性和可靠性至关重要。
首先,我们来了解一下什么是数据库死锁与阻塞。
死锁指的是两个或多个数据库事务相互等待对方释放锁资源而无法继续执行的情况。
阻塞则是指一个事务因为等待其他事务实例释放资源而暂时无法继续执行的情况。
这些问题通常发生在多个事务并发访问数据库时,特别是在涉及到共享资源的情况下。
要正确识别数据库死锁与阻塞问题,常用的方法包括使用数据库系统提供的监控工具和日志分析。
大多数数据库系统都会提供性能监视器和查询分析工具,可以帮助管理员实时监控数据库运行状况。
通过监控数据库的锁机制和事务状态,管理员可以发现死锁和阻塞问题。
此外,还可以通过分析数据库系统的日志文件,查找异常现象和错误提示,以快速定位问题。
一旦识别出数据库死锁与阻塞问题,接下来的关键是解决它们。
下面我将介绍几种常见的解决方法。
首先是死锁的解决。
死锁的产生往往是由于多个事务都在等待对方释放锁资源,造成了互相等待的局面。
为了避免死锁的发生,我们可以采取以下措施之一:1. 从应用设计层面出发,合理规划和设计事务的执行顺序,避免事务之间的交叉依赖。
2. 通过设置超时时间来强制释放锁资源,避免长时间的等待。
3. 使用数据库提供的锁机制和事务管理功能,在事务执行过程中设置恰当的锁级别和事务隔离级别,确保在并发访问时不会发生死锁。
其次是阻塞的解决。
当一个事务因为等待其他事务实例释放资源而无法继续执行时,我们可以采取以下策略解决阻塞问题:1. 优化数据库索引,减少事务访问数据库的时间,降低事务之间冲突的可能性。
2. 合理规划事务执行的时机和频率,避免瞬时高并发时过多的事务等待资源。
数据库中死锁的检测与解决方法死锁是数据库中常见的并发控制问题,指的是两个或多个事务在互相等待对方释放资源或锁的状态,导致所有事务无法继续执行的情况。
数据库中的死锁会导致资源浪费、系统性能下降甚至系统崩溃。
因此,死锁的检测与解决方法是数据库管理中非常重要的一环。
1. 死锁的检测方法死锁的检测旨在及时发现死锁并采取措施进行解决。
以下是几种常见的死锁检测方法。
1.1 死锁检测图算法死锁检测图算法是通过构建资源分配图以及等待图来检测死锁。
资源分配图以资源为节点,以事务与资源之间的分配关系为边;等待图以事务为节点,以事务之间等待请求关系为边。
如果存在一个循环等待的环,那么就可以判断系统中存在死锁。
可以采用深度优先搜索或广度优先搜索的算法遍历图,查找是否存在环。
1.2 超时监控方法超时监控方法是通过设定一个时间阈值,在事务等待资源的过程中进行计时。
如果某个事务等待资源的时间超过阈值,系统将判断该事务可能存在死锁,并采取相应的措施解锁资源。
1.3 等待图算法等待图算法是通过分析等待图来检测死锁。
等待图的构建是以事务为节点,以资源之间的竞争关系为边。
如果图中存在一个有向环,那么就可以判断系统中存在死锁。
2. 死锁的解决方法一旦死锁被检测到,必须采取措施加以解决。
以下是几种常见的死锁解决方法。
2.1 死锁剥夺死锁剥夺是通过终止一个或多个死锁事务来解决死锁。
首先需要选择一个死锁事务,然后终止该死锁事务并释放其所占用的资源。
这种方法会造成一些事务的回滚,需要谨慎操作。
2.2 死锁预防死锁预防是通过对资源的分配与释放进行约束,从而避免死锁的发生。
例如,可以采用事务串行化,即每次只允许一个事务执行;或者采用事务超时,即设定一个时间阈值,如果事务等待时间超过阈值,则自动结束事务。
2.3 死锁检测与恢复死锁检测与恢复是在发生死锁后,通过死锁检测算法找到死锁并进行恢复。
方法可以是终止一个或多个死锁事务,也可以是通过资源抢占来解除死锁。
解决Sybase数据库死锁
2005-10-19 17:29 ChinaUnix 我要评论(1) 字号:T | T
死锁的发生对系统的性能和吞吐量都有重要影响,经检测发现,管理信息系统的死锁主要是因为两个或多个线程(登录)抢占同一表数据资源。
AD:
死锁的发生对系统的性能和吞吐量都有重要影响,经检测发现,管理信息系统的死锁主要是因为两个或多个线程(登录)抢占同一表数据资源。
引起长时间抢占同一资源不是因为我们需要处理的事务太复杂,时间太长,而往往是因为我们在前端应用程序对数据库作操作时忘了提交.本文介绍一种处理解决这种死锁的方法。
Sybase封锁原理
数据共享与数据一致性是一对不可调和的矛盾,为了达到数据共享与数据一致,必须进行并发控制。
并发控制的任务就是为了避免共享冲突而引起的数据不一致。
Sybase SQL Server并发控制的方法是加锁机制(LOCKING)。
锁的类型可申请的锁已有的锁S U X
S∨∨×
U∨××
X×××
Sybase SQL Server有三种封锁类型:排它锁(exclusive lock,简称X锁);共享锁(share lock,简称S锁);更新锁(update lock,简称U锁)。
这三种锁的相容矩阵表如下:
×:表示不兼容。
∨:表示兼容。
Sybase SQL Server是自动决定加锁类型的。
一般来说,读(SELECT)
操作使用S锁,写(UPDATE,INSERT和delete)操作使用X锁。
U锁是建立在页级上的,它在一个更新操作开始时获得,当要修改这些页时,U锁会升级为X锁。
锁的力度
SQL Server有两级锁:页锁和表锁。
通常页锁比表锁的限制更少(或更小)。
页锁对本页的所有行进行锁定,而表锁则锁定整个表。
为了减小用户间的数据争用和改进并发性,SQL Server 试图尽可能地使用页锁。
当SQL Server决定一个语句将访问整个表或表的大多数页时,它用表锁来提供更有效的锁定。
锁定策略直接受查询方案约束,如果update或delete语句没有可用的索引,它就执行表扫描或请求一个表锁定。
如果update或delete语句使用了索引,它就通过请求页锁来开始,如果影响到大多数行,它就要请求表锁。
一旦一个语句积累的页锁超过锁提升阈值,SQL Server就设法给该对象分配一个表锁。
如果成功了,页锁就不再必要了,因此被释放。
表锁也在页层提供避免锁冲突的方法。
对于有些命令SQL Server自动使用表锁。
锁的状态
SQL SERVER加锁有三种状态:
1)意向锁(intend)—是一种表级锁,它表示在一个数据页上获得一个S或X锁的意向。
意向锁可以防止其他事务在该数据页的表上获得排它锁。
2)阻塞(blocking,简记blk)—它表明目前加锁进程的状态,带有blk后缀的锁说明该进程目前正阻塞另一个需要获得锁的进程,只有这一进程完成,其他进程才可以进行。
3)需求锁(demand)—表示此时该进程企图得到一个排它锁。
它可以防止在这一表或页上加过多的S锁,她表示某一事务是下一个去锁定该表和该页的事务。
需求锁是一个内部过程,因此用sp_lock是无法看见的。
死锁DEADLOCK
简单地说,有两个用户进程,每个进程都在一个单独的页或表上有一个锁,而且每个进程都想在对方进程的页或表上请求不相容锁时就会发生“死锁”。
在这种情况下,第一个进程在等待另一进程释放锁,但另一进程要等到第一个进程的对象释放时才会释放自己的锁。
SQL Server检查是否死锁,并终止事务中CPU时间积累最小的用户(即最后进入的用户)。
SQL Server回滚该用户的事务,并用消息号1205通知有此死锁行为的应用程序,然后允许其他用户进程继续进行。
在多用户情形下,每个用户的应用程序都应检查每个修改数据的事务是否有1205号消息,以此确定是否有可能死锁。
消息号1025表示该用户的事务因死锁而终止并被回滚。
应用程序必须重新开始这个事务处理。
查找死锁原因
既然管理信息系统长时间死锁的原因是由于我们提交或者是提交不当,那么我们就可以通过修改程序防止出现死锁。
定位死锁出错处主要经过以下三步:
1)在死锁出现时,用SP_WHO,SP_LOCK获得进程与锁的活动情况。
2)结合库表sysobjects和相应的操作员信息表查出被锁的库表与锁住别人的操作员。
3)根据锁定的库表与操作员的岗位,可以估计出程序大约出错处。
询问操作员在死锁时执行的具体操作即可完全定位出错处。
最后查找程序并修改之。
用sp_who获取关于被阻碍进程的信息
系统过程sp_who给出系统进程的报告。
如果用户的命令正被另一进程保持的锁阻碍,则:
◆status列显示“lock sleep”。
◆blk列显示保持该锁或这些锁的进程标识,即被谁锁定了。
◆loginame列显示登录操作员。
结合相应的操作员信息表,便可知道操作员是谁。
Fid spid status loginame origname blk dbname cmd
0 1 lock sleep lm lm 18 QJYD SELECT
0 2 sleeping NULL NULL 0 master NETWORK HANDLER
0 3 sleeping NULL NULL 0 master NETWORK HANDLER
……
用sp_lock浏览锁
要得到关于当前SQL Server上保持的锁的报告,可用系统过程sp_lock [spid1[,spid2]],spid1,spid2是表master.dbo.sysprocesses中的sql server进程id号,用sp_who可以得到锁定与被锁定的spid号:
◆locktype列显示加锁的类型和封锁的粒度,有些锁的后缀还带有blk表明锁的状态。
前缀表明锁的类型:Sh—共享锁,Ex—排它锁或更新锁,中间表明锁死在表上(”table”或’intent’)还是在页上(page). 后缀“blk”表明该进程正在障碍另一个需要请求锁的进程。
一旦正在障碍的进程一结束,其他进程就向前移动。
“demand”后缀表明当前共享锁一释放,该进程就申请互斥锁。
◆table_id列显示表的id号,结合sysobjects即可查出被封锁的表名。
执行该进程后屏幕显示
Fid Spid locktype table_id page row dbname Class context
0 1 Sh_intent 678293476 0 0 QJYD Non Cursor LockFam dur
0 1 Sh_page 678293476 31764 0 QJYD Non Cursor Lock
0 18 Ex_intent 9767092 0 0 QJYD Non Cursor LockFam dur
……
定位出错处
根据sp_who与sp_lock命令的结果,结合sysobjects和相应的操作员信息表。
得到操作员及其在死锁时所操作的库表,便大约可以知道应用程序的出错处,再询问操作员在死锁时执行什么操作以进一步认证。
最后查找程序并修正之。
select * from sysobjects where id=32000114
select * from sysprocesses where blocked > 0
Select A.F_ID,A.F_TSID,A.F_ISBN,A.F_SM,A.F_BKBZ,A.F_DJ,A.F_PJZK_JJ,B.F_BMBH From SMK A,BMKC B
Where B.F_BMBH =’010000’ AND A.F_ID = B.F_ID AND B.F_KFCS > 0 AND ISNULL(A.F_ISBN,'') <> '' And ISNULL(A.F_ID,'') <> '' AND ISNULL(A.F_SM,'') <> '' AND ISNULL(A.F_DJ,0) <> 0
AND A.F_ID Not In (Select f_id From pos_sm Where f_bmbh = ’010000’) ;
感谢下载!
欢迎您的下载,资料仅供参考。