johanreynaert
asked on
locking problems when using multiple Inner Joins (ASA9 database)
Hello Experts,
When the database reads records (even in explicit read only mode) I get locks.
eg: SELECT article_id from article where article_id IN( SELECT distinct article.article_id from article Inner Join article_settings as settings0 ON (article.article_id = settings0.article_id) Inner Join article_settings as settings1 ON (settings0.article_id = settings1.article_id) where ( settings0.setting like 'mainsite' and settings0.setting_value like '8' ) AND ( settings1.setting like 'site' and settings1.setting_value like '001' ) AND status in (0) AND type in (309) ) ORDER BY article_name asc FOR READ ONLY
I notice that a lock stays for more than approximately 30 seconds. This is not possible. Records can not be locked that long since most of the saves are very short.
This used to work, but now it doesn't anymore.
Also one year ago I had locking problems with multiple Inner Joins.
SELECT Persoon.input_date,Persoon .modified_ date,Perso on.naam,Pe rsoon.vnaa m,Bedrijf. id as bedrijf_id,Bedrijf.naam as bedrijfsnaam,Persoon.adres ,Persoon.p ostcode,Pe rsoon.geme ente,Toega ng.id as toegang_id, Toegang.userid as email,Toegang.paswoord,Per soon.statu s,Starters DagSessie. aantal as sessieAantal,StartersDagAd viseur.aan tal as adviseurAantal,persoonStar ters.gesta rt,persoon Starters.s ectordetai l,persoonS tarters.le eftijdscat egorie,ISN ULL(Nieuws Brief.unsu bscribed,1 ) as unsubscribed,NieuwsBrief.i d as nieuwsbrief_id FROM Persoon Inner Join Bedrijf on (Persoon.bedrijf_id=Bedrij f.id) Inner Join Toegang on (Persoon.id = Toegang.persoon_id) Left outer join StartersDagSessie on (Persoon.id=StartersDagSes sie.persoo n_id) Left outer join StartersDagAdviseur on (Persoon.id=StartersDagAdv iseur.pers oon_id) Left outer join persoonStarters on (Persoon.id=persoonStarter s.persoon_ id) Left outer join Nieuwsbrief on (Persoon.id=Nieuwsbrief.pe rsoon_id) WHERE Persoon.id =? and (Nieuwsbrief.doelgroep = 1 OR NieuwsBrief.doelgroep = NULL)
I solved it using multiple select statements and combining the result.
Important note. There is only a problem on the production server which is a Linux Red Hat Enterprise 3 AS. There are less locking problems on the developmentserver which is a Windows2003 (for the same workload).
Can some one please help me?
Database: Adaptiver Server Anywhere Network Server Version 9.02.3219
JDBC-connection --> JConnect5.5
<resource-ref>
<res-ref-name>jdbc/xxxx</r es-ref-nam e>
<res-type>javax.sql.DataSo urce</res- type>
<init-param driver-name="com.sybase.jd bc2.jdbc.S ybDriver"/ >
<init-param url="jdbc:sybase:Tds:local host:2638/ xxxx"/>
<init-param user="xxxx"/>
<init-param password="xxxx"/>
<init-param max-connections="50"/>
<init-param max-idle-time="30s"/>
</resource-ref>
Table structure
CREATE TABLE "DBA"."article"
(
"article_id" integer NOT NULL DEFAULT autoincrement ,
"article_name" varchar(255) NULL ,
"status" integer NOT NULL DEFAULT 1 ,
"input_date" datetime NOT NULL DEFAULT current timestamp ,
"modified_date" datetime NOT NULL DEFAULT timestamp ,
"input_by" integer NOT NULL DEFAULT 0 ,
"modified_by" integer NOT NULL DEFAULT 0 ,
"start_date" datetime NOT NULL DEFAULT current timestamp ,
"stop_date" datetime NULL ,
"type" integer NOT NULL DEFAULT 0 ,
"scope" integer NOT NULL DEFAULT 0 ,
PRIMARY KEY ("article_id"),
)
Number of rows: 175.000 (approximate)
CREATE TABLE "DBA"."article_settings"
(
"article_id" integer NOT NULL ,
"setting" varchar(250) NOT NULL ,
"setting_value" long varchar NOT NULL ,
PRIMARY KEY ("article_id", "setting"),
)
Number of rows: 1.500.000 (approximate)
Select example:
public Vector getResult(){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector result = new Vector();
boolean first = true;
try{
conn = ConnectionHandler.getConne ction(); // non-transactional connection
StringBuffer select = new StringBuffer("SELECT article_id .......");
..... //make the select string
stmt = conn.createStatement();
rs = stmt.executeQuery(select.t oString()) ;
while (rs.next()){
result.add(new Integer(rs.getInt(1))); //always article_id
}
return result;
} catch (SQLException e) {
throw new ConnectionException(e);
} finally {
ConnectionHandler.close(co nn);
}
}
Insert or Update example:
public boolean save() {
String select = null;
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = ConnectionHandler.getConne ction(true ); //get a transactional connection
if (articleId == 0) {
// generate new
select = "INSERT INTO Article ( article_name, status, start_date, stop_date,input_by, type, scope) Values (?,?,?,?,?,?,? )";
stmt = conn.prepareStatement(sele ct);
stmt.clearParameters();
stmt.setString(1, articleName);
.....
stmt.setInt(7, scope);
int result = stmt.executeUpdate();
Statement autoinc = conn.createStatement();
rs = autoinc.executeQuery("sele ct @@identity");
if (rs.next()) articleId = rs.getInt(1);
} else {
select = "UPDATE article set article_name=?, status=?, start_date=?, stop_date=?, modified_by=?, modified_date=?, type=?, scope=? WHERE article_id = ?";
stmt = conn.prepareStatement(sele ct);
stmt.clearParameters();
stmt.setString(1, articleName);
....
stmt.setInt(9, articleId);
int result = stmt.executeUpdate();
}
stmt = conn.prepareStatement("del ete from article_settings where article_id = ? and setting = ?");
Enumeration enum = deleted.elements(); // only deleted
while (enum.hasMoreElements()) {
String setting = (String) enum.nextElement();
stmt.clearParameters();
stmt.setInt(1, articleId);
stmt.setString(2, setting);
stmt.execute();
}
CallableStatement cstmt = conn.prepareCall("{call sp_set_article_setting(?,? ,?)}");
enum = settings.propertyNames(); // only changed
while (enum.hasMoreElements()) {
String setting = (String) enum.nextElement();
String value = settings.getProperty(setti ng);
cstmt.clearParameters();
cstmt.setInt(1, articleId);
cstmt.setString(2, setting);
cstmt.setString(3, value);
cstmt.execute();
}
conn.commit(); //commit the transaction
return true;
} catch (SQLException e) {
throw new ConnectionException(e); //an explicit conn.rollback() is not required here because we close the connection
} finally {
ConnectionHandler.close(co nn);
}
}
When the database reads records (even in explicit read only mode) I get locks.
eg: SELECT article_id from article where article_id IN( SELECT distinct article.article_id from article Inner Join article_settings as settings0 ON (article.article_id = settings0.article_id) Inner Join article_settings as settings1 ON (settings0.article_id = settings1.article_id) where ( settings0.setting like 'mainsite' and settings0.setting_value like '8' ) AND ( settings1.setting like 'site' and settings1.setting_value like '001' ) AND status in (0) AND type in (309) ) ORDER BY article_name asc FOR READ ONLY
I notice that a lock stays for more than approximately 30 seconds. This is not possible. Records can not be locked that long since most of the saves are very short.
This used to work, but now it doesn't anymore.
Also one year ago I had locking problems with multiple Inner Joins.
SELECT Persoon.input_date,Persoon
I solved it using multiple select statements and combining the result.
Important note. There is only a problem on the production server which is a Linux Red Hat Enterprise 3 AS. There are less locking problems on the developmentserver which is a Windows2003 (for the same workload).
Can some one please help me?
Database: Adaptiver Server Anywhere Network Server Version 9.02.3219
JDBC-connection --> JConnect5.5
<resource-ref>
<res-ref-name>jdbc/xxxx</r
<res-type>javax.sql.DataSo
<init-param driver-name="com.sybase.jd
<init-param url="jdbc:sybase:Tds:local
<init-param user="xxxx"/>
<init-param password="xxxx"/>
<init-param max-connections="50"/>
<init-param max-idle-time="30s"/>
</resource-ref>
Table structure
CREATE TABLE "DBA"."article"
(
"article_id" integer NOT NULL DEFAULT autoincrement ,
"article_name" varchar(255) NULL ,
"status" integer NOT NULL DEFAULT 1 ,
"input_date" datetime NOT NULL DEFAULT current timestamp ,
"modified_date" datetime NOT NULL DEFAULT timestamp ,
"input_by" integer NOT NULL DEFAULT 0 ,
"modified_by" integer NOT NULL DEFAULT 0 ,
"start_date" datetime NOT NULL DEFAULT current timestamp ,
"stop_date" datetime NULL ,
"type" integer NOT NULL DEFAULT 0 ,
"scope" integer NOT NULL DEFAULT 0 ,
PRIMARY KEY ("article_id"),
)
Number of rows: 175.000 (approximate)
CREATE TABLE "DBA"."article_settings"
(
"article_id" integer NOT NULL ,
"setting" varchar(250) NOT NULL ,
"setting_value" long varchar NOT NULL ,
PRIMARY KEY ("article_id", "setting"),
)
Number of rows: 1.500.000 (approximate)
Select example:
public Vector getResult(){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector result = new Vector();
boolean first = true;
try{
conn = ConnectionHandler.getConne
StringBuffer select = new StringBuffer("SELECT article_id .......");
..... //make the select string
stmt = conn.createStatement();
rs = stmt.executeQuery(select.t
while (rs.next()){
result.add(new Integer(rs.getInt(1))); //always article_id
}
return result;
} catch (SQLException e) {
throw new ConnectionException(e);
} finally {
ConnectionHandler.close(co
}
}
Insert or Update example:
public boolean save() {
String select = null;
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = ConnectionHandler.getConne
if (articleId == 0) {
// generate new
select = "INSERT INTO Article ( article_name, status, start_date, stop_date,input_by, type, scope) Values (?,?,?,?,?,?,? )";
stmt = conn.prepareStatement(sele
stmt.clearParameters();
stmt.setString(1, articleName);
.....
stmt.setInt(7, scope);
int result = stmt.executeUpdate();
Statement autoinc = conn.createStatement();
rs = autoinc.executeQuery("sele
if (rs.next()) articleId = rs.getInt(1);
} else {
select = "UPDATE article set article_name=?, status=?, start_date=?, stop_date=?, modified_by=?, modified_date=?, type=?, scope=? WHERE article_id = ?";
stmt = conn.prepareStatement(sele
stmt.clearParameters();
stmt.setString(1, articleName);
....
stmt.setInt(9, articleId);
int result = stmt.executeUpdate();
}
stmt = conn.prepareStatement("del
Enumeration enum = deleted.elements(); // only deleted
while (enum.hasMoreElements()) {
String setting = (String) enum.nextElement();
stmt.clearParameters();
stmt.setInt(1, articleId);
stmt.setString(2, setting);
stmt.execute();
}
CallableStatement cstmt = conn.prepareCall("{call sp_set_article_setting(?,?
enum = settings.propertyNames(); // only changed
while (enum.hasMoreElements()) {
String setting = (String) enum.nextElement();
String value = settings.getProperty(setti
cstmt.clearParameters();
cstmt.setInt(1, articleId);
cstmt.setString(2, setting);
cstmt.setString(3, value);
cstmt.execute();
}
conn.commit(); //commit the transaction
return true;
} catch (SQLException e) {
throw new ConnectionException(e); //an explicit conn.rollback() is not required here because we close the connection
} finally {
ConnectionHandler.close(co
}
}
Have your tried using WITH NOLOCK
ASKER
Is that the same as READPAST ?
Readpast skips the locked records, and so this is not a correct query.
In other words. What is WITH NOLOCK doing?
Readpast skips the locked records, and so this is not a correct query.
In other words. What is WITH NOLOCK doing?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
In my case this is not a problem. It is only to make a list of articles. When they go deeper and want to see the details, I'll use the 'normal' way.
I'll test it and keep you informed.
I'll test it and keep you informed.
ASKER
I changed the "getResult()" method.
eg: SELECT article_id from article with (NOLOCK) where article_id IN( SELECT distinct article.article_id from article with (NOLOCK) Inner Join article_settings as settings0 ON (article.article_id = settings0.article_id) where ( settings0.setting like 'regio' and settings0.setting_value like '1' ) AND status in (0) AND type in (8) AND article.start_date >= '2006-02-08' ) ORDER BY start_date FOR READ ONLY
THX nito8300 it works.
eg: SELECT article_id from article with (NOLOCK) where article_id IN( SELECT distinct article.article_id from article with (NOLOCK) Inner Join article_settings as settings0 ON (article.article_id = settings0.article_id) where ( settings0.setting like 'regio' and settings0.setting_value like '1' ) AND status in (0) AND type in (8) AND article.start_date >= '2006-02-08' ) ORDER BY start_date FOR READ ONLY
THX nito8300 it works.
Glad to help!