云南北大青鸟java培训告诉你在Java程序中处理数据库超时与死锁

云南北大青鸟java培训告诉你在Java程序中处理数据库超时与死锁,第1张

每个使用关系型数据库的程序都可能遇到数据死锁或不可用的情况,而这些情况需要在代码中编程来解决;本文主要介绍与数据库事务死锁等情况相关的重试逻辑概念,此外,还会探讨如何避免死锁等问题,文章以DB2(版本9)与为例进行讲解。

什么是数据库锁定与死锁

锁定(Locking)发生在当一个事务获得对某一资源的“锁”时,这时,其他的事务就不能更改这个资源了,这种机制的存在是为了保证数据一致性;在设计与数据库交互的程序时,必须处理锁与资源不可用的情况。锁定是个比较复杂的概念,仔细说起来可能又需要一大篇,所以在本文中,只把锁定看作是一个临时事件,这意味着如果一个资源被锁定,它总会在以后某个时间被释放。而死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。

如何避免锁

我们可利用事务型数据库中的隔离级别机制来避免锁的创建,正确地使用隔离级别可使程序处理更多的并发事件(如允许多个用户访问数据),还能预防像丢失修改(LostUpdate)、读“脏”数据(DirtyRead)、不可重复读(NonrepeatableRead)及“虚”(Phantom)等问题。

隔离级别问题现象

丢失修改读“脏”数据不可重复读“虚”

可重复读取NoNoNoNo

读取稳定性NoNoNoYes

光标稳定性NoNoYesYes

未提交的读NoYesYesYes

表1:DB2的隔离级别与其对应的问题现象

在只读模式中,就可以防止锁定发生,而不用那些未提交只读隔离级别的含糊语句。丽江电脑培训>

数据库中有两种基本的锁类型:

排它锁(Exclusive Locks,即X锁)

共享锁(Share Locks,即S锁)。

当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。

每个使用关系型数据库的程序都可能遇到数据死锁或不可用的情况,而这些情况需要在代码中编程来解决;本文主要介绍与数据库事务死锁等情况相关的重试逻辑概念,此外,还会探讨如何避免死锁等问题,文章以DB2(版本9)与为例进行讲解。

什么是数据库锁定与死锁锁定(Locking)发生在当一个事务获得对某一资源的“锁”时,这时,其他的事务就不能更改这个资源了,这种机制的存在是为了保证数据一致性;在设计与数据库交互的程序时,必须处理锁与资源不可用的情况。

锁定是个比较复杂的概念,仔细说起来可能又需要一大篇,所以在本文中,只把锁定看作是一个临时事件,这意味着如果一个资源被锁定,它总会在以后某个时间被释放。

而死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。

如何避免锁我们可利用事务型数据库中的隔离级别机制来避免锁的创建,正确地使用隔离级别可使程序处理更多的并发事件(如允许多个用户访问数据),还能预防像丢失修改(LostUpdate)、读“脏”数据(DirtyRead)、不可重复读(NonrepeatableRead)及“虚”(Phantom)等问题。

隔离级别问题现象丢失修改读“脏”数据不可重复读“虚”可重复读取NoNoNoNo读取稳定性NoNoNoYes光标稳定性NoNoYesYes未提交的读NoYesYesYes表1:DB2的隔离级别与其对应的问题现象在只读模式中,就可以防止锁定发生,而不用那些未提交只读隔离级别的含糊语句。

青岛电脑培训>

