java中让数据库死锁的代码?

绝对零度 发布于 2010/09/12 21:08
阅读 1K+
收藏 2

请问要用java写个程序让数据库抛出死锁异常,该怎么写呢?

加载中
0
红薯
红薯

数据库死锁??

锁是容易,可是死锁就不容易了。

0
绝对零度
绝对零度

SQL Server死锁发生的时候,java中会抛出异常吗?我写了下面一个方法,调用updatePerson()一次,程序运行正常,会立即结束。如果连续调用updatePerson();2次,程序就一直卡住了,看样子好像是发生了死锁,但是java中没抛出异常。后台数据库用的是SQL Server. 请问这是怎么回事呢?我是想如果死锁时java中抛出异常的话,想看看这个异常的e.getErrorCode()的返回值是什么?

    private static void updatePerson() {
        Connection conn = DatabaseUtils.getConnection();
        Statement statement = null;
        try {
            conn.setAutoCommit(false);
            statement = conn.createStatement();
            statement.executeUpdate("UPDATE Person SET Name = 'test name'");
        } catch (SQLException e) {
            logException(e);
           
            try {
                statement.close();
                conn.close();
            } catch (SQLException e1) {
                logException(e1);
            }
        }
    }

0
坏孩子
坏孩子

引用来自#3楼“WangZhengbo”的帖子

SQL Server死锁发生的时候,java中会抛出异常吗?我写了下面一个方法,调用updatePerson()一次,程序运行正常,会立即结束。如果连续调用updatePerson();2次,程序就一直卡住了,看样子好像是发生了死锁,但是java中没抛出异常。后台数据库用的是SQL Server. 请问这是怎么回事呢?我是想如果死锁时java中抛出异常的话,想看看这个异常的e.getErrorCode()的返回值是什么?

    private static void updatePerson() {
        Connection conn = DatabaseUtils.getConnection();
        Statement statement = null;
        try {
            conn.setAutoCommit(false);
            statement = conn.createStatement();
            statement.executeUpdate("UPDATE Person SET Name = 'test name'");
        } catch (SQLException e) {
            logException(e);
           
            try {
                statement.close();
                conn.close();
            } catch (SQLException e1) {
                logException(e1);
            }
        }
    }

你这个是被锁住了,不叫死锁。

死锁很简单,连续获得两个Connection,第一个Connection更新数据行a,第二个Connection更新数据行b,第一个Connection更新数据行b,第二个Connection更新数据行a。注意当中不要commit。我说的是oracle

0
高东
高东

你close你的session就可以了。这个不叫死锁,其你调用的update并没有将结果提交到数据库,第二次update在等待你第一次更新的提交。这时候数据库并没有死锁。

0
绝对零度
绝对零度

引用来自#4楼“坏孩子”的帖子

引用来自#3楼“WangZhengbo”的帖子

SQL Server死锁发生的时候,java中会抛出异常吗?我写了下面一个方法,调用updatePerson()一次,程序运行正常,会立即结束。如果连续调用updatePerson();2次,程序就一直卡住了,看样子好像是发生了死锁,但是java中没抛出异常。后台数据库用的是SQL Server. 请问这是怎么回事呢?我是想如果死锁时java中抛出异常的话,想看看这个异常的e.getErrorCode()的返回值是什么?

    private static void updatePerson() {
        Connection conn = DatabaseUtils.getConnection();
        Statement statement = null;
        try {
            conn.setAutoCommit(false);
            statement = conn.createStatement();
            statement.executeUpdate("UPDATE Person SET Name = 'test name'");
        } catch (SQLException e) {
            logException(e);
           
            try {
                statement.close();
                conn.close();
            } catch (SQLException e1) {
                logException(e1);
            }
        }
    }

你这个是被锁住了,不叫死锁。

死锁很简单,连续获得两个Connection,第一个Connection更新数据行a,第二个Connection更新数据行b,第一个Connection更新数据行b,第二个Connection更新数据行a。注意当中不要commit。我说的是oracle

