Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

CHAPTER 8 ■ TRANSACTIONS 273 Distributed Transactions One of the really nice features of Oracle is its ability to transparently handle distributed transactions. I can update data in many different databases in the scope of a single transaction. When I commit, either I commit the updates in all of the instances or I commit none of them (they will all be rolled back). I need no extra code to achieve this; I simply “commit.” A key to distributed transactions in Oracle is the database link. A database link is a database object that describes how to log into another instance from your instance. However, the purpose of this section is not to cover the syntax of the database link command (it is fully documented), but rather to expose you to its very existence. Once you have a database link set up, accessing remote objects is as easy as this: select * from T@another_database; This would select from table T in the database instance defined by the database link ANOTHER_DATABASE. Typically, you would “hide” the fact that T is a remote table by creating a view of it, or a synonym. For example, I can issue the following and then access T as if it were a local table: create synonym T for T@another_database; Now that I have this database link set up and can read some tables, I am also able to modify them (given that I have the appropriate privileges, of course). Performing a distributed transaction is now no different from a local transaction. All I would do is this: update local_table set x = 5; update remote_table@another_database set y = 10; commit; That’s it. Oracle will commit either in both databases or in neither. It uses a 2PC protocol to do this. 2PC is a distributed protocol that allows for a modification that affects many disparate databases to be committed atomically. It attempts to close the window for distributed failure as much as possible before committing. In a 2PC between many databases, one of the databases—typically the one the client is logged into initially—will be the coordinator for the distributed transaction. This one site will ask the other sites if they are ready to commit. In effect, this one site will go to the other sites and ask them to be prepared to commit. Each of the other sites reports back its “prepared state” as YES or NO. If any one of the sites votes NO, the entire transaction is rolled back. If all sites vote YES, the site coordinator broadcasts a message to make the commit permanent on each of the sites. This limits the window in which a serious error could occur. Prior to the “voting” on the 2PC, any distributed error would result in all of the sites rolling back. There would be no doubt as to the outcome of the transaction. After the order to commit or roll back, there again is no doubt as to the outcome of the distributed transaction. It is only during the very short window when the coordinator is collecting the votes that the outcome might be in doubt, after a failure. Assume, for example, we have three sites participating in the transaction with Site 1 being the coordinator. Site 1 has asked Site 2 to prepare to commit, and Site 2 has done so. Site 1 then asks Site 3 to prepare to commit, and it does so. At this point in time, Site 1 is the only site

274 CHAPTER 8 ■ TRANSACTIONS that knows the outcome of the transaction, and it is now responsible for broadcasting the outcome to the other sites. If an error occurs right now—the network fails, Site 1 loses power, whatever—Site 2 and Site 3 will be left “hanging.” They will have what is known as an in-doubt distributed transaction. The 2PC protocol attempts to close the window of error as much as possible, but it cannot close it entirely. Sites 2 and 3 must keep that transaction open, awaiting notification from Site 1 of the outcome. If you recall from the architecture discussion in Chapter 5, it is the function of the RECO process to resolve this issue. This is also where the COMMIT and ROLLBACK with the FORCE option come into play. If the cause of the problem was a network failure between Sites 1, 2, and 3, then the DBAs at Sites 2 and 3 could actually call the DBA at Site 1, ask him for the outcome, and apply the commit or rollback manually, as appropriate. There are some, but not many, limitations to what you can do in a distributed transaction, and they are reasonable (to me, they seem reasonable anyway). The big ones are as follows: • You cannot issue a COMMIT over a database link. That is, you cannot issue a COMMIT@remote_site. You may commit only from the site that initiated the transaction. • You cannot do DDL over a database link. This is a direct result of the preceding issue. DDL commits. You cannot commit from any other site other then the initiating site, hence you cannot do DDL over a database link. • You cannot issue a SAVEPOINT over a database link. In short, you cannot issue any transaction control statements over a database link. All transaction control is inherited from the session that opened the database link in the first place; you cannot have different transaction controls in place in the distributed instances in your transaction. The lack of transaction control over a database link is reasonable, since the initiating site is the only one that has a list of everyone involved in the transaction. If in our three-site configuration, Site 2 attempted to commit, it would have no way of knowing that Site 3 was involved. In Oracle, only Site 1 can issue the commit command. At that point, it is then permissible for Site 1 to delegate responsibility for distributed transaction control to another site. We can influence which site will be the actual commit site by setting the COMMIT_POINT_ STRENGTH (a parameter) of the site. A commit-point strength associates a relative level of importance to a server in a distributed transaction. The more important the server (the more available the data needs to be), the more probable that it will coordinate the distributed transaction. You might want to do this in the event that you need to perform a distributed transaction between your production machine and a test machine. Since the transaction coordinator is never in doubt as to the outcome of a transaction, it would be best if the production machine coordinated the distributed transaction. You do not care so much if your test machine has some open transactions and locked resources. You certainly do care if your production machine does. The inability to do DDL over a database link is actually not so bad at all. First, DDL is “rare.” You do it once at installation or during an upgrade. Production systems don’t do DDL (well, they shouldn’t do DDL). Second, there is a method to do DDL over a database link, in a fashion, using the job queue facility, DBMS_JOB or, in Oracle 10g, the scheduler package, DBMS_SCHEDULER. Instead of trying to do DDL over the link, you use the link to schedule a remote job to be executed as soon as you commit. In that fashion, the job runs on the remote machine, is not a distributed transaction, and can do the DDL. In fact, this is the method by which the Oracle Replication Services perform distributed DDL to do schema replication.

