用通俗语言讲解死锁和阻塞的区别 -群讨论整理

0
已邀请:
1

冰咖啡 - 成功一定有方法,失败一定有原因! 2013-09-23 回答

问:死锁 和 阻塞 咋理解

张旻答: 死锁就是你需要表A和B的锁, 申请a。表锁成功, 申请B失败。因为有另一个回话申请了b。它在等待申请A成功。结果就死锁了 。 阻塞应该是挂起等待吧

问:举个例子,消化下看

张旻答:典型例子就是哲学家吃饭呀。刀和叉 ,我拿到了刀, 要叉, 你拿到了叉要刀 ,结果, 牛排腐烂了我们都不能迟到,因为我不放下刀你就拿不到刀, 你不放下叉, 我就拿不到叉 .这个就是死锁。 阻塞是等待 ,死锁是阻塞的极端情况 ,阻塞在数据库随时发生 ,死锁比较少,死锁一般发生在多表操作,而且是独占锁,而且是独占锁

小霸王答: 死锁就是两个抢动犯遇见了。都想抢对面手里的钱。可是都抢不到。 阻塞就是,一个抢劫犯抢了你一次钱。第二个又来了。 第二个得等第一个抢完了,才能抢你的

Fanr 答: 死锁是 形成了一个环 ,但是 堵塞没有形成环,a等待b,b等待a,就是死锁,a等待b,c等待a,那么就是 堵塞

假日答:死锁(deadlock)是一种特殊的阻塞情况——两个对话互相阻塞。每个对话在保留自己的资源的同时,试图访问其他对话锁定的资源。这将导致一种循环阻塞的情境,也被称为抱死(deadly embrace)。
阻塞(blocking)——是指一个连接需要访问一块数据时,必须等待另一个连接的锁解除。

张旻答:核心就是假日的循环阻塞。。死锁与正常的阻塞是两个经常被混淆的概念。
发生死锁的一些原因:
1、应用程序以不同的次序访问表。例如会话1先更新了客户然后更新了订单,而会话2先更新了订单然后更新了客户。这就增加了死锁的可能性。
2、应用程序使用了长时间的事务,在一个事务中更新很多行或很多表。这样增加了行的“表面积”,从而导致死锁冲突。
3、在一些情况下,SQL Server发出了一些行锁,之后它又决定将其升级为表锁。如果这些行在相同的数据页面中,并且两个会话希望同时在相同的页面升级锁粒度,就会产生死锁。


问:怎么 体现到 数据库里面呢 ?比如 begin tran
update tt set name ='ss' where ID=1 ,我开启了事务,没有提交,另一边查询 select * from tt,这 是 阻塞,死锁 怎么体现?

Fanr 答:死锁之后,数据库会自动解除死锁 ,环中的其中一节,当堵塞的时候,往往是 运行比较慢 照成,那么 就需要调整,

死锁:
begin tran1
update a
update b

begin tran2
update b
update a

堵塞一般是 症状 是很卡 ,sql 很久才能运行完,死锁 是 会报错,卡一般是不会的

张旻答:UPDATE不好, 用SELECT ... FROM ... WHERE ... FOR UPDATE ,这个锁定了一张表格的数据,另一个回话锁定表2,第一个会话再去申请表2的独占锁 ,第二个会话再去申请表1的独占锁,这就发生死锁了

问:嗯,产生 死锁了,怎么解决 死锁呢

Fanr 答:死锁 要看情况 ,一般是通过 索引调整解决。如果解决不了,。select 加 nolock,需要根据执行计划调整
0

梁勇 - 天道酬勤、上善若水。爱好商业智能 2013-09-23 回答

用具体案例 Demo 讲解下 死锁 和阻塞的区别如下:

数据库阻塞和死锁在程序开发过程经常出现,怎么样避免呢?下面通过Demo简单模拟下,数据库发生阻塞和死锁的现象:
一、数据库阻塞:
数据库阻塞的现象:第一个连接占有资源没有释放,而第二个连接需要获取这个资源。如果第一个连接没有提交或者回滚,
第二个连接会一直等待下去,直到第一个连接释放该资源为止。对于阻塞,数据库无法处理,所以对数据库操作要及时地提交或

者回滚。
Demo:
--创建表
create table tb(id int,createtime date);
--插入测试数据
insert into tb select 1,sysdate from dual;
insert into tb select 2,sysdate from dual;
insert into tb select 3,sysdate from dual;
commit;

第一个连接,不提交或者回滚:
SQL> update tb set id=2 where id=1;

1 row updated

第二个连接,一直在运行:
SQL> update tb set id=2 where id=1;

因为第一个连接占有tb表没有释放资源,而第二个连接一直在等待第一个连接释放该资源。

二、数据库死锁:
数据库死锁的现象:第一个连接占有资源没有释放,准备获取第二个连接所占用的资源,而第二个连接占有资源没有释放,

准备获取第一个连接所占用的资源。这种互相占有对方需要获取的资源的现象叫做死锁。对于死锁,数据库处理方法:牺牲一个

连接,保证另外一个连接成功执行。
Demo:
--创建测试表t1
create table t1(id int,createtime date);
insert into t1 select 1,sysdate from dual;
insert into t1 select 2,sysdate from dual;
insert into t1 select 3,sysdate from dual;
commit;

--创建测试表t2
create table t2(id int,createtime date);
insert into t2 select 1,sysdate from dual;
insert into t2 select 2,sysdate from dual;
insert into t2 select 3,sysdate from dual;
commit;

第一个连接,在command窗口中运行:
begin
--先修改t1
update t1 set id=2
where id=1;
--等待20s
dbms_lock.sleep(20);
--再修改t2
update t2 set id=2
where id=1;
end;
/
运行结果:
ORA-00060: 等待资源时检测到死锁
ORA-06512: 在 line 9

第二个连接:

begin
--先修改t2
update t2 set id=2
where id=1;
--等待20s
dbms_lock.sleep(20);
--再修改t1
update t1 set id=2
where id=1;
end;
/
运行结果:
PL/SQL procedure successfully completed

因为第一个连接占有表t1,想要获取表t2的资源,而第二个连接占有表t2,想要获取表t1的资源,这种互相占有对方想要获取的资

源,满足死锁现象。最后第一个连接报异常退出,而第二个连接执行成功
0

choc - 终于找到组织了,学习BI中 2013-09-23 回答

To Liangyong:
第一个连接,不提交或者回滚:
SQL> update tb set id=2 where id=1;

1 row updated

第二个连接,一直在运行:
SQL> update tb set id=2 where id=1;

因为第一个连接占有tb表没有释放资源,而第二个连接一直在等待第一个连接释放该资源。


这2个连接不是一样的SQL语句么?为什么说第一个连接没有释放资源呢,SQL执行完不就应该资源释放了吗?

要回复问题请先登录注册