1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2018, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /**************************************************//** |
21 | @file include/row0trunc.h |
22 | TRUNCATE implementation |
23 | |
24 | Created 2013-04-25 Krunal Bauskar |
25 | *******************************************************/ |
26 | |
27 | #ifndef row0trunc_h |
28 | #define row0trunc_h |
29 | |
30 | #include "row0mysql.h" |
31 | #include "dict0boot.h" |
32 | #include "fil0fil.h" |
33 | #include "srv0start.h" |
34 | #include "ut0new.h" |
35 | |
36 | #include <vector> |
37 | |
38 | /** The information of TRUNCATE log record. |
39 | This class handles the recovery stage of TRUNCATE table. */ |
40 | class truncate_t { |
41 | |
42 | public: |
43 | /** |
44 | Constructor |
45 | |
46 | @param old_table_id old table id assigned to table before truncate |
47 | @param new_table_id new table id that will be assigned to table |
48 | after truncate |
49 | @param dir_path directory path */ |
50 | truncate_t( |
51 | table_id_t old_table_id, |
52 | table_id_t new_table_id, |
53 | const char* dir_path); |
54 | |
55 | /** |
56 | Constructor |
57 | |
58 | @param log_file_name parse the log file during recovery to populate |
59 | information related to table to truncate */ |
60 | truncate_t(const char* log_file_name); |
61 | |
62 | /** |
63 | Consturctor |
64 | |
65 | @param space_id space in which table reisde |
66 | @param name table name |
67 | @param tablespace_flags tablespace flags use for recreating tablespace |
68 | @param log_flags page format flag |
69 | @param recv_lsn lsn of redo log record. */ |
70 | truncate_t( |
71 | ulint space_id, |
72 | const char* name, |
73 | ulint tablespace_flags, |
74 | ulint log_flags, |
75 | lsn_t recv_lsn); |
76 | |
77 | /** Destructor */ |
78 | ~truncate_t(); |
79 | |
80 | /** The index information of MLOG_FILE_TRUNCATE redo record */ |
81 | struct index_t { |
82 | |
83 | /* Default copy constructor and destructor should be OK. */ |
84 | |
85 | index_t(); |
86 | |
87 | /** |
88 | Set the truncate log values for a compressed table. |
89 | @return DB_CORRUPTION or error code */ |
90 | dberr_t set(const dict_index_t* index); |
91 | |
92 | typedef std::vector<byte, ut_allocator<byte> > fields_t; |
93 | |
94 | /** Index id */ |
95 | index_id_t m_id; |
96 | |
97 | /** Index type */ |
98 | ulint m_type; |
99 | |
100 | /** Root Page Number */ |
101 | ulint m_root_page_no; |
102 | |
103 | /** New Root Page Number. |
104 | Note: This field is not persisted to TRUNCATE log but used |
105 | during truncate table fix-up for updating SYS_XXXX tables. */ |
106 | ulint m_new_root_page_no; |
107 | |
108 | /** Number of index fields */ |
109 | ulint m_n_fields; |
110 | |
111 | /** DATA_TRX_ID column position. */ |
112 | ulint m_trx_id_pos; |
113 | |
114 | /** Compressed table field meta data, encode by |
115 | page_zip_fields_encode. Empty for non-compressed tables. |
116 | Should be NUL terminated. */ |
117 | fields_t m_fields; |
118 | }; |
119 | |
120 | /** |
121 | @return the directory path, can be NULL */ |
122 | const char* get_dir_path() const |
123 | { |
124 | return(m_dir_path); |
125 | } |
126 | |
127 | /** |
128 | Register index information |
129 | |
130 | @param index index information logged as part of truncate log. */ |
131 | void add(index_t& index) |
132 | { |
133 | m_indexes.push_back(index); |
134 | } |
135 | |
136 | /** |
137 | Add table to truncate post recovery. |
138 | |
139 | @param ptr table information need to complete truncate of table. */ |
140 | static void add(truncate_t* ptr) |
141 | { |
142 | s_tables.push_back(ptr); |
143 | } |
144 | |
145 | /** |
146 | Clear registered index vector */ |
147 | void clear() |
148 | { |
149 | m_indexes.clear(); |
150 | } |
151 | |
152 | /** |
153 | @return old table id of the table to truncate */ |
154 | table_id_t old_table_id() const |
155 | { |
156 | return(m_old_table_id); |
157 | } |
158 | |
159 | /** |
160 | @return new table id of the table to truncate */ |
161 | table_id_t new_table_id() const |
162 | { |
163 | return(m_new_table_id); |
164 | } |
165 | |
166 | /** |
167 | Update root page number in SYS_XXXX tables. |
168 | |
169 | @param trx transaction object |
170 | @param table_id table id for which information needs to |
171 | be updated. |
172 | @param reserve_dict_mutex if TRUE, acquire/release |
173 | dict_sys->mutex around call to pars_sql. |
174 | @param mark_index_corrupted if true, then mark index corrupted |
175 | @return DB_SUCCESS or error code */ |
176 | dberr_t update_root_page_no( |
177 | trx_t* trx, |
178 | table_id_t table_id, |
179 | ibool reserve_dict_mutex, |
180 | bool mark_index_corrupted) const; |
181 | |
182 | /** Create an index for a table. |
183 | @param[in] table_name table name, for which to create |
184 | the index |
185 | @param[in,out] space tablespace |
186 | @param[in] index_type type of index to truncate |
187 | @param[in] index_id id of index to truncate |
188 | @param[in] btr_redo_create_info control info for ::btr_create() |
189 | @param[in,out] mtr mini-transaction covering the |
190 | create index |
191 | @return root page no or FIL_NULL on failure */ |
192 | inline ulint create_index( |
193 | const char* table_name, |
194 | fil_space_t* space, |
195 | ulint index_type, |
196 | index_id_t index_id, |
197 | const btr_create_t& btr_redo_create_info, |
198 | mtr_t* mtr) const; |
199 | |
200 | /** Create the indexes for a table |
201 | @param[in] table_name table name, for which to create the |
202 | indexes |
203 | @param[in,out] space tablespace |
204 | @param[in] format_flags page format flags |
205 | @return DB_SUCCESS or error code. */ |
206 | inline dberr_t create_indexes( |
207 | const char* table_name, |
208 | fil_space_t* space, |
209 | ulint format_flags); |
210 | |
211 | /** Check if index has been modified since TRUNCATE log snapshot |
212 | was recorded. |
213 | @param[in] space tablespace |
214 | @param[in] root_page_no index root page number |
215 | @return true if modified else false */ |
216 | inline bool is_index_modified_since_logged( |
217 | const fil_space_t* space, |
218 | ulint root_page_no) const; |
219 | |
220 | /** Drop indexes for a table. |
221 | @param[in,out] space tablespace |
222 | @return DB_SUCCESS or error code. */ |
223 | void drop_indexes(fil_space_t* space) const; |
224 | |
225 | /** |
226 | Parses log record during recovery |
227 | @param start_ptr buffer containing log body to parse |
228 | @param end_ptr buffer end |
229 | |
230 | @return DB_SUCCESS or error code */ |
231 | dberr_t parse( |
232 | byte* start_ptr, |
233 | const byte* end_ptr); |
234 | |
235 | /** Parse MLOG_TRUNCATE log record from REDO log file during recovery. |
236 | @param[in,out] start_ptr buffer containing log body to parse |
237 | @param[in] end_ptr buffer end |
238 | @param[in] space_id tablespace identifier |
239 | @return parsed upto or NULL. */ |
240 | static byte* parse_redo_entry( |
241 | byte* start_ptr, |
242 | const byte* end_ptr, |
243 | ulint space_id); |
244 | |
245 | /** |
246 | Write a log record for truncating a single-table tablespace. |
247 | |
248 | @param start_ptr buffer to write log record |
249 | @param end_ptr buffer end |
250 | @param space_id space id |
251 | @param tablename the table name in the usual |
252 | databasename/tablename format of InnoDB |
253 | @param flags tablespace flags |
254 | @param format_flags page format |
255 | @param lsn lsn while logging */ |
256 | dberr_t write( |
257 | byte* start_ptr, |
258 | byte* end_ptr, |
259 | ulint space_id, |
260 | const char* tablename, |
261 | ulint flags, |
262 | ulint format_flags, |
263 | lsn_t lsn) const; |
264 | |
265 | /** |
266 | @return number of indexes parsed from the truncate log record */ |
267 | size_t indexes() const; |
268 | |
269 | /** |
270 | Truncate a single-table tablespace. The tablespace must be cached |
271 | in the memory cache. |
272 | |
273 | Note: This is defined in fil0fil.cc because it needs to access some |
274 | types that are local to that file. |
275 | |
276 | @param space_id space id |
277 | @param dir_path directory path |
278 | @param tablename the table name in the usual |
279 | databasename/tablename format of InnoDB |
280 | @param flags tablespace flags |
281 | @param default_size if true, truncate to default size if tablespace |
282 | is being newly re-initialized. |
283 | @return DB_SUCCESS or error */ |
284 | static dberr_t truncate( |
285 | ulint space_id, |
286 | const char* dir_path, |
287 | const char* tablename, |
288 | ulint flags, |
289 | bool default_size); |
290 | |
291 | /** |
292 | Fix the table truncate by applying information parsed from TRUNCATE log. |
293 | Fix-up includes re-creating table (drop and re-create indexes) |
294 | @return error code or DB_SUCCESS */ |
295 | static dberr_t fixup_tables_in_system_tablespace(); |
296 | |
297 | /** |
298 | Fix the table truncate by applying information parsed from TRUNCATE log. |
299 | Fix-up includes re-creating tablespace. |
300 | @return error code or DB_SUCCESS */ |
301 | static dberr_t fixup_tables_in_non_system_tablespace(); |
302 | |
303 | /** |
304 | Check whether a tablespace was truncated during recovery |
305 | @param space_id tablespace id to check |
306 | @return true if the tablespace was truncated */ |
307 | static bool is_tablespace_truncated(ulint space_id); |
308 | |
309 | /** Was tablespace truncated (on crash before checkpoint). |
310 | If the MLOG_TRUNCATE redo-record is still available then tablespace |
311 | was truncated and checkpoint is yet to happen. |
312 | @param[in] space_id tablespace id to check. |
313 | @return true if tablespace was truncated. */ |
314 | static bool was_tablespace_truncated(ulint space_id); |
315 | |
316 | /** Get the lsn associated with space. |
317 | @param[in] space_id tablespace id to check. |
318 | @return associated lsn. */ |
319 | static lsn_t get_truncated_tablespace_init_lsn(ulint space_id); |
320 | |
321 | private: |
322 | typedef std::vector<index_t, ut_allocator<index_t> > indexes_t; |
323 | |
324 | /** Space ID of tablespace */ |
325 | ulint m_space_id; |
326 | |
327 | /** ID of table that is being truncated. */ |
328 | table_id_t m_old_table_id; |
329 | |
330 | /** New ID that will be assigned to table on truncation. */ |
331 | table_id_t m_new_table_id; |
332 | |
333 | /** Data dir path of tablespace */ |
334 | char* m_dir_path; |
335 | |
336 | /** Table name */ |
337 | char* m_tablename; |
338 | |
339 | /** Tablespace Flags */ |
340 | ulint m_tablespace_flags; |
341 | |
342 | /** Format flags (log flags; stored in page-no field of header) */ |
343 | ulint m_format_flags; |
344 | |
345 | /** Index meta-data */ |
346 | indexes_t m_indexes; |
347 | |
348 | /** LSN of TRUNCATE log record. */ |
349 | lsn_t m_log_lsn; |
350 | |
351 | /** Log file name. */ |
352 | char* m_log_file_name; |
353 | |
354 | /** Encryption information of the table */ |
355 | fil_encryption_t m_encryption; |
356 | uint32_t m_key_id; |
357 | |
358 | /** Vector of tables to truncate. */ |
359 | typedef std::vector<truncate_t*, ut_allocator<truncate_t*> > |
360 | tables_t; |
361 | |
362 | /** Information about tables to truncate post recovery */ |
363 | static tables_t s_tables; |
364 | |
365 | /** Information about truncated table |
366 | This is case when truncate is complete but checkpoint hasn't. */ |
367 | typedef std::map<ulint, lsn_t> truncated_tables_t; |
368 | static truncated_tables_t s_truncated_tables; |
369 | |
370 | public: |
371 | /** If true then fix-up of table is active and so while creating |
372 | index instead of grabbing information from dict_index_t, grab it |
373 | from parsed truncate log record. */ |
374 | static bool s_fix_up_active; |
375 | }; |
376 | |
377 | /** |
378 | Parse truncate log file. */ |
379 | class TruncateLogParser { |
380 | |
381 | public: |
382 | |
383 | /** |
384 | Scan and Parse truncate log files. |
385 | |
386 | @param dir_path look for log directory in following path |
387 | @return DB_SUCCESS or error code. */ |
388 | static dberr_t scan_and_parse( |
389 | const char* dir_path); |
390 | |
391 | private: |
392 | typedef std::vector<char*, ut_allocator<char*> > |
393 | trunc_log_files_t; |
394 | |
395 | private: |
396 | /** |
397 | Scan to find out truncate log file from the given directory path. |
398 | |
399 | @param dir_path look for log directory in following path. |
400 | @param log_files cache to hold truncate log file name found. |
401 | @return DB_SUCCESS or error code. */ |
402 | static dberr_t scan( |
403 | const char* dir_path, |
404 | trunc_log_files_t& log_files); |
405 | |
406 | /** |
407 | Parse the log file and populate table to truncate information. |
408 | (Add this table to truncate information to central vector that is then |
409 | used by truncate fix-up routine to fix-up truncate action of the table.) |
410 | |
411 | @param log_file_name log file to parse |
412 | @return DB_SUCCESS or error code. */ |
413 | static dberr_t parse( |
414 | const char* log_file_name); |
415 | }; |
416 | |
417 | |
418 | /** |
419 | Truncates a table for MySQL. |
420 | @param table table being truncated |
421 | @param trx transaction covering the truncate |
422 | @return error code or DB_SUCCESS */ |
423 | dberr_t |
424 | row_truncate_table_for_mysql(dict_table_t* table, trx_t* trx); |
425 | |
426 | #endif /* row0trunc_h */ |
427 | |
428 | |