首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

Oracle Core 学习札记二 - Transactions 和 Consistency 说明

2012-06-29 
Oracle Core 学习笔记二 -- Transactions 和 Consistency 说明 This chapterexamines the mechanisms Orac

Oracle Core 学习笔记二 -- Transactions 和 Consistency 说明

 

This chapterexamines the mechanisms Oracle uses to create the linked liststhrough undo records and, most importantly, how the code locates the end pointsof those lists.

            --这一章主要看一下Oracle 创建和linked undo records,并且确认undorecords list的结束点。在前面的blog里提到Oracle 采用这种UNDO 机制的3个原因:readconsistency 和 Rollback,最后一个原因就是今天这篇Blog的内容。

Oracle Core 学习笔记一-- Redo 和 Undo 机制详解

http://blog.csdn.net/tianlesoftware/article/details/7626421

 

We’ll be lookingat the transaction table that Oracle keeps in each undo segment header block toanchor one set of linked lists, and the interested transaction list (ITL) thatOracle keeps in every single data (and index) block as the anchor toanother set of linked lists. Then we’ll take a closer look into the undosegment header to examine the transaction table control section (hereinafterreferred to as the transaction control) that Oracle uses as the anchor pointfor the final linked list.

在每个undo sement headerblock里都有一个linked lists,这个就是我们说的transaction table。同样在每个data(index) block 也会有一个linkedlist,叫interested transaction list(ITL).

 

We’ll finishwith a short note on LOBs (large objects), as Oracle deals with undo, redo,read consistency, and transactions differently when dealing with LOBs—or, atleast, the LOB data that is stored “out of row.”

--注意Oracle 处理普通字段与LOBs字段的区别,如果是是LOBs,Oracle 的redo ,undo,readconsistency 都会按照LOBs字段来处理,因为LOB的数据是存储是单独存储的,即“out of row”。

Oracle LOB 详解

http://blog.csdn.net/tianlesoftware/article/details/6905406

 

 

一.Conflict Resolution  --冲突解决

Let’s imagine wehave to deal with a system where there are just two users, you and I, who areconstantly modifying and querying data in the small portion of a database.

--假设存在2个用户,不断的去修改和查询一部分数据。

 

If you areapplying a transaction to a database and I am simply querying the database, Imust not see any of your changes until the moment you tell me (by executing acommit; call) that I can see all of your changes. But even when you havecommitted your transaction, the moment at which I am allowed to see the changesyou’ve made depends on my isolation level (see the sidebar“Isolation Levels” in Chapter 2) and the nature of the work I am doing. So,from an internal point of view, I have to have an efficient method foridentifying (and ignoring) changes that are not yet committed as well aschanges that have been committed so recently that I shouldn’t yet be able tosee them. To make things a little more challenging, I need to remember that“recently” might not be all that recent if I’ve been executing a long-runningquery, so I may have to do a lot of work to get an accurate idea of when yourtransaction committed.

--假如用户A做了一个修改的事务,用户B正在查询,那么用户B看到的数据必须是用户A修改之前的,等用户A提交之后,才可以看到修改之后的数据。事实上,即使用户B提交了数据,用户A能否看见修改的数据还会受isolation level影响。

我们必须制定一种有效的方法来辨别事务最近是否提交. 实现这种方法有一定的难度,我们需要弄清楚这里的‘recently’可能不是所有的’recent’, 比如我们执行一个long-runing query,因此在事务commit时我们必须做很多的工作来获取准确的信息。

 

Viewing theactivity from the opposite perspective, when you commit your transaction(allowing your changes to become visible to other users), you need an efficientmechanism that allows you to let everyone see that you’ve committed thattransaction, but you don’t want to revisit and mark all the blocks that youhave changed, because otherwise this step could take just as much time as thetime it took to make the changes in the first place. Of course, if you decideto roll back your work rather than commit it, you will also need a mechanismthat links together all the undo records for the changes you have made, in theorder you made them, so that you can reverse out the changes in the oppositeorder. Since rolling back real changes is (or ought to be) a rare eventcompared to committing them, Oracle is engineered to make the commit as fast aspossible and allows the rollback mechanism to be much slower.

