I create multiple connections and make batch inserts into myTable simultaneously (multi threading)
insertString = "INSERT INTO ... + values + ") ";
insertTable.addBatch(insertString);
insertTable.executeBatch();
insertTable.clearBatch();
Sometime it works fine, however in other cases it hangs. I understand this is because I am inserting into the same table so it gets locked .
How can I write an INSERT statement such that it does not lock the table?
Are there any special transaction start . . commands that can prevent the table from being locked ? In addition, I am curious why it works fine sometimes ?
PS: the maximum number of connections that I used was 1024 (worked perfect sometimes)
Thanks
1024 session is totally insane. Your DBA should block your user for that.
You probably get blocked sessions when you load multiple rows with the same PI.
Single-row INSERTs are the slowest way to load data. A single session with a batch size of a few 1000 will outperform dozens of single-row sessions (but then only use one session).
Or switch to JDBC FastLoad if the target table is empty.
Check
http://developer.teradata.com/connectivity/articles/speed-up-your-jdbcodbc-applications
Is this a staging table?
Related
We are using Oracle 11G and JDK1.8 combination.
In our application we are using XAConnection, XAResource for DB transaction.
ie) distributed transactions.
On few occasions we need to kill our Java process to stop the application.
After killing, if we restart our application then we are getting the below exception while doing DB transaction.
java.sql.SQLException: ORA-02049: timeout: distributed transaction
waiting for lock
After this for few hours we are unable to use our application till the lock releases.
Can someone provide me some solution so that we can continue working instead of waiting for the lock to release.
I have tried the below option:
a) Fetched the SID and killed the session using alter command.After this also table lock is not released.
I am dealing with very small amount of data.
I followed one topic similar with that with tips about what to do with distributed connections.
Oracle connections remains open until you end your local session or until the number of database links for your session exceeds the value of OPEN_LINKS. To reduce the network overhead associated with keeping a database link open, then use this clause to close the link explicitly if you do not plan to use it again in your session.
I believe that, by closing your connections and sessions after DDL execution, this issue should not happens.
Other possibility is given on this question:
One possible way might be to increase the INIT.ORA parameter for distributed_lock_timeout to a larger value. This would then give you a longer time to observe the v$lock table as the locks would last for longer.
To achieve automation of this, you can either
- Run an SQL job every 5-10 seconds that logs the values of v$lock or the query that sandos has given above into a table and then analyze it to see which session was causing the lock.
- Run a STATSPACK or an AWR Report. The sessions that got locked should show up with high elapsed time and hence can be identified.
v$session has 3 more columns blocking_instance, blocking_session, blocking_session_statusthat can be added to the query above to give a picture of what is getting locked.
I hope I helped you, my friend.
I try load 50000 rows in table with 200 columns. I do executeBatch() every 1000 rows. And I get lock for this table. The same code works for MS SQL and Oracle but with postgresql I get this issue. When I decrease executeBatch number from 1000 to 75 all works correctly.
Is there any param in config file witch responding for batch buffer size?
Same issue http://www.postgresql.org/message-id/c44a1bc0-dcb1-4b57-8106-e50f9303b7d1#79g2000hsk.googlegroups.com
When I execute insert statements in batch for tables with a large number of columns occurs hanging, when call statement.executeBatch().
It is specific for postgresql jdbc driver.
To avoid this issue we should increase buffer size params(SO_SNDBUF, SO_RCVBUF) for socket.
For Windows we have to create such params in register:
[HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet \Services \Afd \Parameters]
DefaultReceiveWindow(type=DWORD) = 1640960(Decimal)
DefaultSendWindow(type=DWORD) = 1640960(Decimal)
This number(1640960) I get from internet as general recommendation!
And it works for me.
Generally you need to look for the following things.
Are you able to actually get a lock for the table?
Do you have other java code locks that you are waiting for?
In general the first place to check is the pg_stat_activity system view which will show you the query being executed and whether it is active, idle, waiting, etc. Then if it is waiting (i.e. waiting is t), then you will want to check the pg_locks view and see what else may have a lock on anything in the relation.
If waiting is not true, then you are better off checking your java code for client-side locks but since this works for MySQL and Oracle, I assume this is less of an issue.
There is one other thing to be aware of. I am not sure about MySQL and Oracle here but PostgreSQL limits you to one query at a time per connection. You might have some locking there?
I have a 1 trillion records file. Batch size is 1000 after which the batch is Executed.
Should I commit after each Batch ? Or Commit just once after all the 1 trillion records are executed in Batches of 1000 ?
{
// Loop for 1 Trillion Records
statement.AddBatch()
if (++count % 1000 == 0)
{
statement.executeBatch()
// SHOULD I COMMIT HERE AFTER EACH BATCH ???
}
} // End Loop
// SHOULD I COMMIT HERE ONCE ONLY ????
A commit marks the end of a successful transaction. So the commit should theoretically happen after all rows have been executed successfully.
If the execution statements are completely independent, than every one should have it's own commit (in theory).
But there may be limitations by the database system that require to split up the rows in several batches with their own commit. Since a database has to reserve some space to be able to do a rollback unless changes are committed, the "cost" of a huge transaction size may by very high.
So the answer is: It depends on your requirements, your database and environment.
Mostly it depends what you want to achieve, usually you need to compromise on something to achieve something. For example, I am deleting 3 million records that are no longer being accessed by my users using a stored procedure.
If I execute delete query all at once, a table lock gets escalated and my other users start getting timeout issues in our applications because the table has been locked by SQL Server (I know the question is not specific to SQL Server but could help debug the problem) to give the deletion process better performance, If you have such a case, you will never go for a bigger batch than 5000. (See Lock Escalation Threshold)
With my current plan, I am deleting 3000 rows per batch and only key lock is happening which is good, I am committing after half a million records are processed.
So, if you do not want simultaneous users hitting the table, you can delete the huge number of records if your database server has enough log space and processing speed but 1 Trillion records are a mess. You better proceed with a batch wise deletion or if 1 Trillion records are total records in the table and you want to delete all of those records, then I'd suggest go for a truncate table.
I have an (java) application that runs database purge queries on startup. Depending on the user, these queries could wind up removing hundreds of thousands of records. I've broken up the queries so that they're limited to 5000 records, with some breathing room between each query running.
The table uses InnoDB.
An example query:
DELETE FROM table WHERE epoch <= '1388094517' LIMIT 5000;
However, certain users are seeing various errors with lock problems:
java.sql.SQLException: The total number of locks exceeds the lock table size
java.sql.BatchUpdateException: Lock wait timeout exceeded; try restarting transaction
Advising mysql config changes are pretty much not possible because this is a distributed application. What steps can I take to make sure the delete queries are not causing locking errors?
The application begins logging data on startup and needs to be able to write to the database while the current delete query is running.
I am executing a series of sql statements using a JDBC connection on a DB2 server. On the last execute() of the simple sql: DELETE FROM MYTABLE, the thread gets hung for a long period of time even if the table somply contains a single record.
The application server I am using is WAS. I wonder if this is an issue specific to WAS and DB2 combination as the same code works on other environments.
Does anybody have any idea what is going on here?
Have you issue the command directly from the CLP? It could be other problem such as:
Transaction log problem: There are a lot of rows to delete, and this takes time. Also, the transaction logs have reached the limit, and the database does not do a rollback but waits for empty log freed by other transactions.
Lock problem (concurrency): some of the rows your are trying to delete have locks in other transactions, and the applications has to wait to release them (lock wait)
Also, try to do frequent commits.
Deleting rows in a database can be a terrible work: don't forget the database server will log all the data of the table in case of a ROLLBACK. Then I assume the problem is coming from the database especially if the table has many rows.
Have you tried to run manually all the SQL requests yourself in an interactive environment?