Re: select for update not locking properly.

Поиск
Список
Период
Сортировка
От Joseph Shraibman
Тема Re: select for update not locking properly.
Дата
Msg-id 396E06AB.7544C109@selectacast.net
обсуждение исходный текст
Ответ на select for update not locking properly.  (Joseph Shraibman <jks@selectacast.net>)
Ответы Re: select for update not locking properly.  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-general
OK here is the test program.

To run
(1) in psql:
once:
    create table locktest (x int, y int , list text, primary key (x,
y));
    insert into locktest values(3, 4, NULL);
between runs:
     update locktest set list = null where x = 3 and y = 4 ;

(2) customize the code below to include a valid username, password, and
url. For those of you not familiar with jdbc the url is
"jdbc:postgres:<dbname>"

(3) run from the command line like so:
java PostgresTest 4 10

Last time I ran it I got this:
About to sleep... done. List now is:
null<A:0><A:1><A:2><A:3><A:4><A:5><B:0><B:1><B:2><C:1><B:5><B:6><B:7><B:8><B:9><D:5><D:6><C:9><D:8><D:9>

There should have been one of <letter:0-9> but obviously some are
missing.

Here is the end of my postres log. See how the changes are overwriting
each other.

query: BEGIN ;
ProcessUtility: BEGIN ;
query: SELECT list FROM locktest WHERE x = 3 AND y = 4 FOR UPDATE;
query: END ;
ProcessUtility: END ;
query: BEGIN ;
ProcessUtility: BEGIN ;
query: SELECT list FROM locktest WHERE x = 3 AND y = 4 FOR UPDATE;
query: UPDATE locktest SET list =
'null<A:0><A:1><A:2><A:3><A:4><A:5><B:0><B:1><B:2><C:1><B:5><B:6><B:7><B:8><B:9><D:5><D:6><D:7>'
WHERE x = 3 AND y = 4 ;
query: UPDATE locktest SET list =
'null<A:0><A:1><A:2><A:3><A:4><A:5><B:0><B:1><B:2><C:1><B:5><B:6><B:7><B:8><B:9><D:5><D:6><C:9>'
=================================== !!! See! C:9 overwrites D:7  !!!
==================================
WHERE x = 3 AND y = 4 ;
query: END ;
ProcessUtility: END ;
query: END ;
ProcessUtility: END ;
NOTICE:  COMMIT: no transaction in progress
=================================== !!! Why this message all of a
sudden?  !!! ==================================
query: BEGIN ;
ProcessUtility: BEGIN ;
query: SELECT list FROM locktest WHERE x = 3 AND y = 4 FOR UPDATE;
query: UPDATE locktest SET list =
'null<A:0><A:1><A:2><A:3><A:4><A:5><B:0><B:1><B:2><C:1><B:5><B:6><B:7><B:8><B:9><D:5><D:6><C:9><D:8>'
WHERE x = 3 AND y = 4 ;
query: END ;
ProcessUtility: END ;
query: BEGIN ;
ProcessUtility: BEGIN ;
query: SELECT list FROM locktest WHERE x = 3 AND y = 4 FOR UPDATE;
query: UPDATE locktest SET list =
'null<A:0><A:1><A:2><A:3><A:4><A:5><B:0><B:1><B:2><C:1><B:5><B:6><B:7><B:8><B:9><D:5><D:6><C:9><D:8><D:9>'
WHERE x = 3 AND y = 4 ;
query: END ;
ProcessUtility: END ;
query: SELECT list FROM locktest WHERE x = 3 AND y = 4 ;

==============================================================================================================
/**
 * PostgresTest.java
 *
 *
 * Created: Thu Jul 13 13:20:25 2000
 *
 * @author Joseph Shraibman
 * @version 1.0
 */
import java.sql.*;

public class PostgresTest  {
    protected final static String alphabet =
"ABCDEFGHIJKLMNOPQRXTUVWXYZ"; //names for threads.

    //these values will have to be customized for each machine
    private static final String url = "jdbc:postgresql:playpen";
    private static final String usr = "";
    private static final String pwd = "";


    int loopvar = 10; //how many times each thread will do an append
    int numt = 10; //number of threads

    protected Connection db; // The connection to the database

    public PostgresTest() throws Exception{
        Class.forName("org.postgresql.Driver");

        db = DriverManager.getConnection(url, usr, pwd);
    }

    public void getGoing(){
    for (int i = 0; i < numt; i++){
        Adder a = new Adder();
        a.name = String.valueOf(alphabet.charAt(i));
        (new Thread(a)).start();
    }
    }

    public String getList() throws Exception{
    String ans = null;
    Statement st =  db.createStatement();
    ResultSet rs = st.executeQuery("SELECT list FROM locktest WHERE x = 3
AND y = 4 ;");
    if (! rs.next()){
        System.err.println("rs.next() returned false!!");
    } else
        ans = rs.getString(1);
    st.close();
    return ans;
    }

    private class Adder implements Runnable {
    String name;
    public void run(){
        for (int i = 0; i < loopvar; i++)
        add(i);
    }
    public void add(int i){
        try{
        Statement st =  db.createStatement();
        st.executeUpdate("BEGIN ;") ;
        ResultSet rs = st.executeQuery("SELECT list FROM locktest WHERE x = 3
AND y = 4 FOR UPDATE;");
        if (! rs.next()){
            System.err.println("rs.next() returned false!!");
        } else{
            String list = rs.getString(1);

            //now do some meaningless work to waste time
            int x = 0;
            for (int j = 0 ; j < 1000000; j++)
            x += j;

            list += "<"+name+":"+i+">";
            int num =  st.executeUpdate("UPDATE locktest SET list = '"+list+"'
WHERE x = 3 AND y = 4 ;");
            if (num != 1)
            System.err.println("WARNING!! num is "+num);

        }
        st.executeUpdate("END ;") ;
        st.close();

        }catch(SQLException e){
        e.printStackTrace();
        }
    }
    }
    //usage: java PostgresTest <treads> <loops>
    public static void main(String[] args) throws Exception{
    PostgresTest pt = new  PostgresTest();

    if (args.length >= 1)
        pt.numt = Integer.parseInt(args[0]);
    if (args.length >= 2)
        pt.loopvar = Integer.parseInt(args[1]);

    pt.getGoing();

    System.out.print("About to sleep...");
    System.out.flush();

    Thread.sleep(pt.loopvar * pt.numt * 250); //should be more than enough
time;

    System.out.println(" done. List now is:\n"+pt.getList());

    pt.db.close();

    }


} // PostgresTest

В списке pgsql-general по дате отправления:

Предыдущее
От: ernie cline
Дата:
Сообщение: performance question
Следующее
От: Tom Lane
Дата:
Сообщение: Re: postmaster crashing the server in 7.0.2