Just got back from watching Oblivion…
I was a little bit reluctant about going to see it because the trailer looked awesome, which these days tends to mean the film is terrible. Fortunately that wasn’t the case here. The film was great. Visually fantastic, with a pretty good story. Why can’t we have a few more Sci-Fi films like this?
As far as the trailers go, Iron Man 3 looks cool and the new Star Trek film looks very interesting. Maybe I’ll get my cinema mojo back after all…
Cheers
Tim…
When using Locally Managed Tablespaces (LMT) with variable, system managed extent sizes (AUTOALLOCATE) and data files residing in ASM the Allocation Unit (AU) size can make a significant difference to the algorithm that searches for free extents.The corresponding free extent search algorithm when searching for free extents >= the AU size seems to only search for free extents on AU boundaries in order to avoid I/O splitting.Furthermore the algorithm seems to use two extent sizes when searching for free extents: A "desired" (for example 8MB) and a "minimum acceptable" (for example 1MB) extent size - however when performing the search the "desired" size seems to be relevant when limiting the search to free extents on AU boundaries.This can lead to some surprising side effects, in particular when using 4MB AUs.It effectively means that although you might have plenty of space (I've seen cases with more than 90% free of a several hundred GB tablespace) processes inserting data might fail with "unable to extend segment" error messages when the "desired" extent size is >= 4MB and the AU size is 4MB, although there might be for example hundreds of (fragmented) free extents available of < 8MB size.This is particularly relevant to Exadata systems because I believe the default ASM AU size is 4MB there.This behaviour can be influenced by using event 60060, which disables the extent alignment to AU boundaries.Here is a simple test case demonstrating the issue. It deliberately interleaves extents of two tables and then drops one of them to leave non-contiguous free space behind:
-----------------------------------------------------------------------
-- Exadata / ASM 4MB AUs LMT AUTOALLOCATE extent fragmentation issue --
-----------------------------------------------------------------------
--
-- Tablespaces using Locally Managed Extents and the AUTOALLOCATE option
-- seem to behave differently on Exadata storage / ASM 4MB AUs than on regular storage / ASM 1MB AUs
--
-- On regular storage / ASM 1MB AUs the algorithm has more flexibility when allocating a next extent
-- For example, if according to the rules an 8MB extent would be required but only 1MB extents
-- are available, it gracefully re-uses the smaller extents, at least to some degree,
-- if they are not too small (for example it won't start re-using 64K free extents if an 8MB extent should be allocated)
--
-- On Exadata / ASM 4MB AUs the same test case fails with an ORA-01652 since it obviously can't re-use the existing free extents
-- Since in the below example there is no suitable extent on AU boundary available the table creation fails
--
-- Given a corresponding usage pattern this can lead to huge space wastage or "unable to extend" errors with plenty of (fragmented) free space
-- in Exadata / ASM 4MB AUs tablespaces
set echo on timing on time on
-- Enable this EVENT to disable the extent alignment to AU boundaries
-- This will allow below table to get created also in a tablespace using 4MB AUs in ASM
-- alter session set events '60060 trace name context forever, level 1';
drop tablespace auto_alloc_test including contents and datafiles;
-- Create tablespace either on ASM / Exadata storage or outside on regular file system
-- by uncommenting the datafile name clause
create tablespace auto_alloc_test
datafile
--'auto_alloc.dbf'
size 400M
extent management local
autoallocate
segment space management auto;
-- Create two tables
begin
for i in 1..2 loop
execute immediate 'create table table'||i||'(col1 number,col2 number) /*segment creation immediate*/ tablespace auto_alloc_test';
end loop;
end;
/
-- Interleave the extents until no space left (the ORA-01653 is expected)
-- This will generate lots of 1MB extents
begin
for i in 1..1000 loop
execute immediate 'alter table table'||(mod(i,2)+1)||' allocate extent';
end loop;
end;
/
-- Free half of the tablespace, but free extents are fragmented, and max. free contiguous space is 1MB
-- If you drop TABLE2, no extents on 4MB AU boundaries will be available
drop table table2;
-- If you drop TABLE1, extents on 4MB AU boundaries will be available and below CREATE TABLE will be successful
--drop table table1;
select sum(bytes)/1024/1024 sum_free_mb, max(bytes)/1024/1024 max_free_mb from dba_free_space where tablespace_name='AUTO_ALLOC_TEST';
-- Create a table that fits into the free space (less than 200MB) but usually will request 8MB extents
--
-- When you drop TABLE2 above, this fails on Exadata storage/ ASM 4MB AUs because it attempts to find extents on AU boundaries that are not available
--
-- When you drop TABLE2 above, this succeeds on regular storage / ASM 1MB AUs because it gracefully re-uses the existing 1MB extents if no 8MB extents can be found among the free extents
--
-- This leads to ORA-01652 error messages on Exadata storage / ASM 4MB AUs with a suitable extent usage pattern although there is plenty of (fragmented) free space
create table test
tablespace auto_alloc_test
as
select rpad('x', 100) as col1 from
(select /*+ cardinality(1e5) */ * from dual connect by level <= 1e5),
(select /*+ cardinality(11) */ * from dual connect by level <= 11)
;
-- In case of success check segment size and extent layout
select bytes/1024/1024 as MB from dba_segments where segment_name = 'TEST' and owner = USER;
select extent_id, bytes, blocks from user_extents where segment_name = 'TEST';
-- In case of failure check AU boundaries of free extents
with au_size
as
(
select allocation_unit_size from v$asm_diskgroup where name = (select substr(file_name, 2, instr(file_name, '/') - 2) from dba_data_files where tablespace_name = 'AUTO_ALLOC_TEST')
)
select count(*) from (
select block_id * 16384 / allocation_unit_size as AU_info, a.* from dba_free_space a, au_size where tablespace_name = 'AUTO_ALLOC_TEST'
)
where au_info = trunc(au_info);
If you run this test case on a tablespace using 4MB AU ASM data files, it will fail to create the last table, although it only requires approx. 127MB and there is approx. 200MB of (non-contiguous) free space (200 times 1MB extents), simply because the "desired" extent size is 8MB and no suitable free extents on "AU boundary" can be found.The relevance of the "AU boundary" condition can easily be checked by changing the test case to drop the other table. This table's extents allocate all the "AU boundaries" and hence the table creation will succeed as a sufficient number of (1MB) extents on "AU boundaries" could be found.If you repeat the same test case with the event set or using data files with a 1MB AU (or simply standard file system data files) the table will be created successfully (even with no extents on "AU boundaries" available), re-using the available 1MB extents. Although the "desired" extent size is still 8MB, the "minimum acceptable" extent size of 1MB allows the re-usage since the free extents don't need to be aligned on AU boundaries.
So with the event you can choose between performance (larger extents, no I/O splitting for desired larger extents) and space usage (non-contiguous, smaller extents).Another option in such cases is the usage of tablespaces with UNIFORM extent allocation, however it might be hard to find a good extent size when dealing with many segments of vastly differing sizes.
This should only be relevant if the processes inserting into the tablespace manage to run at a high concurrency, therefore interleaving the extents (causing non-contiguous free extents when moving / dropping / truncating segments) in conjunction with extent sizes of vastly different sizes.Interestingly I've observed this behaviour on an Exadata system running 11.2.0.3 BP14 and using a tablespace where mostly partitioned objects resided. Since partitioned objects are using an initial extent size of 8MB in recent versions you wouldn't expect this problem in such a scenario, but it looks like that mixing regular load processes with ALTER TABLE ... MOVE COMPRESS PARALLEL can lead to much smaller extent sizes than 8MB and therefore allowing the issue to occur.
I just got permission from The UK Oracle Users Group to reproduce my article series on optimising scans in Oracle. Part One is available here, Part Two will follow shortly after, and then Part Three will be a few weeks away, following its publication in the magazine. Enjoy!
For your entertainment – there’s nothing up my sleeves, this was a simple cut-n-paste after real-time typing with no tricks:
20:39:51 SQL> create table t1 (t1 timestamp); Table created. 20:39:55 SQL> insert into t1 values(systimestamp); 1 row created. 20:39:59 SQL> select t1 - systimestamp from t1; T1-SYSTIMESTAMP --------------------------------------------------------------------------- +000000000 04:59:50.680620 1 row selected. 20:40:08 SQL>
My laptop runs Oracle so quickly that it took only 4 seconds for 5 hours to elapse !
11.2.0.3 on 64-bit Linux – the client is running with TZ=EST5EDT, while the server is running UK Time (currently BST (GMT+1))
Comments available on MOS: 340512.1 Timestamps & time zones – Frequently Asked Questions
Another MOS note, thanks to Jure Bratina in the comments: 227334.1 – “Dates & Calendars – Frequently Asked Questions” in the question
As Niall quotes in the comments: “times are difficult”.
Oracle supplies three timestamps: systimestamp, localtimestamp, and current_timestamp. (For reasons of consistency, only one of uses an underscore ;) )
Oracle also supplies three timestamp types: timestamp, timestamp with time zone, and timestamp with local time zone.
Oracle also supplies two timezone calls: dbtimezone, and sessiontimezone
If you need to figure out all the details of how these things hang together, I think you need to set your machine timezone to something that isn’t UTC (or GMT as I still tend to call it), then use two separate machines as clients, with their timezones set to two other timezones (again avoiding UTC).
I’ve done a few experiments but without being so rigorous in my settings – my machine was running on GMT, but I opened a (UNIX) session and set the session time zone to EST5EDT to start the database, while running other (UNIX) session with different TZ settings. The reason I should have restarted the machine in a different timezone is that Oracle “normalises” some timestamps to UTC – which means there are cases when I can’t be certain whether the stored value is in UTC because it has been normalised or because it simply was the actual machine time.
So here’s a little experiment (11.2.0.2, instance started in EST5EDT, unix session running in UTC, connecting across the network to the server).
select
current_timestamp,
localtimestamp,
systimestamp
from
dual
;
CURRENT_TIMESTAMP
---------------------------------------------------------------------------
LOCALTIMESTAMP
---------------------------------------------------------------------------
SYSTIMESTAMP
---------------------------------------------------------------------------
17-APR-13 11.37.10.870658 AM +01:00
17-APR-13 11.37.10.870658 AM
17-APR-13 06.37.10.870554 AM -04:00
Notes:
systimestamp reflects the instance timestamp – which is 5 hours earlier than the session timestamp.
systimestamp returns a timestamp with time zone, not just a timestamp
localtimestamp and current_timestamp show the client time, but localtimestamp doesn’t show the timezone, current_timestamp does (the +1:00 appears because Daylight Saving Time (British Summer Time) is active so my session is one hour ahead of UTC, while the database is 4 hours behind.)
Another quick test:
create table t1 (
t0 timestamp,
tz timestamp with time zone,
tl timestamp with local time zone,
ts_type varchar2(20)
)
;
insert into t1 values(
systimestamp, systimestamp, systimestamp,
'sys Timestamp'
);
commit;
select * from t1;
T0
---------------------------------------------------------------------------
TZ
---------------------------------------------------------------------------
TL TS_TYPE
--------------------------------------------------------------------------- --------------------
17-APR-13 06.44.04.353489 AM
17-APR-13 06.44.04.353489 AM -04:00
17-APR-13 11.44.04.353489 AM sys Timestamp
select
dump(t0,16),
dump(tz,16),
dump(tl,16),
ts_type
from
t1
;
DUMP(T0,16)
------------------------------------------------------------------------------------------------------------------------
DUMP(TZ,16)
------------------------------------------------------------------------------------------------------------------------
DUMP(TL,16)
------------------------------------------------------------------------------------------------------------------------
TS_TYPE
--------------------
Typ=180 Len=11: 78,71,4,11,7,2d,5,15,11,d0,68
Typ=181 Len=13: 78,71,4,11,b,2d,5,15,11,d0,68,10,3c
Typ=231 Len=11: 78,71,4,11,b,2d,5,15,11,d0,68
sys Timestamp
Notes:
T0 – the timestamp column, has the instance timestamp in it – but doesn’t have any timezone information stored; the raw dump show the value 6:44:04 (7, 2d, 5 – convert from hex and substract one). Anyone on ANY timezone will see their output showing 6:44:04 if they select this column.
TZ – the timestamp with time zone column, has the instance timestamp, but has stored it as (b, 2d,5 – 11:44:04) with time zone information (10,3c) that allows the session to know what “global” moment the information really represents and the location (or, rather, time zone) where is was entered.
TL – the timestamp with local time zone, has the instance timestamp, but has stored it as (b, 2d, 5 – 11:44:04) with NO timezone information. So the output when you query this column is adjusted to suit the local timestamp. It’s the right “global” moment, and it displays as the relevant local time. But, as a penalty, it’s lost the information about where (in which time zone) it was entered.
I think that examination of the content of the raw dumps of the three different types may help you understand why you need to store timestamps in a column type that includes a time zone – if you don’t then you lose some information, and time-based arithmetic will give you some surprises if your application crosses timezones.
Indexing time (though the link in the comments below to Tony Hasler’s blog probably gives you all the answers you need), and an Oracle design error that I’ve visited before.
Check out the extensive slide deck (over 500 slides) about upgrading techniques to Oracle 11.2, by Oracle Corp (Roy Swonger and Mike Dietrich):
It has lots of examples (from real customer upgrade cases) in it.
Thanks to Randolf Geist for telling me about this.
You can also download other interesting presentations from that page (check the right hand side download section), like the Oracle Database Behavior Changes 8.0 through 11.2 doc. Pretty cool!
Assuming my current WordPress prefix was “wp_” and I wanted to change it to “banana_”, then I would do the following…
Take a backup of your database and file system. Remember, if you screw up and trash your blog you will thank yourself for the extra time you spent doing this!
Amend the “$table_prefix” setting in the “wp-config.php” file.
$table_prefix = 'banana_'; // Only numbers, letters, and underscores please!
Rename all the tables, swapping the “wp_” prefix with “banana_”. For example, the following statement would rename the “wp_comments” table to “banana_comments”.
RENAME TABLE wp_comments TO banana_comments
Perform the following updates.
UPDATE banana_options SET option_name = 'banana_user_roles' WHERE option_name = 'wp_user_roles' UPDATE banana_usermeta SET meta_key = 'banana_capabilities' WHERE meta_key = 'wp_capabilities' UPDATE banana_usermeta SET meta_key = 'banana_user_level' WHERE meta_key = 'wp_user_level' UPDATE banana_usermeta SET meta_key = 'banana_autosave_draft_ids' WHERE meta_key = 'wp_autosave_draft_ids'
If you don’t do these updates, the blog will work, but when you try to access the admin site you will be greeted with a message saying,
You do not have sufficient permissions to access this page.
That’s it!
Cheers
Tim…
VirtualBox 4.2.12 has just been released. The downloads and changelog are in the usual places.
Happy upgrading!
Cheers
Tim…
Here’s a deadlock graph that might cause a little confusion:
Deadlock graph:
---------Blocker(s)-------- ---------Waiter(s)---------
Resource Name process session holds waits process session holds waits
TX-001a0015-00014787 34 90 X 32 3 S
TX-00190008-0000601b 32 3 X 34 90 S
session 90: DID 0001-0022-00000327 session 3: DID 0001-0020-000009E9
session 3: DID 0001-0020-000009E9 session 90: DID 0001-0022-00000327
Rows waited on:
Session 90: obj - rowid = 00030CE5 - AAAwzlAAGAABDiuAAA
(dictionary objn - 199909, file - 6, block - 276654, slot - 0)
Session 3: obj - rowid = 00030CE5 - AAAwzlAAGAABp8gAAA
(dictionary objn - 199909, file - 6, block - 433952, slot - 0)
Both sessions are holding X and waiting S on a TX lock. There are several well-known reasons why you might see a share (mode 4) lock on a transaction table slot: collisions on bitmap indexes, unique indexes, index organized tables, or referential integrity checks are the commonest “external” examples, and problems with interested transaction lists (ITLs) or freelists are the common “internal” ones – so the presence of the waits in share mode shouldn’t, of themselves, a source of confusion.
The confusion is in the reported rowids. If you try to interpret them as real rowids you may be unlucky and discover that they seem to be related to the SQL reported for the deadlocked sessions when really the information they hold is garbage. (Just to avoid confusion, let me make it clear that there are cases where the rowids reported definitely WILL be garbage; on the other hand, there may be some scenarios where the rowids are relevant – although I haven’t done any exhaustive check to see if there really are such scenarios.)
When I see a deadlock graph on transaction locks and the waits are for S mode I tend to assume that the information about the rows waited on is probably misleading; when the slot number for the rowid is zero this increases my confidence that the rowid is rubbish. (Zero is a legal value for a rowid slot, of course, so a zero doesn’t prove that the rowid is rubbish, it’s just a coincidence that allows me to continue following a hypothesis.)
The problem is that Oracle doesn’t waste resources tidying up after itself, and in the case of deadlock graphs this laziness shows up in the rowids reported. The trace is simply reporting whatever happens to be in the row_wait_obj#, row_wait_file#, row_wait_block# and row_wait_row# columns of v$session; and if the waiting process hasn’t updated these columns with current row information you could be looking at the details of the last row (or block) that the session waited for. Here’s the description of a test to demonstrate the behaviour:
create table t1 (n1 number, n2 number); insert into t1 values(1,1); create unique index t1_i1 on t1(n1); create unique index t1_i2 on t1(n2); session 1: insert into t1 values(2,11); session 2: insert into t1 values(3,21); session 1: insert into t1 values(4,21); session 2: insert into t1 values(5,11);
With this table, and sequence of events following it, session 1 raised a deadlock error, and dumped the following trace:
Deadlock graph:
---------Blocker(s)-------- ---------Waiter(s)---------
Resource Name process session holds waits process session holds waits
TX-000a0021-0000c4aa 16 93 X 13 90 S
TX-00020020-0000fdb9 13 90 X 16 93 S
session 93: DID 0001-0010-00000057 session 90: DID 0001-000D-000000F2
session 90: DID 0001-000D-000000F2 session 93: DID 0001-0010-00000057
Rows waited on:
Session 90: obj - rowid = 00000009 - AAAAAJAABAAAQJcAAA
(dictionary objn - 9, file - 1, block - 66140, slot - 0)
Session 93: obj - rowid = 0002E7DC - AAAufaAAFAAAAAJAAA
(dictionary objn - 190428, file - 5, block - 9, slot - 0)
Object 9 is the I_FILE#_BLOCK# index in the data dictionary – and session 90 is definitely not doing anything with that object in this transaction.
Object 190428 is another table in the test schema, but session 93 didn’t access it in this transaction, and the block referenced is the segment header block, not a block that could hold a row.
In fact, just before I started the sequence of inserts I ran this query from a third session (connected as sys) with the following results:
select
sid,
row_wait_obj#, row_wait_file#, row_wait_block#, row_wait_row#
from
v$session
where
sid in (90,93)
;
SID ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW#
---------- ------------- -------------- --------------- -------------
90 9 1 66140 0
93 190428 5 9 0
The “rows” reported for the deadlock simply echoed the values that were already in the row_wait columns before the test started. (The sessions were waiting on “SQL*Net message from client” at the time.)
Session 90 created the tables and indexes, that’s probably why it happened to have an outstanding reference to the i_file#_block# index.
Session 93 had just run a script to drop all the objects in the schema, which may explain why it happened to have an outstanding reference to a segment header block
If the row_wait_obj# had been set to -1 for either session then the deadlock graph would have reported “No row” for that session.
By now the Denver Convention Center is probably cleaned up from IOUG Collaborate. The signs directing thousands of attendees to top-notch technical presentations have been removed, the twenty rental laptops which composed the classroom for Pythian’s RAC Attack class have been returned and the vendor exhibition floor has been completely cleared out. Flight delays notwithstanding (thanks to some midwest weather), attendees are generally home by now – even those coming from places as far away as Germany and Australia.
Now that the buzz is dying down, I’ve finally found a few minutes to post my personal highlights.
First off, my favorite part of Collaborate is the opportunity to meet so many old friends and make new acquaintances who are all using Oracle technology. It’s both fun and informative to hear about the ways others are using Oracle software.
One person deserves very special mention: this was my first time hanging out in person with my Australia-based colleague Yury Velikanov. You could hear Yury’s deep-chested, enthuiastic “Pythian” chants even if you were on the opposite side of the exhibition hall from our booth. His sense of fun and relentless demands for silly faces during photos were so unresistable that anybody within about thirty feet of him was affected. In the photo below, notice how the guy standing behind me has also made a silly face for the picture.
I wasn’t able to attend many technical sessions simply because I was so busy with the RAC Attack classes but the two I did attend didn’t disappoint.
Craig Shallahamer‘s session Practical Performance Forecasting for the Oracle DBA was excellent. He compared benchmarking, simulating and modelling for performance evaluation and then took a deep dive into best practices for creating and using models. He discussed a variety of potential input sources in depth and walked through practice exercises on a theoretical consolidation case. Finally we wrapped up with a brief discussion of the queueing theory. Excellent material!
If I had to choose one take-away which I think was the single most important point, it would be this: R = S + Q. Every DBA should know what this is referring to on a basic level. If you don’t know what I’m referring to, then I’d recommend Craig’s class – or any of Cary Millsap‘s talks for that matter (they both cover this very well).
Frits Hoogland‘s session How Oracle Secretly Changed Multiblock Reads (at most conferences this same session is simply titled About Multiblock Reads) is a must-see presentation for DBA’s with any interest in database internals. With the aid of operating system traces and debuggers, Frits has dissected the Oracle database kernel’s I/O process and compiled an incredible summary report. Showing surprising differences between recent releases of Oracle RDBMS, Frits dispels any myth that they aren’t making major changes to the database engine.
However, despite unmatched technical depth and quality, my favorite part of this session wasn’t technical. At one point during the presentation I remember Frits saying that he ran a test and was completely baffled by the output. While trying to problem-solve himself, he also fired off a few emails looking for feedback from others. An email from a colleague pointed him to the “total number of slots” statistic, which led to an “ah-ha” moment and explained the data he was seeing. This was my favorite part because it made me feel much better about asking for help myself, since someone as smart as Frits asks for help sometimes too!
The bulk of my energy this week was dedicated to the RAC Attack class.
First off, I am excited to announce a major development for RAC Attack: we have re-introduced printed textbooks. Two years ago we stopped printing textbooks – when the curriculum was moved to wikibooks in order to better support broad collaboration in creating the best beginner RAC curriculum available. Last week we completed and released the process for creating a printed textbook from the wikibooks content. The process is completely automated. You start up an EC2 instance and run a little code which lives at github; shortly after this you get a PDF which is ready to go to the printers. The 250-page textbook has over 200 screenshots. In the USA, I’ve had them printed in the past for US$30-40 each. This should go a long way toward supporting instructors who want to teach RAC Attack classes. Information about the textbooks is at http://racattack.org/book.
In addition to this, there have been a number of improvements to the organizer’s guide over the past few months. Anyone interested in organizing RAC Attack events can find a good deal of helpful material on the Events wiki page. We’ve learned a lot through the many events we’ve run in the past!
We had 15-20 people gather in the foyer area for the initial kick-off. Everyone listened to the description of the RAC Attack project with interest and some stayed to try starting out with their personal laptops, while many decided to attend one of the two later classroom sessions. We occupied most of the available tables and we were a very noticeable crowd as everyone passed by from the keynote to find technical sessions to attend!
We filled the classroom sessions. There were no major technical problems with lab machines as people worked through the labs. There were many good conversations; I remember in-depth discussions about listener architecture in 11.2 RAC (with SCAN) and about init parameters related to client connections and about services and about applications which require all connections to be made in a single instance.
There was significant positive feedback about RAC Attack. One guy stopped me as I was entering the exhibition hall Monday night just to tell me that that he had learned more in the RAC Attack class than any other session thus far at Collaborate – he was visibly pleased with the experience!
Collaborate was a memorable conference this year. I’m very thankful for the hard work by the IOUG leadership to put this event together! If you attended Collaborate then make sure to pass along your thanks and any other feedback to IOUG! And whether or not you attended – support your local user group; they are a crucial resource and tremendous asset to all of us.
For those of you who attended Collaborate, what were your favorite technical sessions or keynotes? What other parts of the conference did you find valuable? Leave a comment here to tell us what you thought about Collaborate!
Recent comments
17 weeks 2 days ago
27 weeks 18 hours ago
28 weeks 5 days ago
32 weeks 4 hours ago
34 weeks 2 days ago
43 weeks 5 days ago
45 weeks 2 days ago
46 weeks 2 days ago
46 weeks 3 days ago
49 weeks 1 day ago