Reputation: 167
I am using Oracle Coherence with sybase tables as backstore of data. My java program inserts data into coherence cache and the data gets written to tables by means of stored procedure.
The code calls store procedure is like below for a batch of records
begin
beging tran
update tableA
set
col1=val1,
col2=val2
where
col3=val3
if(@@rowcount=0)
insert into tableA
(
col1,
col2,
col3
)
values
(
val1,
val2,
val3
)
if(@@error=0)
begin
rollback tran
end
commit tran
end
Nearly 50 threads may call the procedure by calling execureBatch where a batch contains nearly 125 records, however all records are mutually different and the table got datarows locking.
But Iget deadlock error by means of a BatchUpdateException
java.sql.BatchUpdateException: Your server command (family id #0, process id #464) encountered a deadlock situation. Please re-run your command.
What can be the reason of getting the deadlock here?
Upvotes: 0
Views: 1245
Reputation: 2378
Most likely, tableA is using the default allpages locking, and there's a deadlock occurring between the index and data pages. But the only way to know for sure is to enable the Sybase ASE config setting 'print deadlock information', and see what gets logged into the ASE errorlog file.
BTW, the test 'if(@@error=0)' to perform the rollback, looks funny. This will roll back if @@error = 0. But that actually means the preceding statement went well and there was no error, so typically you would commit instead of rolling back. Another issue is that that this is not working as you will expect. After executing the first 'if' statement '(@@rowcount=0)', the @@error value will have been reset to 0, since the 'if' statement always succeeds. This means you'll never be able to catch an error status from the update. The right way to do this is to copy, in a single statement, @@rowcount and @@error into local variables directly after a DML statement, and then perform any tests as needed.
Lastly, using 'if' without 'begin-end' compound statements is dangerous as it can quickly lead to code that doesn't do what you expect. As a general principle, it's best to always use begin-end after 'if', 'else' and 'while'.
Upvotes: 1