1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
/*! @m_page{{c,java},cursor_log,Log cursors}
WiredTiger cursors provide access to data from a variety of sources, and
one of these sources is the records in the transaction log files. Log
files may not be present in every WiredTiger database, only databases
that have been configured for logging using the \c log configuration for
::wiredtiger_open. In databases with log files, a log cursor provides
access to the log records. Although log cursors are read-only,
applications may store records in the log using WT_SESSION::log_printf.
While the log cursor is open automatic log file archiving, even if
enabled, will not reclaim any log files.
Each physical WiredTiger log record represents one or more operations
in the database. When a log record represents more than a single
operation in the database, all of the operations in a log record will
be part of the same transaction, however, there is no corresponding
guarantee that all operations in a transaction must appear in the same
log record.
The following examples are taken from the complete example program
@ex_ref{ex_log.c}.
To open a log cursor on the database:
@snippet ex_log.c log cursor open
A log cursor's key is a unique log record identifier, plus a
@m_if{c}
uint32_t
@m_else
int
@m_endif
operation counter within that log record. When a log record reflects
something log record that is not a transaction, such as the start of
a checkpoint, the operation counter
returned for the key will be zero. When the log record maps to a
transaction, the first log record returned, with an operation counter of
zero, will be the entire log record. Then the WT_CURSOR::next call will
step into the transaction and return the first individual operation
within that transaction and each additional individual operation, adding one to
the operation counter for each one. A transaction with a single operation will
return two records related to that transaction.
The unique log record identifier maps to a WT_LSN data structure, which
has two fields: WT_LSN::file, the log file identifier, and WT_LSN::offset,
the offset of the log record in the log file.
Here is an example of getting the log cursor's key:
@snippet ex_log.c log cursor get_key
The log cursor's value is comprised of six fields:
@m_if{c}
- a \c uint64_t transaction ID (set for commit records only, otherwise 0),
- a \c uint32_t log record type
- a \c uint32_t operation type (set for commit records only, otherwise 0)
- a \c uint32_t file id (if applicable, otherwise 0)
@m_else
- a \c long transaction ID (set for commit records only, otherwise 0),
- a \c int record type
- a \c int operation type (set for commit records only, otherwise 0)
- a \c int file id (if applicable, otherwise 0)
@m_endif
- the operation key (commit records only, otherwise empty)
- the operation value
The transaction ID may not be unique across recovery, that is, closing
and reopening the database may result in transaction IDs smaller than
previously seen transaction IDs.
The log record and log operation types are taken from @ref_single log_types;
typically, the only record or operation type applications are concerned with
is ::WT_LOGREC_MESSAGE, which is a log record generated by the application.
The file ID may not be unique across recovery, that is, closing and
reopening the database may result in file IDs changing. Additionally,
there is currently no way to map file IDs to file names or higher-level
objects.
Here is an example of getting the log cursor's value:
@snippet ex_log.c log cursor get_value
For clarity, imagine a set of three log records:
- the first recording an internal operation, say a checkpoint start,
- the second committing a transaction with three operations,
- the third committing a transaction with a single operation.
The log cursor's WT_CURSOR::next call will return a total of seven
records. Here's an example of what it would look like:
1. LSN=[1,1000], operation counter=0, transaction ID=0, value of checkpoint start
2. LSN=[1,2000], operation counter=0, transaction ID=30, all operations of transaction 30
3. LSN=[1,2000], operation counter=1, transaction ID=30, first operation of transaction 30
4. LSN=[1,2000], operation counter=2, transaction ID=30, second operation of transaction 30
5. LSN=[1,2000], operation counter=3, transaction ID=30, third operation of transaction 30
6. LSN=[1,3000], operation counter=0, transaction ID=31, all operations of transaction 31
7. LSN=[1,3000], operation counter=1, transaction ID=31, only operation of transaction 31
The first time the log cursor will return a key with a unique
log ID, no transaction ID, and an operation counter of 0. The
next six returns from the log cursor will have a common log ID, a
common transaction ID, and operation counters starting at 0, returning
the whole record and then starting at 1 and ending at 5 for each
of the five individual operations. The next return from the log cursor
will again have a unique log ID, a unique transaction ID, and an
operation counter of 0. And the final return from the log cursor
will have an operation counter of 1.
Here's a more complete example of walking the log and displaying
the results:
@snippet ex_log.c log cursor walk
The log cursor's key can be used to search for specific records in the
log (assuming the record still exists and has not been archived), by
setting the key and calling WT_CURSOR::search. However, it is not
possible to search for a specific operation within a log record, and the
key's operation counter is ignored when the key is set. The result of
a search for a log record with more than one operation is always the
first operation in the log record.
Here is an example of setting the log cursor's key:
@snippet ex_log.c log cursor set_key
Log cursors are read-only, however applications can insert their own log
records using WT_SESSION::log_printf. Here is an example of adding an
application record into the database log:
@snippet ex_log.c log cursor printf
*/
|