--从另一个观点来看,当我们提交事务,我们需要一个有效的机制来保证我们修改的数据所有人都可以看的到,但我们不想重新访问和标记我们修改的block,因为额外的操作会占用和我们之前修改数据同样多的时间。

当然我们可以可以rollback我们的事务,而不是提交,但是我们同样需要一个机制按照正确的顺序link 我们所有修改的undo record,这样才能回滚我们的数据。因为rollback 操作要比commit少很多,所以Oracle 设计时让commit尽可能的快,而允许rollback 机制慢一些。

 

One of the firstthings we need so that we can coordinate our activity is some sort of focalpoint for change. Since, in this scenario, you are the agent of change, yousupply the focal point or, rather, two focal points—the first is a single entryin a special part of the database to act as the primary reference point for thetransaction, and the second appears as an entry in every single table or indexblock that you change. We’ll start by looking at the reference point for thetransaction.

 

 

二.Transactions and Undo

 

When you createa database, you have to create an undo tablespace (and if you’re using RAC,this is extended to one undo tablespace for each instance that will access thedatabase). Unless you’re using old-style manual rollback management, Oraclewill automatically create several undo segments in that tablespace and willautomatically add, grow, shrink, or drop undo segments as the workload on thedatabase changes.

--在我们创建数据库的时候,我们必须创建undo tablespace(如果是RAC 环境,那么每个实例都会对应一个undo tablespace)。除非我们使用manul rollback 管理,这种情况下,Oracle 会在SYSTEM表空间下创建一些undo segments,然后用这些undo segments 来作为工作平台进行add,grow,shrink 或者drop undo segment操作。

                          

Transactionmanagement starts with, and revolves around, the undo segments. The segmentheader block, which (for undo segments) is the first block of the segment,contains a lot of the standard structures that you will see in the segmentheader block of other types of segment—the extent map and the extent controlheader, for example—but it also contains a number of very special structures(see Figure 3-1), in particular the transaction table (TRN TBL:, a short listidentifying recent transactions) and the transaction table control section (TRNCTL::, a collection of details describing the state and content ofthe transaction table).

--事务管理从undo segment开始或者围绕undo segment进行,undosegment header block是undo segment的第一个block,header  block 由一些保准的structures组成:extentmap,extent control header。在transaction table和transactiontable control section里也包含一些特殊的structures,如transaction table中的TRNTBL:,transaction table control section的TRNCTL::。

 

 Oracle Core 学习札记二 - Transactions 和 Consistency 说明

Figure 3-1. Schematic comparing key contentof different types of segment headers

 

 

The followingdump is an extract from a transaction table, restricted to just the first fewand last few entries and hiding some of the columns we don’t need to discuss.This extract includes one entry (index = 0x02) that represents anactive transaction.

--下面是从transaction table里抽取的dump文件,我们这里只看开头和结尾的部分entries,中间的的部分我们不讨论。 Entry(index = 0x02))代表的就是一个活动的事务。

 

TRN TBL: index statecflags  wrap#   uel       scn          dba         nub        cmt

--------------------------------------------- 

0x00    9   0x00  0x20130x001b 0x0000.016f1fc1 0x0180083e 0x00000001 1302762364  

0x01    9   0x00  0x20140x001a 0x0000.016f1f54 0x0180083e 0x00000001 1302762364

0x02   10   0x80  0x20130x0002 0x0000.016f20fc 0x0180083e0x00000001          0  

0x03    9   0x00  0x200c0x001c 0x0000.016f20d8 0x0180083e 0x00000001 1302762364

...  

0x20    9   0x00  0x200f0x001f 0x0000.016f1c75 0x0180083f 0x00000001 1302762364  

0x21    9   0x00  0x20130x0010 0x0000.016f1e0c 0x0180083f 0x00000001 1302762364

 

This dump isfrom an 8KB block size using automatic undo management on a system runningOracle Database 11g, and the restrictions on space imposed by the 8KB blockmean that the transaction table holds just 34 rows. (Earlier versions of Oracleheld 48 entries in automatic undo segments and 96 entries in manually managedrollback segments—which didn’t have an extent retention map—when using 8KBblocks).