我照你说的这么试了,也是运行的时候卡住了,看上去和我开始那样处理的效果一样,也是没抛出异常。

0
绝对零度
绝对零度

难道数据库死锁的时候在java中真的不抛出异常吗?

0
芙蓉镇
芙蓉镇

4楼说的没错

第一个connection执行顺序是,1.更新数据a行,2.更新数据b行

而第二个connection执行顺序是,1.更新数据b行,2.更新数据a行

在第一个connection和第二个connection的每个程序的第1步执行以后,设置断点,然后放开第一个的断点,这时你会发现第一个会等待,然后再放开第二的断点,这时会抛出死锁的异常,这个一般是由数据库那边抛出来的

0
绝对零度
绝对零度

参考http://www.bitscn.com/pdb/otherdb/201008/190248.html中的做法,我写了下面2个存储过程,在一个Query Window中通过exec UpdatePerson1开始运行UpdatePerson1存储过程后,立即在另一个Query Window中通过exec UpdatePerson2运行UpdatePerson2存储过程,代码如下所示:

--drop table person

create table person
(
    i_id int identity,
    vc_name varchar(20)
)

insert into person values ('liuyang')
insert into person values ('xucheng')
select * from person


IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[UpdatePerson1]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[UpdatePerson1]
GO

CREATE PROCEDURE [dbo].[UpdatePerson1]
AS
BEGIN
    begin tran

    print 'UpdatePerson1-1: ' + CONVERT(varchar(100), getdate(), 25)

    update person with (rowlock)
    set vc_name = 'liuyang1'
    where i_id = 1

    print 'UpdatePerson1-2: ' + CONVERT(varchar(100), getdate(), 25)

    WAITFOR DELAY '000:00:020'

    print 'UpdatePerson1-3: ' + CONVERT(varchar(100), getdate(), 25)

    update person with (rowlock)
    set vc_name = 'xucheng1'
    where i_id = 2

    commit tran
END
GO

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[UpdatePerson2]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[UpdatePerson2]
GO

CREATE PROCEDURE [dbo].[UpdatePerson2]
AS
BEGIN
    begin tran

    print 'UpdatePerson2-1: ' + CONVERT(varchar(100), getdate(), 25)

    update person with (rowlock)
    set vc_name = 'xucheng2'
    where i_id = 2

    print 'UpdatePerson2-2: ' + CONVERT(varchar(100), getdate(), 25)

    WAITFOR DELAY '000:00:040'

    print 'UpdatePerson2-3: ' + CONVERT(varchar(100), getdate(), 25)

    update person with (rowlock)
    set vc_name = 'liuyang2'
    where i_id = 1

    commit tran
END
GO

按照http://www.bitscn.com/pdb/otherdb/201008/190248.html所说的,应该会发生死锁,但是我运行后并没有死锁,2个SP运行结束后表的结果是:

i_id  vc_name

1      liuyang2
2      xucheng2

这是为什么呢?

0
坏孩子
坏孩子

告诉你一个简单的方法,数据库里面有两条数据,先用一个辅助的session锁住第一行,然后写一个存储过程,先更新第一行,再更新第二行,运行这个存储过程,存储过程会卡住的,这个时候其实数据库中的两行分别被两个session锁住,然后用第三个session做跟第一个存储过程相反顺序的事情,最后释放辅助的session,这样就死锁了

 

注意,我说的是oracle

0
nile
nile

引用来自#8楼“芙蓉镇”的帖子

4楼说的没错

第一个connection执行顺序是,1.更新数据a行,2.更新数据b行

而第二个connection执行顺序是,1.更新数据b行,2.更新数据a行

在第一个connection和第二个connection的每个程序的第1步执行以后,设置断点,然后放开第一个的断点,这时你会发现第一个会等待,然后再放开第二的断点,这时会抛出死锁的异常,这个一般是由数据库那边抛出来的

返回顶部
顶部