Как создать тупик базы данных, используя jdbc и JUNIT - PullRequest
1 голос
/ 11 апреля 2010

Я пытаюсь создать тупик базы данных и использую JUnit. У меня есть два параллельных теста, которые оба обновляют одну и ту же строку в таблице снова и снова в цикле.

Моя идея состоит в том, что вы обновляете, скажем, строку A в таблице A, а затем строку B в таблице B снова и снова в одном тесте. Затем в то же время вы обновляете строку B таблицы B, а затем строки A таблицы A снова и снова. Насколько я понимаю, это должно в конечном итоге привести к тупику.

Вот код для первого теста.

public static void testEditCC()
{
    try{
        int rows = 0;
        int counter = 0;
        int large=10000000;
        Connection c=DataBase.getConnection();
        while(counter<large)
        {
            int pid = 87855;
            int cCode = 655;
            String newCountry="Egypt";              
            int bpl = 0;
            stmt = c.createStatement();

            rows = stmt.executeUpdate("UPDATE main " +              //create lock on main table
                                                  "SET BPL="+cCode+
                                                  "WHERE ID="+pid);
            rows = stmt.executeUpdate("UPDATE BPL SET DESCRIPTION='SomeWhere' WHERE ID=602"); //create lock on bpl table
            counter++;
        }

        assertTrue(rows == 1);
        //rows = stmt.executeUpdate("Insert into BPL (ID, DESCRIPTION) VALUES ("+cCode+", '"+newCountry+"')");

    }
    catch(SQLException ex)
    {
        ex.printStackTrace();
        //ex.getMessage();
    }
}

А вот код для второго теста.

public static void testEditCC()
{
    try{
        int rows = 0;
        int counter = 0;
        int large=10000000;
        Connection c=DataBase.getConnection();
        while(counter<large)
        {
            int pid = 87855;
            int cCode = 655;
            String newCountry="Jordan";         
            int bpl = 0;
            stmt = c.createStatement();
            //stmt.close();
            rows = stmt.executeUpdate("UPDATE BPL SET DESCRIPTION='SomeWhere' WHERE ID=602"); //create lock on bpl table
            rows = stmt.executeUpdate("UPDATE main " +          //create lock on main table
                                                  "SET BPL="+cCode+
                                                  "WHERE ID="+pid);
            counter++;
        }

        assertTrue(rows == 1);
        //rows = stmt.executeUpdate("Insert into BPL (ID, DESCRIPTION) VALUES ("+cCode+", '"+newCountry+"')");

    }
    catch(SQLException ex)
    {
        ex.printStackTrace();
    }
}

Я запускаю эти два отдельных теста JUnit одновременно и подключаюсь к базе данных Apache Derby, которую я запускаю в сетевом режиме в Eclipse. Может ли кто-нибудь помочь мне понять, почему не возникает тупик? Возможно, я неправильно использую JUnit.

1 Ответ

1 голос
/ 12 апреля 2010

Необходимо проверить уровень изоляции транзакции, так как он определяет, блокирует ли БД строки, к которым прикоснулась транзакция. Если уровень изоляции слишком низкий, блокировка не происходит, поэтому и тупика тоже нет.

Обновление: в соответствии с этой страницей , уровень изоляции передачи по умолчанию для Derby зафиксирован на чтение и должен быть в порядке. Между прочим, стоит прочитать эту страницу, поскольку она объясняет изоляцию tx и ее различные уровни, а также какие проблемы она решает.

Следующий вопрос: что такое DataBase в вашем коде? Кажется, это нестандартный способ получить соединение.

Обновление2: Я думаю, что понял. Цитата API doc :

Примечание. По умолчанию объект Connection находится в режиме автоматической фиксации, что означает, что он автоматически фиксирует изменения после выполнения каждого оператора. Если режим автоматической фиксации был отключен, метод commit должен быть вызван явно, чтобы зафиксировать изменения; в противном случае изменения базы данных не будут сохранены.

Другими словами, строки не блокируются, потому что ваши эффективные транзакции действуют только на время существования отдельных обновлений. Вы должны отключить автокоммит перед началом работы с вашим соединением:

Connection c=DataBase.getConnection();
c.setAutoCommit(false);
...