JAVA中几种常见死锁及对策:解决死锁没有简单的方法,这是因为线程产生死锁都各有各的原因,而且往往具有很高的负载。大多数软件测试产生不了足够多的负载,所以不可能暴露所有的线程错误。在这里中,下面将讨论开发过程常见的4类典型的死锁和解决对策。(1)数据库死锁在数据库中,如果一个连接占用了另一个连接所需的数据库锁,则它可以阻塞另一个连接。如果两个或两个以上的连接相互阻塞,则它们都不能继续执行,这种情况称为数据库死锁。数据库死锁问题不易处理,通常数据行进行更新时,需要锁定该数据行,执行更新,然后在提交或回滚封闭事务时释放锁。由于数据库平台、配置的隔离级以及查询提示的不同,获取的锁可能是细粒度或粗粒度的,它会阻塞(或不阻塞)其他对同一数据行、表或数据库的查询。基于数据库模式,读写 *** 作会要求遍历或更新多个索引、验证约束、执行触发器等。每个要求都会引入锁。此外,其他应用程序还可能正在访问同一数据库模式中的某些对象,并获取不同应用程序所具有的锁。所有这些因素综合在一起,数据库死锁几乎不可能被消除了。值得庆幸的是,数据库死锁通常是可恢复的:当数据库发现死锁时,它会强制销毁一个连接(通常是使用最少的连接),并回滚其事务。这将释放所有与已经结束的事务相关联的锁,至少允许其他连接中有一个可以获取它们正在被阻塞的锁。由于数据库具有这种典型的死锁处理行为,所以当出现数据库死锁问题时,数据库常常只能重试整个事务。当数据库连接被销毁时,会抛出可被应用程序捕获的异常,并标识为数据库死锁。如果允许死锁异常传播到初始化该事务的代码层之外,则该代码层可以启动一个新事务并重做先前所有工作。当出现问题就重试,由于数据库可以自由地获取锁,所以几乎不可能保证两个或两个以上的线程不发生数据库死锁。此方法至少能保证在出现某些数据库死锁情况时,应用程序能正常运行。(2)资源池耗尽死锁客户端的增加导致资源池耗尽死锁是由于负载而造成的,即资源池太小,而每个线程需要的资源超过了池中的可用资源。假设连接池最多有10个连接,同时有10个对外部并发调用。这些线程中每一个都需要一个数据库连接用来清空池。现在,每个线程都执行嵌套的调用。则所有线程都不能继续,但又都不放弃自己的第一个数据库连接。这样,10个线程都将被死锁。研究此类死锁,会发现线程存储中有大量等待获取资源的线程,以及同等数量的空闲且未阻塞的活动数据库连接。当应用程序死锁时,如果可以在运行时检测连接池,就能确认连接池实际上已空。修复此类死锁的方法包括:增加连接池的大小或者重构代码,以便单个线程不需要同时使用很多数据库连接。或者可以设置内部调用使用不同的连接池,即使外部调用的连接池为空,内部调用也能使用自己的连接池继续。(3)单线程、多冲突数据库连接死锁对同一线程执行嵌套的调用有时出现死锁,此情形即使在非高负载系统中通常也会发生。当第一个(外部)连接已获取第二个(内部)连接所需要的数据库锁,则第二个连接将永久阻塞第一个连接,并等待第一个连接被提交或回滚,这就出现了死锁情形。因为数据库没有注意到两个连接之间的关系,所以数据库不会将此情形检测为死锁。这样即使不存在并发,此代码也将导致死锁。此情形有多种具体的变种,可以涉及多个线程和两个以上的数据库连接。(4)Java虚拟机锁与数据库锁冲突这种情形发生在数据库锁与Java虚拟机锁并存的时候。在这种情况下,一个线程占有一个数据库锁并尝试获取Java虚拟机锁。同时,另一个线程占有Java虚拟机锁并尝试获取数据库锁。此时,数据库发现一个连接阻塞了另一个连接,但由于无法阻止连接继续,所以不会检测到死锁。Java虚拟机发现同步的锁中有一个线程,并有另一个尝试进入的线程,所以即使Java虚拟机能检测到死锁并对它们进行处理,它还是不会检测到这种情况。 总而言之,JAVA应用程序中的死锁是一个大问题——它能导致整个应用程序慢慢终止,还很难被分离和修复,尤其是当开发人员不熟悉如何分析死锁环境的时候。五死锁的经验法则笔者在开发中总结以下死锁问题的经验。(1)对大多数的Java程序员来说最简单的防止死锁的方法是对竞争的资源引入序号,如果一个线程需要几个资源,那么它必须先得到小序号的资源,再申请大序号的资源。可以在Java代码中增加同步关键字的使用,这样可以减少死锁,但这样做也会影响性能。如果负载过重,数据库内部也有可能发生死锁。(2)了解数据库锁的发生行为。假定任何数据库访问都有可能陷入数据库死锁状况,但是都能正确进行重试。例如了解如何从应用服务器获取完整的线程转储以及从数据库获取数据库连接列表(包括互相阻塞的连接),知道每个数据库连接与哪个Java线程相关联。了解Java线程和数据库连接之间映射的最简单方法是向连接池访问模式添加日志记录功能。(3)当进行嵌套的调用时,了解哪些调用使用了与其它调用同样的数据库连接。即使嵌套调用运行在同一个全局事务中,它仍将使用不同的数据库连接,而不会导致嵌套死锁。(4)确保在峰值并发时有足够大的资源池。(5)避免执行数据库调用或在占有Java虚拟机锁时,执行其他与Java虚拟机无关的 *** 作。 最重要的是,多线程设计虽然是困难的,但在开始编程之前详细设计系统能够帮助你避免难以发现死锁的问题。死锁在语言层面上不能解决,就需要一个良好设计来避免死锁。

你可以采取以下方法将死锁减至最少:

•按同一顺序访问对象。

•避免事务中的用户交互。

•保持事务简短并处于一个批处理中。

•使用较低的隔离级别。

•使用基于行版本控制的隔离级别。

a将 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON,使得已提交读事务使用行版本控制。

b使用快照隔离。

•使用绑定连接。

避免死锁的方法,主要看代码了。

我们用PB开发,造成死锁的原因,通常是因为某个用户大数据量 *** 作某张表,而导制其它人无法使用,我常用的是在PB写完嵌入式SQL,类似SELECT TYPE INTO :ls_id from TABLE WHEERE ID = '1' ,很多人都这样,然后下面直接用ls_id去继续往下走,我都会加一句commit; 提交一下,实践证明,不加COMMIT,易死锁。

你说所说的注册用户和数据库用户,是指CREATE USER 吗,没有太大的区别,数据库用户,是一安装后,为了让你有足够权限 *** 作库和表,给你赋值了一些高的权限,而CREATE USER 的权限较低,也可以通过代码提高权限达到DBA的权限甚至SYS的权限,MSSQL亦是一样。

以上就是关于云南北大青鸟java培训告诉你在Java程序中处理数据库超时与死锁全部的内容,包括:云南北大青鸟java培训告诉你在Java程序中处理数据库超时与死锁、javamysql乐观锁为什么能防止死锁、北大青鸟设计培训:在Java程序中处理数据库超时与死锁等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9335717.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存