--这个内容是从一个8KB的block 里dump出来的,环境是Oracle11g下的自动undo 管理,因为8KB大小的限制,每个transaction table只能保存34条记录,在Oracle11g之前的版本中,在使用automatic undo segments可以保存48条entries,手工管理rollbacksegment可以保存96条记录,使用manually managed rollback segment时,没有extentretention map。

 

Since there’sonly a limited number of entries in a transaction table and a limited number ofundo segments in an undo tablespace, you can only record details about arelatively small number of recent transactions, and you will have to keepreusing the transaction table entries. Reusing the entries is where the columnlabeled wrap# becomes relevant; each time you reuse anentry in the table, you increment the wrap# for that entry.

--因为每个事务表里只能保存有限的entry,并且undo 表空间里的undosegment也是有限的,我们只能记录最近小部分事务的详细信息, 因此我们必须重用transaction tableentry,重用entry与entry中的wrap#有关,每次使用事务表里的entry,该entry的wrap#值就会增加。

 

Note:

Occasionally Ihear the question, “Does the wrap# get reset every time the instance restarts?”The answer is no. As a general principle, any sort of counter that is stored onthe database is unlikely to be reset when the instance restarts. Remember,every slot in every undo segment has its own wrap#, so it would be a lot ofwork at startup to reset them all.

            --一次偶然的机会我听到一个问题:每次instance 重启时wrap# 会被重置吗?答案是不会,一般来说,任何计数都会存储在数据库中,因此不会在实例重启时被重置,记住,任何undo segment中的任何slot都有自己的wrap#,所以如果在实例重启时重置他们就需要做大量的工作。

 

2.1 Start and End of Transaction  --事务开始与结束

 

When a sessionstarts a transaction, it picks an undo segment, picks an entry from thetransaction table, increments the wrap#, changes the state to “active” (value10), and modifies a few other columns. Since this is a change to a databaseblock, it will generate a redo change vector (with an OP code of 5.2) that willultimately get into the redo log file; this declares to the world and writesinto the database the fact that the session has an active transaction.

--当一个事务开始时,它会申请一个undo segment,在从这个undo segment中的transactiontable中申请一个entry,增加entry的wrap#,并将其状态改成active(即值为10),然后修改其他的一些字段值。因为这些是改变数据库的block,所以也会生成redo change vector(这种情况的OP值是5.2),  这些redo vector最终也会写入redolog file。这些操作完成后在表明是一个active transaction。

 

Similarly, whenthe transaction completes (typically through a commit; call), the session setsthe state back to “free” (value 9) and updates a few other columns in theentry—in particular, by writing the current SCN into the scn column. Again,this constitutes a change to the database so it generates a redo change vector(with an OP code of 5.4) that will go into the redo log. This moment is alsorather special because (historically) this is the “moment” when your sessionprotects its committed changes by issuing a call to the log writer (lgwr) towrite the current content of the redo log buffer to disc and then waiting forthe log writer to confirm that it has finished writing. Once the log writer haswritten, you have a permanent record of the transaction—in the ACID jargon, thetransaction is now durable.

--同样,当一个事务完成时(即commit),session 会重新将transactiontable中的entry对应的wrap# 状态改为9,然后更新其他的一些字段值,注意一点,这里会把current SCN 写入entry的scn 字段。同样,这个些操作也会生成redo vector(此时对应的OP值为5.4),并写入redo log,这个时候非常特殊,因为session 会调用logwrite 进程把当前的redo log buffer中的数据写入disc,然后等待logwriter确认已经写完,这样就保护它所提交的数据不会丢失,所有事务的record都会写入disc。

 

Note:

You will oftenfind comments on the Internet and in the Oracle documentation about the logwriter “creating a commit record.” There is no such action. When you commit,you modify a database block, specifically the undo segment header block holdingthe transaction table slot that you’re using, and this block change firstrequires you to generate a redo change vector (historically as a stand-aloneredo record) and copy it into the redo log buffer. It is this change vectorthat (very informally) could be called “the commit record”; but it’s yoursession (not the log writer) that generates it and puts it into the redo logbuffer, it’s just a specific example of the standard logging mechanism. Theonly special thing about “the commit record” is that once it has been copiedinto the log buffer, the session calls the log writer to write the currentcontents of the log buffer to disk, and waits for that write to complete.

