uncommittable transaction is detected at the end of batch. the transaction is rolled back - sql

We are having problem with the server migration. We have one application that are having
so much transactions It working fine on the one database server. But when transfer same database to another server. We are facing the following error.
Server: Msg 3998, Level 16, State 1, Line 1
Uncommittable transaction is
detected at the end of the batch. The
transaction is rolled back.
Same database is copied to the another server with the all data. If we change connectionstring to old server then it is working fine.
Can anybody suggest on this?

This message means one of the other participants in the transaction voted to rollback. After that the transaction must fail.
So this message is a consequence, rather than a cause. Are you receiving any earlier / other error messages?
What happens when you run the query from Management Studio?

What you seem to have is a problem where the record is acceptable in one database but not theother. Suggest you look at the differnces between the two database structures (yes I know they are supposed to be the same, but clearly they are not). Suspect you will either find a collation difference, a data type differnce, or a data length differnce between the two. YOu might also have a table where the identity definition is missing and thus it can't insert becasue it is a required field and the value is missing. Tools like SQl Compare are easy to use to find differences.

Related

How to rollback data in a SQL Server database?

I had unfortunately deleted data from database by using following query in SQL Server
exec usp_delete_cascade "someTable", "id='somexyz'"
Can anyone please tell me how to get back my data?
Is this possible?
There are two kinds of transactions - implicit and explicit.
Implicit transaction is used every time you do DML statement (in your case delete). This transaction is not user handled. And it is not true your qry did not run under transaction.
Explicit transaction can be defined by user (with begin transaction). When you do not specify transaction, there are only implicit transactions, which are autocommited when statement success.
There is a few ways how to data recover, but never with 100% success and without work. You have to use some external program as SysTools SQL Recovery, ApexSQL Recover or Veeam. Level of recovery depends on your storage use and your server configuration.
Only one 100% way is prevension (and backups, change tracking etc).
You can try to recover with this tool of ApexSQL, but you would think in backup and measures to avoid this kind of problem.
http://www.apexsql.com/sql_tools_recover.aspx
Obviously is a third party tool and you would pay for using it.
It depends on your server config. But, by default, SQL Server does not starts transaction when executing query. So, if you do not started transaction, or transaction started, but commited, rollback is impossible.
Other ways to restore the data: if your database recovery model is set to full, and you have diff or full backup, youre lucky. If no, data is missing forewer.

Redshift: Serializable isolation violation on table

