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 по дате отправления: