1 /*****************************************************************************
2 
3 Copyright (c) 2017, 2019, Oracle and/or its affiliates. All Rights Reserved.
4 
5 Portions of this file contain modifications contributed and copyrighted by
6 Google, Inc. Those modifications are gratefully acknowledged and are described
7 briefly in the InnoDB documentation. The contributions by Google are
8 incorporated with their permission, and subject to the conditions contained in
9 the file COPYING.Google.
10 
11 This program is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License, version 2.0, as published by the
13 Free Software Foundation.
14 
15 This program is also distributed with certain software (including but not
16 limited to OpenSSL) that is licensed under separate terms, as designated in a
17 particular file or component or in included license documentation. The authors
18 of MySQL hereby grant you an additional permission to link the program and
19 your derivative works with the separately licensed software that they have
20 included with MySQL.
21 
22 This program is distributed in the hope that it will be useful, but WITHOUT
23 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
24 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
25 for more details.
26 
27 You should have received a copy of the GNU General Public License along with
28 this program; if not, write to the Free Software Foundation, Inc.,
29 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
30 
31 *****************************************************************************/
32 
33 /** @file include/log0ddl.h
34  DDL log
35 
36  Created 12/1/2016 Shaohua Wang
37  *******************************************************/
38 
39 #ifndef log0ddl_h
40 #define log0ddl_h
41 
42 /** DDL log types defined as uint32_t because it costs 4 bytes in
43 mysql.innodb_ddl_log. */
44 enum class Log_Type : uint32_t {
45   /** Smallest log type */
46   SMALLEST_LOG = 1,
47 
48   /** Drop an index tree */
49   FREE_TREE_LOG = 1,
50 
51   /** Delete a file */
52   DELETE_SPACE_LOG,
53 
54   /** Rename a file */
55   RENAME_SPACE_LOG,
56 
57   /** Drop the entry in innodb_table_metadata */
58   DROP_LOG,
59 
60   /** Rename table in dict cache. */
61   RENAME_TABLE_LOG,
62 
63   /** Remove a table from dict cache */
64   REMOVE_CACHE_LOG,
65 
66   /** Alter Encrypt a tablespace */
67   ALTER_ENCRYPT_TABLESPACE_LOG,
68 
69   /** Biggest log type */
70   BIGGEST_LOG = ALTER_ENCRYPT_TABLESPACE_LOG
71 };
72 
73 /** DDL log record */
74 class DDL_Record {
75  public:
76   /** Constructor. */
77   DDL_Record();
78 
79   /** Destructor. */
80   ~DDL_Record();
81 
82   /** Get the id of the DDL log record.
83   @return id of the record. */
get_id()84   ulint get_id() const { return (m_id); }
85 
86   /** Set the id for the DDL log record.
87   @param[in]	id	id of the record. */
set_id(ulint id)88   void set_id(ulint id) { m_id = id; }
89 
90   /** Get the type of operation to perform
91   for the DDL log record.
92   @return type of the record. */
get_type()93   Log_Type get_type() const { return (m_type); }
94 
95   /** Set the type for the DDL log record.
96   @param[in]	type	set the record type.*/
set_type(Log_Type type)97   void set_type(Log_Type type) { m_type = type; }
98 
99   /** Get the thread id for the DDL log record.
100   @return thread id of the DDL log record. */
get_thread_id()101   ulint get_thread_id() const { return (m_thread_id); }
102 
103   /** Set the thread id for the DDL log record.
104   @param[in]	thread_id	thread id. */
set_thread_id(ulint thread_id)105   void set_thread_id(ulint thread_id) { m_thread_id = thread_id; }
106 
107   /** Get the space_id present in the DDL log record.
108   @return space_id in the DDL log record. */
get_space_id()109   space_id_t get_space_id() const { return (m_space_id); }
110 
111   /** Set the space id for the DDL log record.
112   @param[in]	space	space id. */
set_space_id(space_id_t space)113   void set_space_id(space_id_t space) { m_space_id = space; }
114 
115   /** Get the page no present in the DDL log record.
116   @return page_no */
get_page_no()117   page_no_t get_page_no() const { return (m_page_no); }
118 
119   /** Set the page number for the DDL log record.
120   @param[in]	page_no	page number. */
set_page_no(page_no_t page_no)121   void set_page_no(page_no_t page_no) { m_page_no = page_no; }
122 
123   /** Get the index id present in the DDL log record.
124   @return index id. */
get_index_id()125   ulint get_index_id() const { return (m_index_id); }
126 
127   /** Set the index id for the DDL log record.
128   @param[in]	index_id	index id. */
set_index_id(ulint index_id)129   void set_index_id(ulint index_id) { m_index_id = index_id; }
130 
131   /** Get the table id present in the DDL log record.
132   @return table id from the record. */
get_table_id()133   table_id_t get_table_id() const { return (m_table_id); }
134 
135   /** Set the table if for the DDL log record.
136   @param[in]	table_id	table id. */
set_table_id(table_id_t table_id)137   void set_table_id(table_id_t table_id) { m_table_id = table_id; }
138 
139   /** Set deletability of this record.
140   @param[in] deletable	deletability. */
set_deletable(bool deletable)141   void set_deletable(bool deletable) { m_deletable = deletable; }
142 
143   /** If this record can be deleted.
144   @return true if record is deletable. */
get_deletable()145   bool get_deletable() const { return (m_deletable); }
146 
147   /** Get the old file path/name present in the DDL log record.
148   @return old file path/name. */
get_old_file_path()149   const char *get_old_file_path() const { return (m_old_file_path); }
150 
151   /** Set the old file path from the name for the DDL log record.
152   @param[in]	name	old file name. */
153   void set_old_file_path(const char *name);
154 
155   /** Copy the data and set it in old file path
156   @param[in]	data	data to be set
157   @param[in]	len	length of the data. */
158   void set_old_file_path(const byte *data, ulint len);
159 
160   /** Get the new file path/name present in the DDL log record.
161   @return new file path/name. */
get_new_file_path()162   const char *get_new_file_path() const { return (m_new_file_path); }
163 
164   /** Set the new file path/name for the DDL log record.
165   @param[in]	name	name to be set. */
166   void set_new_file_path(const char *name);
167 
168   /** Copy the data and set it in new file path.
169   @param[in]	data	data to be set
170   @param[in]	len	length of the data. */
171   void set_new_file_path(const byte *data, ulint len);
172 
173   /** Print the DDL record to specified output stream
174   @param[in,out]	out	output stream
175   @return output stream */
176   std::ostream &print(std::ostream &out) const;
177 
178  private:
179   /** Log id */
180   ulint m_id;
181 
182   /** Log type */
183   Log_Type m_type;
184 
185   /** Thread id */
186   ulint m_thread_id;
187 
188   /** Tablespace id */
189   space_id_t m_space_id;
190 
191   /** Index root page */
192   page_no_t m_page_no;
193 
194   /** Index id */
195   ulint m_index_id;
196 
197   /** Table id */
198   table_id_t m_table_id;
199 
200   /** Tablespace file path for DELETE, Old tablespace file path
201   for RENAME */
202   char *m_old_file_path;
203 
204   /** New tablespace file name for RENAME */
205   char *m_new_file_path;
206 
207   /** memory heap object used for storing file name. */
208   mem_heap_t *m_heap;
209 
210   /** If this record can be deleted */
211   bool m_deletable;
212 };
213 
214 /** Forward declaration */
215 class THD;
216 struct que_thr_t;
217 struct dtuple_t;
218 
219 /** Array of DDL records */
220 using DDL_Records = std::vector<DDL_Record *>;
221 
222 /** Wrapper of mysql.innodb_ddl_log table. Accessing to this table doesn't
223 require row lock because thread could only access/modify its own ddl records. */
224 class DDL_Log_Table {
225  public:
226   /** Constructor. */
227   DDL_Log_Table();
228 
229   /** Constructor and it initalizes transaction and query thread.
230   Once trx is passed in, make sure destructor is called before the
231   trx commits.
232   @param[in,out]	trx	Transaction */
233   explicit DDL_Log_Table(trx_t *trx);
234 
235   /** Destructor. */
236   ~DDL_Log_Table();
237 
238   /** Insert the DDL log record into the innodb_ddl_log table.
239   This is thread safe.
240   @param[in]	record	Record to be inserted.
241   @return DB_SUCCESS or error. */
242   dberr_t insert(const DDL_Record &record);
243 
244   /** Search for all records of specified thread_id. The records
245   are kept in reverse order.
246   This is thread safe. Because different threads have different thread
247   ids, there should not be any conflict with update.
248   @param[in]	thread_id	thread id to search
249   @param[out]	records		DDL_Records of the specified thread id
250   @return DB_SUCCESS or error. */
251   dberr_t search(ulint thread_id, DDL_Records &records);
252 
253   /** Do a reverse scan on the table to fetch all the record.
254   This is only called during recovery
255   @param[out]	records	DDL_Records of the whole table
256   @return DB_SUCCESS or error. */
257   dberr_t search_all(DDL_Records &records);
258 
259   /** Delete the innodb_ddl_log record of specified ID.
260   This is thread safe. One thread will only remove its ddl record.
261   @param[in]	id	ID of the DDL_Record
262   @return DB_SUCCESS or error. */
263   dberr_t remove(ulint id);
264 
265   /** Delete specified DDL_Records from innodb_ddl_log.
266   This is thread safe. Different threads have their own ddl records
267   to delete. And this could be called during recovery.
268   @param[in]	records		DDL_Record(s) to be deleted
269   @return DB_SUCCESS or error. */
270   dberr_t remove(const DDL_Records &records);
271 
272  private:
273   /** Set the query thread using graph. */
274   void start_query_thread();
275 
276   /** Stop the query thread. */
277   void stop_query_thread();
278 
279   /** Create tuple for the innodb_ddl_log table.
280   It is used for insert operation.
281   @param[in]	record	DDL log record. */
282   void create_tuple(const DDL_Record &record);
283 
284   /** Create tuple for the given index. Used for search by id
285   (and following delete)
286   @param[in]	id	Thread id/ id of the record
287   @param[in]	index	Clustered index or secondary index. */
288   void create_tuple(ulint id, const dict_index_t *index);
289 
290   /** Convert the innodb_ddl_log index record to DDL_Record.
291   @param[in]	is_clustered	true if this is clustered index record,
292                                   otherwise the secondary index record
293   @param[in]	rec		index record
294   @param[in]	offsets		index record offset
295   @param[in,out]	record		to store the innodb_ddl_log record. */
296   void convert_to_ddl_record(bool is_clustered, rec_t *rec,
297                              const ulint *offsets, DDL_Record &record);
298 
299   /** Parse the index record and get 'ID'.
300   @param[in]	index	index where the record resides
301   @param[in]	rec	index rec
302   @param[in]	offsets	offsets of the index.
303   @return id of the record. */
304   ulint parse_id(const dict_index_t *index, rec_t *rec, const ulint *offsets);
305 
306   /** Set the given field of the innodb_ddl_log record from given data.
307   @param[in]	data	data to be set
308   @param[in]	offset	column of the ddl record
309   @param[in]	len	length of the data
310   @param[in,out]	record	DDL_Record to set */
311   void set_field(const byte *data, ulint offset, ulint len, DDL_Record &record);
312 
313   /** Fetch the value from given offset.
314   @param[in]	data	value to be retrieved from data
315   @param[in]	offset	offset of the column
316   @return value of the given offset. */
317   ulint fetch_value(const byte *data, ulint offset);
318 
319   /** Seach specified index by specified ID
320   @param[in]	id	ID to search
321   @param[in]	index	index to search
322   @param[in,out]	records	DDL_Record(s) got by the search
323   @return DB_SUCCESS or error */
324   dberr_t search_by_id(ulint id, dict_index_t *index, DDL_Records &records);
325 
326  private:
327   /** Column number of mysql.innodb_ddl_log.id. */
328   static constexpr unsigned s_id_col_no = 0;
329 
330   /** Column length of mysql.innodb_ddl_log.id. */
331   static constexpr unsigned s_id_col_len = 8;
332 
333   /** Column number of mysql.innodb_ddl_log.thread_id. */
334   static constexpr unsigned s_thread_id_col_no = 1;
335 
336   /** Column length of mysql.innodb_ddl_log.thread_id. */
337   static constexpr unsigned s_thread_id_col_len = 8;
338 
339   /** Column number of mysql.innodb_ddl_log.type. */
340   static constexpr unsigned s_type_col_no = 2;
341 
342   /** Column length of mysql.innodb_ddl_log.type. */
343   static constexpr unsigned s_type_col_len = 4;
344 
345   /** Column number of mysql.innodb_ddl_log.space_id. */
346   static constexpr unsigned s_space_id_col_no = 3;
347 
348   /** Column length of mysql.innodb_ddl_log.space_id. */
349   static constexpr unsigned s_space_id_col_len = 4;
350 
351   /** Column number of mysql.innodb_ddl_log.page_no. */
352   static constexpr unsigned s_page_no_col_no = 4;
353 
354   /** Column length of mysql.innodb_ddl_log.page_no. */
355   static constexpr unsigned s_page_no_col_len = 4;
356 
357   /** Column number of mysql.innodb_ddl_log.index_id. */
358   static constexpr unsigned s_index_id_col_no = 5;
359 
360   /** Column length of mysql.innodb_ddl_log.index_id. */
361   static constexpr unsigned s_index_id_col_len = 8;
362 
363   /** Column number of mysql.innodb_ddl_log.table_id. */
364   static constexpr unsigned s_table_id_col_no = 6;
365 
366   /** Column length of mysql.innodb_ddl_log.table_id. */
367   static constexpr unsigned s_table_id_col_len = 8;
368 
369   /** Column number of mysql.innodb_ddl_log.old_file_path. */
370   static constexpr unsigned s_old_file_path_col_no = 7;
371 
372   /** Column number of mysql.innodb_ddl_log.new_file_path. */
373   static constexpr unsigned s_new_file_path_col_no = 8;
374 
375   /** innodb_ddl_log table. */
376   dict_table_t *m_table;
377 
378   /** Tuple used for insert, search, delete operation. */
379   dtuple_t *m_tuple;
380 
381   /** Transaction used for insert, delete operation. */
382   trx_t *m_trx;
383 
384   /** Dummy query thread. */
385   que_thr_t *m_thr;
386 
387   /** Heap to store the m_tuple, m_thr and all
388   operation on mysql.innodb_ddl_log table. */
389   mem_heap_t *m_heap;
390 };
391 
392 /** Class to write and replay ddl logs */
393 class Log_DDL {
394  public:
395   /** Constructor */
396   Log_DDL();
397 
398   /** Deconstructor */
~Log_DDL()399   ~Log_DDL() {}
400 
401   /** Write DDL log for freeing B-tree
402   @param[in,out]	trx		transaction
403   @param[in]	index		dict index
404   @param[in]	is_drop_table	true if this is drop table
405   @return	DB_SUCCESS or error */
406   dberr_t write_free_tree_log(trx_t *trx, const dict_index_t *index,
407                               bool is_drop_table);
408 
409   /** Write DDL log for deleting tablespace file
410   @param[in,out]	trx		transaction
411   @param[in]	table		dict table
412   @param[in]	space_id	tablespace id
413   @param[in]	file_path	file path
414   @param[in]	is_drop		flag whether dropping tablespace
415   @param[in]	dict_locked	true if dict_sys mutex is held
416   @return	DB_SUCCESS or error */
417   dberr_t write_delete_space_log(trx_t *trx, const dict_table_t *table,
418                                  space_id_t space_id, const char *file_path,
419                                  bool is_drop, bool dict_locked);
420 
421   /** Write a RENAME log record
422   @param[in]	space_id	tablespace id
423   @param[in]	old_file_path	file path after rename
424   @param[in]	new_file_path	file path before rename
425   @return DB_SUCCESS or error */
426   dberr_t write_rename_space_log(space_id_t space_id, const char *old_file_path,
427                                  const char *new_file_path);
428 
429   /** Write an ALTER ENCRYPT Tablespace DDL log record
430   @param[in]	space_id	tablespace id
431   @return DB_SUCCESS or error */
432   dberr_t write_alter_encrypt_space_log(space_id_t space_id);
433 
434   /** Write a DROP log to indicate the entry in innodb_table_metadata
435   should be removed for specified table
436   @param[in,out]	trx		transaction
437   @param[in]	table_id	table ID
438   @return DB_SUCCESS or error */
439   dberr_t write_drop_log(trx_t *trx, const table_id_t table_id);
440 
441   /** Write a RENAME table log record
442   @param[in]	table		dict table
443   @param[in]	old_name	table name after rename
444   @param[in]	new_name	table name before rename
445   @return DB_SUCCESS or error */
446   dberr_t write_rename_table_log(dict_table_t *table, const char *old_name,
447                                  const char *new_name);
448 
449   /** Write a REMOVE cache log record
450   @param[in,out]	trx		transaction
451   @param[in]	table		dict table
452   @return DB_SUCCESS or error */
453   dberr_t write_remove_cache_log(trx_t *trx, dict_table_t *table);
454 
455   /** Replay DDL log record
456   @param[in,out]	record	DDL log record
457   return DB_SUCCESS or error */
458   dberr_t replay(DDL_Record &record);
459 
460   /** Replay and clean DDL logs after DDL transaction
461   commints or rollbacks.
462   @param[in]	thd	mysql thread
463   @return	DB_SUCCESS or error */
464   dberr_t post_ddl(THD *thd);
465 
466   /** Recover in server startup.
467   Scan innodb_ddl_log table, and replay all log entries.
468   Note: redo log should be applied, and DD transactions
469   should be recovered before calling this function.
470   @return	DB_SUCCESS or error */
471   dberr_t recover();
472 
473   /** Post tablespace (un)encryption recovery. Delete ddl logs
474   entry for the tablespaces for which (un)encyrption operation
475   was resumed.
476   NOTE: This is called by background thread doing resume (un)encryption.
477   param[in]	records		list of records to be deleted
478   @return InnoDB error code */
479   dberr_t post_ts_encryption(DDL_Records &records);
480 
481   /** Is it in ddl recovery in server startup.
482   @return	true if it's in ddl recover */
is_in_recovery()483   static bool is_in_recovery() { return (s_in_recovery); }
484 
485  private:
486   /** Insert a FREE log record
487   @param[in,out]	trx		transaction
488   @param[in]	index		dict index
489   @param[in]	id		log id
490   @param[in]	thread_id	thread id
491   @return DB_SUCCESS or error */
492   dberr_t insert_free_tree_log(trx_t *trx, const dict_index_t *index,
493                                uint64_t id, ulint thread_id);
494 
495   /** Replay FREE log(free B-tree if exist)
496   @param[in]	space_id	tablespace id
497   @param[in]	page_no		root page no
498   @param[in]	index_id	index id */
499   void replay_free_tree_log(space_id_t space_id, page_no_t page_no,
500                             ulint index_id);
501 
502   /** Insert a DELETE log record
503   @param[in,out]	trx		transaction
504   @param[in]	id		log id
505   @param[in]	thread_id	thread id
506   @param[in]	space_id	tablespace id
507   @param[in]	file_path	file path
508   @param[in]	dict_locked	true if dict_sys mutex is held
509   @return DB_SUCCESS or error */
510   dberr_t insert_delete_space_log(trx_t *trx, uint64_t id, ulint thread_id,
511                                   space_id_t space_id, const char *file_path,
512                                   bool dict_locked);
513 
514   /** Replay DELETE log(delete file if exist)
515   @param[in]	space_id	tablespace id
516   @param[in]	file_path	file path */
517   void replay_delete_space_log(space_id_t space_id, const char *file_path);
518 
519   /** Insert a RENAME log record
520   @param[in]	id		log id
521   @param[in]	thread_id	thread id
522   @param[in]	space_id	tablespace id
523   @param[in]	old_file_path	file path after rename
524   @param[in]	new_file_path	file path before rename
525   @return DB_SUCCESS or error */
526   dberr_t insert_rename_space_log(uint64_t id, ulint thread_id,
527                                   space_id_t space_id,
528                                   const char *old_file_path,
529                                   const char *new_file_path);
530 
531   /** Replay RENAME log
532   @param[in]	space_id	tablespace id
533   @param[in]	old_file_path	old file path
534   @param[in]	new_file_path	new file path */
535   void replay_rename_space_log(space_id_t space_id, const char *old_file_path,
536                                const char *new_file_path);
537 
538   /** Insert an ALTER ENCRYPT TABLESPACE log record
539   @param[in]	id		log id
540   @param[in]	thread_id	thread id
541   @param[in]	space_id	tablespace id
542   @return DB_SUCCESS or error */
543   dberr_t insert_alter_encrypt_space_log(uint64_t id, ulint thread_id,
544                                          space_id_t space_id);
545 
546   /** Replay an ALTER ENCRYPT TABLESPACE log record
547   @param[in]	space_id	tablespace id */
548   void replay_alter_encrypt_space_log(space_id_t space_id);
549 
550   /** Insert a DROP log record
551   @param[in,out]	trx		transaction
552   @param[in]	id		log id
553   @param[in]	thread_id	thread id
554   @param[in]	table_id	table id
555   @return DB_SUCCESS or error */
556   dberr_t insert_drop_log(trx_t *trx, uint64_t id, ulint thread_id,
557                           const table_id_t table_id);
558 
559   /** Replay DROP log
560   @param[in]	table_id	table id */
561   void replay_drop_log(const table_id_t table_id);
562 
563   /** Insert a RENAME TABLE log record
564   @param[in]	id		log id
565   @param[in]	thread_id	thread id
566   @param[in]	table_id	table id
567   @param[in]	old_name	table name after rename
568   @param[in]	new_name	table name before rename
569   @return DB_SUCCESS or error */
570   dberr_t insert_rename_table_log(uint64_t id, ulint thread_id,
571                                   table_id_t table_id, const char *old_name,
572                                   const char *new_name);
573 
574   /** Relay RENAME TABLE log
575   @param[in]	table_id	table id
576   @param[in]	old_name	old name
577   @param[in]	new_name	new name */
578   void replay_rename_table_log(table_id_t table_id, const char *old_name,
579                                const char *new_name);
580 
581   /** Insert a REMOVE cache log record
582   @param[in]	id		log id
583   @param[in]	thread_id	thread id
584   @param[in]	table_id	table id
585   @param[in]	table_name	table name
586   @return DB_SUCCESS or error */
587   dberr_t insert_remove_cache_log(uint64_t id, ulint thread_id,
588                                   table_id_t table_id, const char *table_name);
589 
590   /** Relay remove cache log
591   @param[in]	table_id	table id
592   @param[in]	table_name	table name */
593   void replay_remove_cache_log(table_id_t table_id, const char *table_name);
594 
595   /** Delete log record by id
596   @param[in]	trx		transaction instance
597   @param[in]	id		log id
598   @param[in]	dict_locked	true if dict_sys mutex is held,
599                                   otherwise false
600   @return DB_SUCCESS or error */
601   dberr_t delete_by_id(trx_t *trx, uint64_t id, bool dict_locked);
602 
603   /** Scan, replay and delete log records by thread id
604   @param[in]	thread_id	thread id
605   @return DB_SUCCESS or error */
606   dberr_t replay_by_thread_id(ulint thread_id);
607 
608   /** Delete the log records present in the list.
609   @param[in]	records		DDL_Records where the IDs are got
610   @return DB_SUCCESS or error. */
611   dberr_t delete_by_ids(DDL_Records &records);
612 
613   /** Scan, replay and delete all log records
614   @return DB_SUCCESS or error */
615   dberr_t replay_all();
616 
617   /** Get next autoinc counter by increasing 1 for innodb_ddl_log
618   @return	new next counter */
619   inline uint64_t next_id();
620 
621   /** Check if we need to skip ddl log for a table.
622   @param[in]	table	dict table
623   @param[in]	thd	mysql thread
624   @return true if should skip, otherwise false */
625   inline bool skip(const dict_table_t *table, THD *thd);
626 
627  private:
628   /** Whether in recover(replay) ddl log in startup. */
629   static bool s_in_recovery;
630 };
631 
632 /** Object to handle Log_DDL */
633 extern Log_DDL *log_ddl;
634 
635 /** Close the DDL log system */
ddl_log_close()636 inline void ddl_log_close() { UT_DELETE(log_ddl); }
637 
638 #ifdef UNIV_DEBUG
639 struct SYS_VAR;
640 
641 /** Used by SET GLOBAL innodb_ddl_log_crash_counter_reset_debug = 1; */
642 extern bool innodb_ddl_log_crash_reset_debug;
643 
644 /** Reset all crash injection counters. It's used by:
645         SET GLOBAL innodb_ddl_log_crash_reset_debug = 1 (0).
646 @param[in]	thd	thread handle
647 @param[in]	var	pointer to system variable
648 @param[in]	var_ptr	where the formal string goes
649 @param[in]	save	immediate result from check function */
650 void ddl_log_crash_reset(THD *thd, SYS_VAR *var, void *var_ptr,
651                          const void *save);
652 #endif /* UNIV_DEBUG */
653 
654 #endif /* log0ddl_h */
655