[
https://issues.apache.org/jira/browse/DERBY-1482?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Mamta A. Satoor updated DERBY-1482:
-----------------------------------
Attachment: TriggerTests_ver1_stat.txt
TriggerTests_ver1_diff.txt
The attached patch, TriggerTests_ver1_diff.txt, includes junit test which has
few test fixtures to test triggers on table with LOB columns. Each and every
one of those tests run into OOM probably because we are streaming the before
and after values of LOB columns even when they are not being referenced by the
trigger action. More code investigation is needed to identify different trigger
cases where we should not stream the LOBs.
I have added this junit test, TriggerTests.java, in
org.apache.derbyTesting.functionTests.tests.memory package. It has been added
to the _Suite in that package but has been commented for now with the following
comments.
//Disable following TriggerTests until DERBY-1482 has been fixed.
//Without that fix, the test will run into OOM errors for all
//the test fixtures. This test is written for triggers defined
//on table with LOB columns. No matter whether the LoB columns
//are touched in the trigger action, it appears that Derby is
//streaming the before and after values of LOB columns. Once
//the streaming problem has been resolved, we should be able
//to uncomment the following test.
//suite.addTest(TriggerTests.suite());
The org.apache.derbyTesting.functionTests.tests.memory._Suite gets run as part
of the lowmem suite. lowmem suite runs all the tests in it with 16M heap. I
have tweaked the page cache size for TriggerTests to 100 pages. The reason for
this is that the test deals with pretty big LOBs(320M each) and we will soon
run into OOM because of no memory left for page cache if we ran with the
default page cache of 1000 against the 16M heap.
For now, this suite runs only in embedded mode. When I ran with network server
mode, I got following error. But for now, I just want to focus on the OOM
failures. Once they are fixed, we can probably look at enabling this test for
network server mode.
java.sql.SQLNonTransientConnectionException: Network protocol exception: actual
code point, 4,692, does not match expected code point, 9,224. The connection
has been terminated.
One interesting exception I have noticed for few of the test fixtures (in
addition to OOM) looks something like following.
java.io.FileNotFoundException: system\wombat\log\log211.dat (The system cannot
find the file specified.)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:112)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests.copySingleFile(PrivilegedFileOpsForTests.java:245)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests.recursiveCopy(PrivilegedFileOpsForTests.java:222)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests.access$000(PrivilegedFileOpsForTests.java:47)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests$6.run(PrivilegedFileOpsForTests.java:184)
at
java.security.AccessController.doPrivileged(AccessController.java:251)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests.copy(PrivilegedFileOpsForTests.java:182)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests.recursiveCopy(PrivilegedFileOpsForTests.java:220)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests.access$000(PrivilegedFileOpsForTests.java:47)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests$6.run(PrivilegedFileOpsForTests.java:184)
at
java.security.AccessController.doPrivileged(AccessController.java:251)
at
org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests.copy(PrivilegedFileOpsForTests.java:182)
at
org.apache.derbyTesting.junit.BaseTestCase.runBare(BaseTestCase.java:133)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.extensions.TestDecorator.basicRun(TestDecorator.java:22)
at junit.extensions.TestSetup$1.protect(TestSetup.java:19)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.extensions.TestSetup.run(TestSetup.java:23)
at
org.apache.derbyTesting.junit.BaseTestSetup.run(BaseTestSetup.java:57)
at junit.extensions.TestDecorator.basicRun(TestDecorator.java:22)
at junit.extensions.TestSetup$1.protect(TestSetup.java:19)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.extensions.TestSetup.run(TestSetup.java:23)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at junit.textui.TestRunner.doRun(TestRunner.java:116)
at junit.textui.TestRunner.start(TestRunner.java:172)
at junit.textui.TestRunner.main(TestRunner.java:138)
I do not see this exception for first test fixtures. The reason behind these
additional exceptions may be that we are running into OOM and jvm can start
behaving unpredictably after running into OOMs. To verify that the problem is
not with my tests, I changed the LOB size to 60K from 320M and ran with default
heap and default page cache size and didn't run into above exceptions. Of
course there were no OOMs either because we have enough heap memory to be able
to stream the LOBs. In the patch attached, I have reverted my junit test back
to use 320M LOB data, page cache size of 100 and limited heap of 16M enforced
by the lowmem suite.
The typical OOM exception for the test looks as follows
7)
test1InsertBeforeTrigger(org.apache.derbyTesting.functionTests.tests.memory.TriggerTests)java.sql.SQLException:
Java exception: ': java.lang.OutOfMemoryError'.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:95)
at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:142)
at org.apache.derby.impl.jdbc.Util.javaException(Util.java:299)
at
org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(TransactionResourceImpl.java:403)
at
org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(TransactionResourceImpl.java:346)
at
org.apache.derby.impl.jdbc.EmbedConnection.handleException(EmbedConnection.java:2269)
at
org.apache.derby.impl.jdbc.ConnectionChild.handleException(ConnectionChild.java:81)
at
org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1321)
at
org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(EmbedPreparedStatement.java:1673)
at
org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeUpdate(EmbedPreparedStatement.java:303)
at
org.apache.derbyTesting.functionTests.tests.memory.TriggerTests.runInsertTriggerTest(TriggerTests.java:1479)
at
org.apache.derbyTesting.functionTests.tests.memory.TriggerTests.test1InsertBeforeTrigger(TriggerTests.java:541)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at
org.apache.derbyTesting.junit.BaseTestCase.runBare(BaseTestCase.java:109)
at junit.extensions.TestDecorator.basicRun(TestDecorator.java:22)
at junit.extensions.TestSetup$1.protect(TestSetup.java:19)
at junit.extensions.TestSetup.run(TestSetup.java:23)
at
org.apache.derbyTesting.junit.BaseTestSetup.run(BaseTestSetup.java:57)
at junit.extensions.TestDecorator.basicRun(TestDecorator.java:22)
at junit.extensions.TestSetup$1.protect(TestSetup.java:19)
at junit.extensions.TestSetup.run(TestSetup.java:23)
Caused by: java.sql.SQLException: Java exception: ':
java.lang.OutOfMemoryError'.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(SQLExceptionFactory40.java:119)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(SQLExceptionFactory40.java:70)
... 38 more
Caused by: java.lang.OutOfMemoryError
at
org.apache.derby.iapi.types.SQLBinary.readExternal(SQLBinary.java:421)
at org.apache.derby.iapi.types.SQLBinary.getValue(SQLBinary.java:244)
at org.apache.derby.iapi.types.SQLBinary.loadStream(SQLBinary.java:686)
at
org.apache.derby.impl.sql.execute.DMLWriteResultSet.objectifyStreams(DMLWriteResultSet.java:156)
at
org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:135)
at
org.apache.derby.impl.sql.execute.InsertResultSet.open(InsertResultSet.java:494)
at
org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(GenericPreparedStatement.java:436)
at
org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:317)
at
org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1232)
... 31 more
In order to run the junit test to repro the problem, first you will need to
uncomment the test from
org.apache.derbyTesting.functionTests.tests.memory._Suite and compile the code.
Next, you can run the lowmem suite one of the following 2 ways
1)You can run it as an ant target
ant junit-lowmem
2)java -Xmx16M junit.textui.TestRunner
org.apache.derbyTesting.functionTests.tests.memory._Suite
Either one of above runs should show you OOMs for each of the test fixtures in
TriggerTests.java
Following documents the different trigger and LOB combinations that are being
tested in TriggerTests.java. It also shows the test fixture name for that
trigger and LOB test combination
NO REFERENCE CLAUSE in trigger
definition
AFTER INSERT trigger test5InsertAfterTriggerNoReferencingClause
BEFORE INSERT trigger test5InsertBeforeTriggerNoReferencingClause
AFTER DELETE trigger test5DeleteAfterTriggerNoReferencingClause
BEFORE DELETE trigger test5DeleteBeforeTriggerNoReferencingClause
AFTER UPDATE trigger test5UpdateAfterTriggerNoReferencingClause
BEFORE UPDATE trigger test5UpdateBeforeTriggerNoReferencingClause
tirgger created on non-LOB column and no LOB is
referenced in trigger action(*)
AFTER INSERT trigger test1InsertAfterTrigger
BEFORE INSERT trigger test1InsertBeforeTrigger
AFTER DELETE trigger test1DeleteAfterTrigger
BEFORE DELETE trigger test1DeleteBeforeTrigger
AFTER UPDATE trigger test1UpdateAfterTrigger
BEFORE UPDATE trigger test1UpdateBeforeTrigger
tirgger created on non-LOB column and LOB is accessed in
trigger action(+)
AFTER INSERT trigger test2InsertAfterTriggerAccessLOB
BEFORE INSERT trigger test2InsertBeforeTriggerAccessLOB
AFTER DELETE trigger test2DeleteAfterTriggerAccessLOB
BEFORE DELETE trigger test2DeleteBeforeTriggerAccessLOB
AFTER UPDATE trigger test2UpdateAfterTriggerAccessLOB
BEFORE UPDATE trigger test2UpdateBeforeTriggerAccessLOB
tirgger created on non-LOB column and LOB is getting UPDATEed
in trigger action(+)
AFTER INSERT trigger test2InsertAfterTriggerUpdatedLOB
BEFORE INSERT trigger No test - BEFORE triggers do not allow
INSERT/UPDATE/DELETE in trigger action
AFTER DELETE trigger No test - the row has been deleted and hence no way
for trigger action to modify the LOB of the deleted row
BEFORE DELETE trigger No test - BEFORE triggers do not allow
INSERT/UPDATE/DELETE in trigger action
AFTER UPDATE trigger test2UpdateAfterTriggerUpdatedLOB
BEFORE UPDATE trigger No test - BEFORE triggers do not allow
INSERT/UPDATE/DELETE in trigger action
tirgger created on LOB column and no LOB is referenced
in trigger action (*)
AFTER INSERT trigger No test because INSERT trigger is defined on a row,
not a column. test1InsertAfterTrigger will suffice.
BEFORE INSERT trigger No test because INSERT trigger is defined on a row,
not a column. test1InsertBeforeTrigger will suffice.
AFTER DELETE trigger No test because DELETE trigger is defined on a row,
not a column. test1DeleteAfterTrigger will suffice.
BEFORE DELETE trigger No test because DELETE trigger is defined on a row,
not a column. test1DeleteBeforeTrigger will suffice.
AFTER UPDATE trigger test3UpdateAfterTrigger
BEFORE UPDATE trigger test3UpdateBeforeTrigger
tirgger created on LOB column and LOB is accessed in
trigger action(+)
AFTER INSERT trigger No test because INSERT trigger is defined on a row,
not a column. test2InsertAfterTriggerAccessLOB will suffice.
BEFORE INSERT trigger No test because INSERT trigger is defined on a row, not
a column. test2InsertBeforeTriggerAccessLOB will suffice.
AFTER DELETE trigger No test because DELETE trigger is defined on a row,
not a column. test2DeleteAfterTriggerAccessLOB will suffice.
BEFORE DELETE trigger No test because DELETE trigger is defined on a row, not
a column. test2DeleteBeforeTriggerAccessLOB will suffice.
AFTER UPDATE trigger test4UpdateAfterTriggerAccessLOB
BEFORE UPDATE trigger test4UpdateBeforeTrigger
tirgger created on LOB column and LOB is getting
UPDATEed in trigger action(+)
AFTER INSERT trigger No test because INSERT trigger is defined on a row, not
a column. test2InsertAfterTriggerUpdatedLOB will suffice.
BEFORE INSERT trigger No test - BEFORE triggers do not allow
INSERT/UPDATE/DELETE in trigger action
AFTER DELETE trigger No test - the row has been deleted and hence no way for
trigger action to modify the LOB of the deleted row
BEFORE DELETE trigger No test - BEFORE triggers do not allow
INSERT/UPDATE/DELETE in trigger action
AFTER UPDATE trigger test4UpdateAfterTriggerUpdatedLOB
BEFORE UPDATE trigger No test - BEFORE triggers do not allow
INSERT/UPDATE/DELETE in trigger action
(*) Has two versions of this trigger+LOB combination. The trigger action is
coded as either a stored procedure call or as a direct SQL statement.
(+)These test cases do not have stored procedure version of them. The reason is
that the trigger action references LOB columns and at this point, there is no
way to pass LOB parameters to a stored procedure
> Update triggers on tables with blob columns stream blobs into memory even
> when the blobs are not referenced/accessed.
> ---------------------------------------------------------------------------------------------------------------------
>
> Key: DERBY-1482
> URL: https://issues.apache.org/jira/browse/DERBY-1482
> Project: Derby
> Issue Type: Bug
> Components: SQL
> Affects Versions: 10.2.1.6
> Reporter: Daniel John Debrunner
> Priority: Minor
> Attachments: derby1482DeepCopyAfterTriggerOnLobColumn.java,
> derby1482Repro.java, derby1482ReproVersion2.java, TriggerTests_ver1_diff.txt,
> TriggerTests_ver1_stat.txt
>
>
> Suppose I have 1) a table "t1" with blob data in it, and 2) an UPDATE trigger
> "tr1" defined on that table, where the triggered-SQL-action for "tr1" does
> NOT reference any of the blob columns in the table. [ Note that this is
> different from DERBY-438 because DERBY-438 deals with triggers that _do_
> reference the blob column(s), whereas this issue deals with triggers that do
> _not_ reference the blob columns--but I think they're related, so I'm
> creating this as subtask to 438 ]. In such a case, if the trigger is fired,
> the blob data will be streamed into memory and thus consume JVM heap, even
> though it (the blob data) is never actually referenced/accessed by the
> trigger statement.
> For example, suppose we have the following DDL:
> create table t1 (id int, status smallint, bl blob(2G));
> create table t2 (id int, updated int default 0);
> create trigger tr1 after update of status on t1 referencing new as n_row
> for each row mode db2sql update t2 set updated = updated + 1 where t2.id =
> n_row.id;
> Then if t1 and t2 both have data and we make a call to:
> update t1 set status = 3;
> the trigger tr1 will fire, which will cause the blob column in t1 to be
> streamed into memory for each row affected by the trigger. The result is
> that, if the blob data is large, we end up using a lot of JVM memory when we
> really shouldn't have to (at least, in _theory_ we shouldn't have to...).
> Ideally, Derby could figure out whether or not the blob column is referenced,
> and avoid streaming the lob into memory whenever possible (hence this is
> probably more of an "enhancement" request than a bug)...
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.