I have a very large Redshift database that contains billions of rows of HTTP request data.
I have a table called requests which has a few important fields:
ip_address
city
state
country
I have a Python process running once per day, which grabs all distinct rows which have not yet been geocoded (do not have any city / state / country information), and then attempts to geocode each IP address via Google's Geocoding API.
This process (pseudocode) looks like this:
for ip_address in ips_to_geocode:
country, state, city = geocode_ip_address(ip_address)
execute_transaction('''
UPDATE requests
SET ip_country = %s, ip_state = %s, ip_city = %s
WHERE ip_address = %s
''')
When running this code, I often receive errors like the following:
psycopg2.InternalError: 1023
DETAIL: Serializable isolation violation on table - 108263, transactions forming the cycle are: 647671, 647682 (pid:23880)
I'm assuming this is because I have other processes constantly logging HTTP requests into my table, so when I attempt to execute my UPDATE statement, it is unable to select all rows with the ip address I'd like to update.
My question is this: what can I do to update these records in a sane way that will stop failing regularly?
Your code is violating the serializable isolation level of Redshift. You need to make sure that your code is not trying to open multiple transactions on the same table before closing all open transactions.
You can achieve this by locking the table in each transaction so that no other transaction can access the table for updates until the open transaction gets closed. Not sure how your code is architected (synchronous or asynchronous), but this will increase the run time as each lock will force others to wait till the transaction gets over.
Refer: http://docs.aws.amazon.com/redshift/latest/dg/r_LOCK.html
Just got the same issue on my code, and this is how I fixed it:
First things first, it is good to know that this error code means you are trying to do concurrent operations in redshift. When you do a second query to a table before the first query you did moments ago was done, for example, is a case where you would get this kind of error (that was my case).
Good news is: there is a simple way to serialize redshift operations! You just need to use the LOCK command. Here is the Amazon documentation for the redshift LOCK command. It works basically making the next operation wait until the previous one is closed. Note that, using this command your script will naturally get a little bit slower.
In the end, the practical solution for me was: I inserted the LOCK command before the query messages (in the same string, separated by a ';'). Something like this:
LOCK table_name; SELECT * from ...
And you should be good to go! I hope it helps you.
Since you are doing a point update in your geo codes update process, while the other processes are writing to the table, you can intermittently get the Serializable isolation violation error depending on how and when the other process does its write to the same table.
Suggestions
One way is to use a table lock like Marcus Vinicius Melo has suggested in his answer.
Another approach is to catch the error and re run the transaction.
For any serializable transaction, it is said that the code initiating the transaction should be ready to retry the transaction in the face of this error. Since all transactions in Redshift are strictly serializable, all code initiating transactions in Redshift should be ready to retry them in the face of this error.
Explanations
The typical cause of this error is that two transactions started and proceeded in their operations in such a way that at least one of them cannot be completed as if they executed one after the other. So the db system chooses to abort one of them by throwing this error. This essentially gives control back to the transaction initiating code to take an appropriate course of action. Retry being one of them.
One way to prevent such a conflicting sequence of operations is to use a lock. But then it restricts many of the cases from executing concurrently which would not have resulted in a conflicting sequence of operations. The lock will ensure that the error will not occur but will also be concurrency restricting. The retry approach lets concurrency have its chance and handles the case when a conflict does occur.
Recommendation
That said, I would still recommend that you don't update Redshift in this manner, like point updates. The geo codes update process should write to a staging table, and once all records are processed, perform one single bulk update, followed by a vacuum if required.
Either you start a new session when you do second update on the same table or you have to 'commit' once you transaction is complete.
You can write set autocommit=on before you start updating.

SQL Replication error - row was not found at the Subscriber

We are trying to setup replication on a SQL Server 2005 database. We have followed some instructions for the past year, and all has been fine. Recently, it started failing (Development environment, so every week we rebuild the database.. and apply replciation).
We follow a set of steps, snap shot gets generated.. and applied to the replicated database. All fine. No errors.
We then add a new row to the source database, and bang! Error.
Command attempted:
if ##trancount > 0 rollback tran
(Transaction sequence number: 0x000004BE00000558000100000000, Command ID: 1)
Error messages:
The row was not found at the Subscriber when applying the replicated command. (Source: MSSQLServer, Error number: 20598)
We're inserting a row, but it's complaining that the row isn't on the subscriber. That's right, though. We want it to replicate the insert to the subscriber...
When we do a SELECT COUNT(*) on both the source and the destination, the row count is the same, until we do the INSERT, at which point, the source incriments, but the destination remains the same....
Any ideas where we can start looking?
Ugh... this error sucks. When you say that you inserted a row, I assume that you inserted it at the publisher. That's not going to work; replication delivers commands serially. That is, it won't replicate the fact that you inserted the missing row until it gets past your current error.
So, here's where we start. In the error message, we see an transaction sequence number. We can use that to determine the primary key of the missing row. At the distributor, there's a stored procedure called sp_browsereplcmds. You can plug in the transaction sequence number in for both the #xact_seqno_start and #xact_seqno_end parameters. You'll also see a command_id parameter in the stored procedure; this corresponds to the Command ID in your error message. Try executing the procedure with just those parameters specified. It should give you the command that it's trying to execute at the subscriber. From there, you can tell the primary key of the row that it's either trying to update or delete. You can then insert a row with that primary key at the subscriber and replication will move on.
Alternatively, you could drop this article from this subscriber, re-add it, and re-initialize that article. It's a bit more intense on the server, but is a lot less fiddly.
This is due to data corruption on publisher database,we faced the same replication errors,when we ran DBCC check DB with allow data loss.
Finally We tried doing RCA like
1.) Checking for storage errors by doing CHKDSK in offline mode
2.)Purging the table if it has a lot of data ..in our case we had 40 million rows.
The issue was gone after doing Purging data in our case

