1、创建测试用例
以scott用户创建一个测试的表test_t1,并更新一行字段,但不提交
SQL> create table scott.test_t1 (a int);
Table created.
SQL> insert into scott.test_t1 values (1);
1 row created.
SQL> commit;
Commit complete.
SQL> update scott.test_t1 set a=2 where a=1;
1 row updated.
2、制造一个锁
此时切换另一个用户(SYS用户),也更新同行字段,造成锁
SQL> update scott.test_t1 set a=3 where a=1;
3、查找被锁对象
图1) 通过v$locked_object视图查询锁对象的进程sid
图2) 通过sid在v$session视图查询出sql_id、用户username、进程paddr等信息
图3) 通过sql_id在v$sqltext视图中可查询出造成锁的具体sql语句
图4) 通过paddr在v$process视图中查询出服务器的进程号spid
4、解决方案
1) 将产生死锁的语句提交
这里也就是以scott用户执行commit 就可以了,但多数情况下, 是不知道哪个语句产生的死锁的,所以这个不常用
2) kill掉死锁的会话
alter system kill session 'sid,serial#'; 这里具体如下(可参照上面图2):
SQL> alter system kill session '51,99';
System altered.
同样的以sys用户更新的语句会出现session被kill的信息
SQL> update scott.test_t1 set a=3 where a=1;
update scott.test_t1 set a=3 where a=1
*
ERROR at line 1:
ORA-00028: your session has been killed
3)杀掉服务器端相应的oracle进程
如果上述的kill session还不能杀掉的话,可以直接杀掉服务器的进程,图4中的spid来查询
[oracle@oracletest~]$ ps -ef|grep 3207
oracle 3207 3206 0 23:55 ? 00:00:00 oracleorcl(DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
oracle 3223 3155 0 23:58 pts/4 00:00:00 grep 3207
杀掉服务器的oracle进程
[oracle@oracletest~]$ kill -s 9 3207
再次查询已被杀掉
[oracle@oracletest~]$ ps -ef|grep 3207
oracle 3287 3155 0 00:09 pts/4 00:00:00 grep 3207
同样的以sys用户更新的语句会出现服务器进程被kill的信息,无法连接了
SQL> update scott.test_t1 set a=3 where a=1;
update scott.test_t1 set a=3 where a=1
*
ERROR at line 1:
ORA-03113:end-of-file on communication channel
Process ID: 3207
Session ID: 51Serial number: 99