--在文档中经常可以看一句:log writer “creating a commit record”,实际上并没有这个操作,commit时,会修改block,特使是undo segment headerblock,其记录了我们使用的transaction table slot,在修改之前也是需要先生成redo change vector(一个独立的redo record),然后把redovector写入redo log buffer,这个操作可以称为: the commit record,但其是在session中生成并写入buffer。

关于the commit record,一旦redovector copy进入log buffer,session 就会调用log writer 将redolog buffer中的当前内容写入disc,并等待写入操作结束,session 操作才能完成。这个机制也保证了修改的数据不会丢失,如果在没有写完之前,db crash了,那么session 就是失败的,在下次启动时会回滚相关的操作。

 

A transaction isdefined by the entry it acquires in a transaction table and is given atransaction ID constructed from the undo segment number, the index number ofthe entry in the transaction table, and the latest wrap# of that entry—so whenyou see a transaction ID like 0x0009.002.00002013, you can translate this into:undo segment 9, entry 2, wrap# 0x2013 (8,211 decimal). If you want to checkwhich undo segment this is and the location of the header block, you can alwaysquery view dba_rollback_segs by segment_id.

--事务由transaction table中的entry来定义,会提供一个transaction ID,其由undo segment number,transactiontable中entry的index number和entry中最新的wrap#构成,所以我们可以看到transaction ID,如:0x0009.002.00002013,从这个ID,我们可以获得如下信息: undo segment 号是9,entry 号是2,wrap#值是 0x2013 (8,211 十进制),如果我们想检查使用了哪个undo segment和undohead block的位置,可以通过segment_id 来查询dba_rollback_segs 视图。

 

This transactionID will appear in several different places—a couple of the well-known placesare in the dynamic performance views v$transaction and v$lock. The examples ofdumps that I’ve printed so far came from an instance where nothing else wasrunning, so when I ran the following queries, I knew they would return just onerow which would be for the transaction I had started:

--在除了dump 文件,在v$transaction 和v$lock视图中我们也可以查到transaction ID的信息。如:

 

select xidusn, xidslot, xidsqn fromv$transaction;    

 XIDUSN    XIDSLOT     XIDSQN

---------- ---------- ----------         

9          2       8211

 

select trunc(id1/65536) usn, mod(id1,65536)slot, id2 wrap, lmode from V$lock where type = 'TX';       

 

USN       SLOT       WRAP      LMODE

---------- ---------- ---------- ----------        

 9          2       8211          6

 

You’ll noticethat the lock mode on this “transaction lock” is 6 (exclusive, or X, mode).While my transaction is active, no one else can change that entry in thetransaction table, although, as you will see in Chapter 4, other sessions maytry to acquire it in mode 4 (share, or S, mode) so that they can spot themoment the transaction commits (or rolls back). You’ll also notice that whereI’ve been talking about an “entry” in the transaction table, the view refers toit as a slot, and this is how I’ll refer to it from now on.

--我们可以注意到lock 的模式是6,排他锁. 关于锁的更多说明参考:

ORACLE 锁机制

http://blog.csdn.net/tianlesoftware/article/details/4696896

           

 

2.2 The Transaction Table –事务表

 

Table 3-1 lists and describes the columnsfrom the transaction table extract presented earlier in the chapter.

--下表列出了事务表字段及其描述:

 Oracle Core 学习札记二 - Transactions 和 Consistency 说明

 

In fact, youdon’t need to do block dumps to see the transaction table information becauseit’s exposed in one of the x$ structures: x$ktuxe. This is one of the strangerstructures in Oracle because a query against the structure will actually causeOracle to visit each undo segment header block of each undo segment in thedatabase. The formatting of the contents is different and the cmt column(transaction commit time) isn’t available.

--一般来说,我们不需要dump block 来查看transaction table里的内容,我们可以直接通过x$ktuxe 来查看。每次查询这个字典,都会导致数据库访问所有undo segment 的undo segment header block。