When is a row actually inserted into DB?

When is a row actually inserted into the database? Is it when "INSERT" statement is finished? or when "COMMIT" statement is finished after "INSERT" statement?
Later than you think. The principles here apply generally.
The whole point of the transaction log is to ensure ACID works in case of a power failure just as the INSERT finishes. The INSERT will be rolled forward or rolled back as part of the recovery phase (in most RDBMS)
So, it's more important that the transaction log entry is acknowledged as stored on the media. Then the INSERT can commit.
The data page containing the changed row will end up on disk eventually (checkpoint etc) but not necessarily at the point of successful commit.
However, the data page is in memory and available for use.
Note, an INSERT could cause a page split, indexes to be updated, triggers to fire etc so what I've said is simplified.
And it doesn't matter one way or the other when the data ends up on disk: as long as I can get the data and it's safe in case of, say, power failure
An oldie but still relevant for SQL Server: SQL Server 2000 I/O Basics
And what I've summarized is Write Ahead Logging
If you are running inside a transaction, when the transaction is committed. Otherwise, immediately.
Depends on the database/table implementation. It might just be when the transaction log is integrated - until which time the row is only inserted in the transaction log, and in memory.

Is a commit needed on a select query in DB2?

I have a vendor reporting product executing queries to pull report data, no inserts, no updates just reading data.
We have double our heap size 3 times and are now at 1024 4k pages, The app will run fine for a week then we will begin to see DB2 SQL error: SQLCODE: -954, SQLSTATE: 57011 indicating the transaction log is not able to accomodate the request.
Its not the size of the reports since they run fine after a recycle. I spoke with another DBA on this. He believe the problem was in a difference between ORACLE and DB2 in that the vendor code is crappy and not issuing commits on the selects. This is causing the references to not be cleaned up and is slowly accumulating as garbage in the heap.
I wanted to know if this is accurate as I thought only inserts and updates needed to have commits included. Is there any IBM documentation on this?
We are currently recycling on a weekly basis to alleviate the problem but I would like to have a good handle on the issue before going back to the vendor asking them to alter their code.
Any transaction needs to be properly terminated -- why did you think that only applies to inserts and updates? Consider running transactionally a "select a from b where c > 12" and then "select a from b where c <= 12"; within a transaction the DB has to guarantee that every a gets returned exactly once either from the first or second select, not both (assuming c is never null;-). Without transactionality, some a's might fall between the cracks or be returned twice if their corresponding c was changed by a different transaction, and that's just not ACID!-)
So when you do not need separate SELECT queries to be transactional wrt each other, tell the DB! And the way you tell, is by terminating the transaction after each select (normally commit is what you use for the purpose, though I guess you could, indifferently, choose to use rollback here;-).
Per Alex's response, the first SQL activity after any CONNECT, COMMIT, or ROLLBACK initiates a transaction.
To get a handle on your resource issue (transaction logs full), you should investigate your application that issues the reports - ensure that transactions are being closed out explicitly in code. I've seen cases where application developers rely upon the Garbage Collector to clean up database objects - while those objects are waiting for cleanup, the database resources (transactions) are held open.
It's always good practice to explicitly COMMIT or ROLLBACK your transactions as soon as you are done with the data - regardless of the programming methodology you use.
I get this error when committing transaction on a SELECT query, but despite the error it does return a Result-Set that include queried data.
tran.Commit();
error [hy011] [ibm] cli0126e the operation is invalid sqlstate=hy011
I changed my code to tran.Rollback(); and the error disapered.
Can anyone explain this behavior?