274<br />

CHAPTER 8 ■ TRANSACTIONS<br />

that knows the outcome of the transaction, <strong>and</strong> it is now responsible for broadcasting the outcome<br />

to the other sites. If an error occurs right now—the network fails, Site 1 loses power,<br />

whatever—Site 2 <strong>and</strong> Site 3 will be left “hanging.” They will have what is known as an in-doubt<br />

distributed transaction. The 2PC protocol attempts to close the window of error as much as<br />

possible, but it cannot close it entirely. Sites 2 <strong>and</strong> 3 must keep that transaction open, awaiting<br />

notification from Site 1 of the outcome. If you recall from the architecture discussion in<br />

Chapter 5, it is the function of the RECO process to resolve this issue. This is also where the<br />

COMMIT <strong>and</strong> ROLLBACK with the FORCE option come into play. If the cause of the problem was a<br />

network failure between Sites 1, 2, <strong>and</strong> 3, then the DBAs at Sites 2 <strong>and</strong> 3 could actually call<br />

the DBA at Site 1, ask him for the outcome, <strong>and</strong> apply the commit or rollback manually, as<br />

appropriate.<br />

There are some, but not many, limitations to what you can do in a distributed transaction,<br />

<strong>and</strong> they are reasonable (to me, they seem reasonable anyway). The big ones are as follows:<br />

• You cannot issue a COMMIT over a database link. That is, you cannot issue a<br />

COMMIT@remote_site. You may commit only from the site that initiated the transaction.<br />

• You cannot do DDL over a database link. This is a direct result of the preceding issue.<br />

DDL commits. You cannot commit from any other site other then the initiating site,<br />

hence you cannot do DDL over a database link.<br />

• You cannot issue a SAVEPOINT over a database link. In short, you cannot issue any transaction<br />

control statements over a database link. All transaction control is inherited from<br />

the session that opened the database link in the first place; you cannot have different<br />

transaction controls in place in the distributed instances in your transaction.<br />

The lack of transaction control over a database link is reasonable, since the initiating site<br />

is the only one that has a list of everyone involved in the transaction. If in our three-site configuration,<br />

Site 2 attempted to commit, it would have no way of knowing that Site 3 was<br />

involved. In <strong>Oracle</strong>, only Site 1 can issue the commit comm<strong>and</strong>. At that point, it is then permissible<br />

for Site 1 to delegate responsibility for distributed transaction control to another site.<br />

We can influence which site will be the actual commit site by setting the COMMIT_POINT_<br />

STRENGTH (a parameter) of the site. A commit-point strength associates a relative level of<br />

importance to a server in a distributed transaction. The more important the server (the more<br />

available the data needs to be), the more probable that it will coordinate the distributed<br />

transaction. You might want to do this in the event that you need to perform a distributed<br />

transaction between your production machine <strong>and</strong> a test machine. Since the transaction<br />

coordinator is never in doubt as to the outcome of a transaction, it would be best if the production<br />

machine coordinated the distributed transaction. You do not care so much if your test<br />

machine has some open transactions <strong>and</strong> locked resources. You certainly do care if your production<br />

machine does.<br />

The inability to do DDL over a database link is actually not so bad at all. First, DDL is<br />

“rare.” You do it once at installation or during an upgrade. Production systems don’t do DDL<br />

(well, they shouldn’t do DDL). Second, there is a method to do DDL over a database link, in<br />

a fashion, using the job queue facility, DBMS_JOB or, in <strong>Oracle</strong> 10g, the scheduler package,<br />

DBMS_SCHEDULER. Instead of trying to do DDL over the link, you use the link to schedule a<br />

remote job to be executed as soon as you commit. In that fashion, the job runs on the remote<br />

machine, is not a distributed transaction, <strong>and</strong> can do the DDL. In fact, this is the method by<br />

which the <strong>Oracle</strong> Replication Services perform distributed DDL to do schema replication.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!