1 /* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /**
24 @file sql/mysqld.cc
25 MySQL server daemon.
26 */
27
28 /* clang-format off */
29 /**
30 @mainpage Welcome
31
32 Welcome to the MySQL source code documentation.
33
34 This documentation covers primarily the MySQL server,
35 for the @c mysqld process.
36
37 Other programs, like the MySQL Router, are also documented,
38 see the @ref PAGE_SERVER_TOOLS section.
39
40 The order chosen to present the content is to start with low level components,
41 and build upon previous sections, so that code is presented in a logical order.
42
43 For some sections, a full article (Doxygen 'page') presents the component in detail.
44
45 For other sections, only links are provided, as a starting point into the component.
46
47 For the user manual, see http://dev.mysql.com/doc/refman/8.0/en/
48
49 For the internals manual, see https://dev.mysql.com/doc/internals/en/index.html
50
51 This documentation is published for each release, starting with MySQL 8.0.
52
53 The present document corresponds to:
54
55 Document generated on: ${DOXYGEN_GENERATION_DATE},
56 branch: ${DOXYGEN_GENERATION_BRANCH},
57 revision: ${DOXYGEN_GENERATION_REVISION}
58
59 For the latest available version, see https://dev.mysql.com/doc/dev/mysql-server/latest/
60
61 For other versions, see https://dev.mysql.com/doc/index-archive.html
62 */
63
64 /**
65 @page PAGE_GET_STARTED Getting Started
66
67 - @ref start_source
68 - @subpage PAGE_CODING_GUIDELINES
69 - @ref start_debug
70
71 @section start_source Build from source
72
73 See https://dev.mysql.com/doc/refman/8.0/en/source-installation.html
74
75 @section start_debug Debugging
76
77 The easiest way to install a server, and attach a debugger to it,
78 is to start the mysql-test-run (MTR) tool with debugging options
79
80 @verbatim
81 cd mysql-test
82 ./mtr --ddd main.parser
83 @endverbatim
84
85 The following functions are good candidates for breakpoints:
86 - #my_message_sql
87 - #dispatch_command
88
89 Replace 'main.parser' with another test script, or write your own, to debug a specific area.
90 */
91
92 /**
93 @page PAGE_CODING_GUIDELINES Coding Guidelines
94
95 This section shows the guidelines that MySQL developers
96 follow when writing new code.
97
98 New MySQL code uses the Google C++ coding style
99 (https://google.github.io/styleguide/cppguide.html), with one
100 exception:
101
102 - Member variable names: Do not use foo_. Instead, use
103 m_foo (non-static) or s_foo (static).
104
105 Old projects and modifications to old code use an older MySQL-specific
106 style for the time being. Since 8.0, MySQL style uses the same formatting
107 rules as Google coding style (e.g., brace placement, indentation, line
108 lengths, etc.), but differs in a few important aspects:
109
110 - Class names: Do not use MyClass. Instead, use My_class.
111
112 - Function names: Use snake_case().
113
114 - Comment Style: Use either the // or <em>/</em>* *<em>/</em> syntax. // is
115 much more common but both syntaxes are permitted for the time being.
116
117 - Doxygen comments: Use <em>/</em>** ... *<em>/</em> syntax and not ///.
118
119 - Doxygen commands: Use '@' and not '\' for doxygen commands.
120
121 - You may see structs starting with st_ and being typedef-ed to some
122 UPPERCASE (e.g. typedef struct st_foo { ... } FOO). However,
123 this is legacy from when the codebase contained C. Do not make such new
124 typedefs nor structs with st_ prefixes, and feel free to remove those that
125 already exist, except in public header files that are part of libmysql
126 (which need to be parseable as C99).
127
128
129 Code formatting is enforced by use of clang-format throughout the code
130 base. However, note that formatting is only one part of coding style;
131 you are required to take care of non-formatting issues yourself, such as
132 following naming conventions, having clear ownership of code or minimizing
133 the use of macros. See the Google coding style guide for the entire list.
134
135 Consistent style is important for us, because everyone must know what to
136 expect. Knowing our rules, you'll find it easier to read our code, and when
137 you decide to contribute (which we hope you'll consider!) we'll find it
138 easier to read and review your code.
139
140 - @subpage GENERAL_DEVELOPMENT_GUIDELINES
141 - @subpage CPP_CODING_GUIDELINES_FOR_NDB_SE
142 - @subpage DBUG_TAGS
143
144 */
145
146 /**
147 @page PAGE_INFRASTRUCTURE Infrastructure
148
149 @section infra_basic Basic classes and templates
150
151 @subsection infra_basic_container Container
152
153 See #DYNAMIC_ARRAY, #List, #I_P_List, #LF_HASH.
154
155 @subsection infra_basic_syncho Synchronization
156
157 See #native_mutex_t, #native_rw_lock_t, #native_cond_t.
158
159 @subsection infra_basic_fileio File IO
160
161 See #my_open, #my_dir.
162
163 @section infra_server_blocks Server building blocs
164
165 @subsection infra_server_blocks_vio Virtual Input Output
166
167 See #Vio, #vio_init.
168
169 @section deployment Deployment
170
171 @subsection deploy_install Installation
172
173 See #opt_initialize, #bootstrap::run_bootstrap_thread.
174
175 @subsection deploy_startup Startup
176
177 See #mysqld_main.
178
179 @subsection deploy_shutdown Shutdown
180
181 See #handle_fatal_signal, #signal_hand.
182
183 @subsection deploy_upgrade Upgrade
184
185 See #Mysql::Tools::Upgrade::Program.
186
187 */
188
189 /**
190 @page PAGE_PROTOCOL Client/Server Protocol
191
192 @section protocol_overview Overview
193
194 The MySQL protocol is used between MySQL Clients and a MySQL Server.
195 It is implemented by:
196 - Connectors (Connector/C, Connector/J, and so forth)
197 - MySQL Proxy
198 - Communication between master and slave replication servers
199
200 The protocol supports these features:
201 - Transparent encryption using SSL
202 - Transparent compression
203 - A @ref page_protocol_connection_phase where capabilities and
204 authentication data are exchanged
205 - A @ref page_protocol_command_phase which accepts commands
206 from the client and executes them
207
208 Further reading:
209 - @subpage page_protocol_basics
210 - @subpage page_protocol_connection_lifecycle
211 */
212
213
214 /** @page mysqlx_protocol X %Protocol
215
216 @par Topics in this section:
217
218 - @subpage mysqlx_protocol_lifecycle
219 - @subpage mysqlx_protocol_authentication
220 - @subpage mysqlx_protocol_messages
221 - @subpage mysqlx_protocol_expectations
222 - @subpage mysqlx_protocol_notices
223 - @subpage mysqlx_protocol_xplugin
224 - @subpage mysqlx_protocol_use_cases
225 - @subpage mysqlx_protocol_implementation
226 - @subpage mysqlx_protocol_comparison
227
228
229 The X %Protocol is implemented by the X Plugin and the following
230 MySQL clients support the protocol:
231
232 - MYSQLXSHELL
233
234 - MySQL for Visual Studio 2.0.2 or higher
235
236 - MySQL Connector/J 6.0.2 or higher
237
238 - MySQL Connector/Net 7.0.2 or higher
239
240 - MySQL Connector/Node.js
241
242 @section xprotocol_community_connector How to build a Community Connector
243
244 MySQL provides a set of official MySQL Connectors for several popular
245 development frameworks and languages like Node.js, .Net, Python, Java, C,
246 C++ and more. At the same time, we also encourage community developers to
247 create native connectors for their favorite languages. To improve the process
248 and encourage creating a community connector going forward, and allow for more
249 rapid new feature support within the MySQL communications protocol, we created
250 a new protocol called the MySQL X Protocol.
251
252 The new X Protocol leverages current industry standards. One of those standards
253 in use is protobuf (more formally know as Google Protobuffers).
254 The .proto formatted files provide the complete message definitions of the
255 X Protocol. Another feature of protobuf is the automatic code generation based
256 on those .proto files across a variety of languages for use in community
257 developed connectors for MySQL.
258
259 These language specific generated files can be used with no restrictions under
260 your own terms.
261
262 The X Protocol use of .proto makes our protocol design clear and concise,
263 no longer requiring the efforts previously required – no longer will you need
264 to directly analyze our message format. In addition to the layout of
265 the message format, the .proto also defines and documents message sequence
266 and flow between the connectors and the MySQL server. The information defined
267 in the .proto file makes it easy to implement X protocol support in connector
268 code. As those who have written a MySQL connector know, coding the protocol
269 is only a small part of the effort required.
270
271 Finally, you can focus on the big task of creating a MySQL community
272 connector - designing apis, coding, testing, selecting your license, packaging,
273 documentation. And, promoting and speaking about your work.
274
275 @section xprotocol_mysqlxshell_example X Protocol example
276
277 The following figure shows usage of the X %Protocol between MYSQLXSHELL and
278 MySQL Server 5.7.12 or higher with the X %Plugin enabled.
279 The object _X %Protocol_ on this figure represents rather some concept
280 than an implementation object. The aim is to show its role in the process
281 of information exchange between the client and the server.
282
283 @startuml "X Protocol Overview"
284 actor "User"
285 box "MySQLx Shell"
286 participant "X DevAPI" as devapi
287 participant "X Protocol" as xclproto
288 end box
289
290 box "MySQL Server"
291 participant "X Plugin" as xpl
292 participant "X Protocol" as xplproto
293 participant "Server" as serv
294 end box
295
296 User -> devapi: Request
297 activate devapi
298 devapi -> xclproto: Encode request
299 activate xclproto
300
301 xclproto --> devapi
302 deactivate xclproto
303
304 devapi -> xpl: Receive request << Network (TCP) >>
305 activate xpl
306
307 xpl -> xplproto: Decode request
308 activate xplproto
309
310 xplproto --> xpl
311 deactivate xplproto
312
313 xpl -> serv: Execute request
314 activate serv
315
316 serv --> xpl
317 deactivate serv
318
319 xpl --> devapi: << Network (TCP) >>
320 deactivate xpl
321
322 devapi --> User
323 deactivate devapi
324 ...
325 @enduml
326
327 The documentation is based on the source files such as:
328
329 - [``mysqlx.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx.proto)
330 - [``mysqlx_connection.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_connection.proto)
331 - [``mysqlx_session.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_session.proto>)
332 - [``mysqlx_crud.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_crud.proto>)
333 - [``mysqlx_sql.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_sql.proto>)
334 - [``mysqlx_resultset.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_resultset.proto>)
335 - [``mysqlx_expr.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_expr.proto>)
336 - [``mysqlx_datatypes.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_datatypes.proto>)
337 - [``mysqlx_expect.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_expect.proto>)
338 - [``mysqlx_notice.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_notice.proto>)
339
340 */
341
342
343 /**
344 @page PAGE_SQL_EXECUTION SQL Query Execution
345
346 @section sql_query_exec_parsing SQL Parsing
347
348 The parser processes SQL strings and builds a tree representation of them.
349
350 See @ref GROUP_PARSER.
351
352 @subpage PAGE_SQL_Optimizer
353
354 @subpage stored_programs
355
356 @section sql_query_exec_prepared Prepared statements
357
358 See #mysql_stmt_prepare
359
360 @section func_stored_proc Stored procedures
361
362 See #sp_head, #sp_instr.
363
364 @section sql_query_exec_sql_functions SQL Functions
365
366 See #Item_func
367
368 @section sql_query_exec_error_handling Error handling
369
370 See #my_message, #my_error
371
372 @subpage PAGE_TXN
373
374 */
375
376 /**
377 @page PAGE_STORAGE Data Storage
378
379 @section storage_innodb Innodb
380
381 See #ha_innobase or read details about InnoDB internals:
382 - @subpage PAGE_INNODB_PFS
383 - @subpage PAGE_INNODB_REDO_LOG
384 - @subpage PAGE_INNODB_LOCK_SYS
385 - @subpage PAGE_INNODB_UTILS
386
387 @section storage_temptable Temp table
388
389 Before 8.0, temporary tables were handled by heap engine.
390 The heap engine had no feature to store bigger tables on disk.
391
392 Since 8.0, there is a brand new temptable engine, which
393 is written from scratch using c++11. It has following advantages:
394 - it is able to store bigger tables on disk (in temporary files),
395 - it uses row format with variable size (can save memory for varchars),
396 - it is better designed (easier to maintain).
397
398 @subpage PAGE_TEMPTABLE
399
400 */
401
402
403 /**
404 @page PAGE_REPLICATION Replication
405
406 @subpage PAGE_RPL_FIELD_METADATA
407
408 */
409
410 /**
411 @page PAGE_TXN Transactions
412
413 See #trans_begin, #trans_commit, #trans_rollback.
414 */
415
416 /**
417 @page PAGE_SECURITY Security
418
419 @subpage AUTHORIZATION_PAGE
420 */
421
422
423 /**
424 @page PAGE_MONITORING Monitoring
425
426 @subpage PAGE_PFS
427 */
428
429 /**
430 @page PAGE_EXTENDING Extending MySQL
431
432 Components
433 ----------
434
435 MySQL 8.0 introduces support for extending the server through components.
436 Components can communicate with other components through service APIs.
437 And can provide implementations of service APIs for other components to use.
438 All components are equal and can communicate with all other components.
439 Service implementations can be found by name via a registry service handle
440 which is passed to the component initialization function.
441 There can be multiple service API implementations for a single service API.
442 One of them is the default implementation.
443 Service API are stateless by definition. If they need to handle state or
444 object instances they need to do so by using factory methods and instance
445 handles.
446
447 To ease up transition to the component model the current server
448 functionality (server proper and plugins) is contained within
449 a dedicated built in server component. The server component currently
450 contains all of the functionality provided by the server and
451 classical server plugins.
452
453 More components can be installed via the "INSTALL COMPONENT" SQL command.
454
455 The component infrastructure is designed as a replacement for the classical
456 MySQL plugin system as it does not suffer from some of the limitations of it
457 and provides better isolation for the component code.
458
459 See @subpage PAGE_COMPONENTS.
460
461 Plugins and Services
462 --------------------
463
464 As of MySQL 5.1 the server functionality can be extended through
465 installing (dynamically or statically linked) extra code modules
466 called plugins.
467
468 The server defines a set of well known plugin APIs that the modules
469 can implement.
470
471 To allow plugins to reuse server code the server exposes a pre-defined
472 set of functions to plugins called plugin services.
473
474 See the following for more details:
475 - @subpage page_ext_plugins
476 - @subpage page_ext_plugin_services
477
478
479 User Defined Functions
480 ----------------------
481
482 Native code user defined functions can be added to MySQL server using
483 the CREATE FUNCTION ... SONAME syntax.
484
485 These can co-exit with @ref page_ext_plugins or reside in their own
486 separate binaries.
487
488 To learn how to create these user defined functions see @subpage page_ext_udf
489 */
490
491
492 /**
493 @page PAGE_SERVER_TOOLS Server tools
494
495 - @subpage PAGE_MYSQL_ROUTER
496 */
497
498
499 /**
500 @page PAGE_CLIENT_TOOLS Client tools
501
502 See mysqldump.cc mysql.cc
503 */
504
505
506 /**
507 @page PAGE_TESTING_TOOLS Testing Tools
508
509 - @subpage PAGE_MYSQL_TEST_RUN
510 */
511
512 /**
513 @page PAGE_DEV_TOOLS Development Tools
514
515 - @subpage PAGE_LOCK_ORDER
516 */
517
518 /**
519 @page PAGE_CODE_PATHS Code paths
520
521 This section details how the server executes some statements,
522 to illustrate how different parts work together.
523
524 Note that this overall view might take some shortcuts,
525 hiding some details or taking liberties with the notations,
526 to present the whole code structure in a comprehensible way.
527
528 - @subpage CODE_PATH_CREATE_TABLE
529 */
530
531 /**
532 @page CODE_PATH_CREATE_TABLE CREATE TABLE
533
534 @section CREATE_TABLE_PARSER Parser
535
536 @startuml
537
538 actor ddl as "CREATE TABLE Query"
539 participant server as "MySQL Server"
540 participant parser as "SQL Parser"
541 participant bison as "Bison Parser"
542 participant lexer as "Lexical Scanner"
543 participant pt as "Parse Tree Nodes"
544
545 ddl -> server : DDL QUERY TEXT
546 server -> parser : THD::sql_parser()
547 == Bison parser ==
548 parser -> bison : MYSQLparse()
549 bison -> lexer : MYSQLlex()
550 bison <-- lexer : yylval, yylloc
551 bison -> pt : new
552 activate pt
553 parser <-- pt : Abstract Syntax Tree
554
555 @enduml
556
557 When a query is sent to the server,
558 the first step is to invoke the bison parser
559 to build an Abstract Syntax Tree to represent the query text.
560
561 Assume the following statement:
562 @verbatim
563 CREATE TABLE test.t1 (a int) ENGINE = "INNODB";
564 @endverbatim
565
566 In the bison grammar file, the rule implementing the CREATE TABLE
567 statement is @c create_table_stmt.
568
569 The tree created is an object of class @ref PT_create_table_stmt.
570
571 This parse tree node has several related nodes, such as:
572 - @ref PT_create_table_option and sub classes, for table options.
573 - @ref PT_table_element and sub classes, for the columns, indexes, etc.
574
575 The collection of nodes returned after the bison parsing is known
576 as the "Abstract Syntax Tree" that represents a SQL query.
577
578 @section CREATE_TABLE_CMD Sql command
579
580 @startuml
581
582 actor ddl as "CREATE TABLE Query"
583 participant server as "MySQL Server"
584 participant parser as "SQL Parser"
585 participant ast as "Abstract Syntax Tree"
586 participant cmd as "SQL Command"
587 participant ci as "HA_CREATE_INFO"
588 participant plugin as "MySQL plugin"
589
590 ddl -> server : DDL QUERY TEXT
591 server -> parser : THD::sql_parser()
592 == Bison parser ==
593 == Build SQL command ==
594 parser -> ast : make_cmd()
595 ast -> ast : contextualize()
596 ast -> ci : build()
597 activate ci
598 ci -> plugin : ha_resolve_engine()
599 ci <-- plugin : storage engine handlerton
600 ast <-- ci : Parse Tree (contextualized)
601 ast -> cmd : build()
602 activate cmd
603 server <-- cmd : SQL Command
604
605 @enduml
606
607 Once the bison parser has finished parsing a query text,
608 the next step is to build a SQL command from the Abstract Syntax Tree.
609
610 In the Abstract Syntax Tree, attributes like a storage engine name
611 ("INNODB") are represented as strings, taken from the query text.
612
613 These attributes need to be converted to objects in the SQL context,
614 such as an @ref innodb_hton pointer to represent the INNODB storage engine.
615
616 The process that performs these transformations is contextualize().
617
618 The @ref Parse_tree_root class is an abstract factory, building @ref Sql_cmd
619 objects.
620
621 For a CREATE TABLE statement, class @ref PT_create_table_stmt builds a
622 concrete @ref Sql_cmd_create_table object.
623
624 @ref PT_create_table_stmt::make_cmd() in particular performs the following
625 actions:
626 - contextualize the parse tree for the CREATE TABLE statement.
627 - build a @ref HA_CREATE_INFO structure to represent the table DDL.
628 - resolve the storage engine name to an actual @ref handlerton pointer,
629 in @ref PT_create_table_engine_option::contextualize()
630
631 @section CREATE_TABLE_RUNTIME Runtime execution
632
633 @startuml
634
635 actor ddl as "CREATE TABLE Query"
636 participant server as "MySQL Server"
637 participant cmd as "SQL Command"
638 participant rt as "Runtime"
639
640 ddl -> server : DDL QUERY TEXT
641 == Bison parser ==
642 == Build SQL command ==
643 == Execute SQL command ==
644 server -> cmd : execute()
645 cmd -> rt : mysql_create_table()
646
647 @enduml
648
649 Execution of a CREATE TABLE statement invokes
650 @ref Sql_cmd_create_table::execute(),
651 which in turns calls:
652 - @ref mysql_create_table(),
653 - @ref mysql_create_table_no_lock(),
654 - @ref create_table_impl(),
655 - @ref rea_create_base_table().
656
657 Execution of this code is the runtime implementation of the CREATE TABLE
658 statement, and eventually leads to:
659 - @ref dd::create_table(), to create the table in the Data Dictionary,
660 - @ref ha_create_table(), to create the table in the handlerton.
661
662 Details about the dictionary and the storage engine are expanded
663 in the following two sections.
664
665
666 @section CREATE_TABLE_DD Data Dictionary
667
668 @startuml
669
670 actor ddl as "CREATE TABLE Query"
671 participant server as "MySQL Server"
672 participant rt as "Runtime"
673 participant dd as "Data Dictionary"
674 participant ddt as "Data Dictionary Table"
675 participant sdi as "Serialized Dictionary Information"
676 participant hton as "Handlerton"
677 participant se as "Storage Engine"
678 participant ts as "Tablespace"
679
680 ddl -> server : DDL QUERY TEXT
681 == ... ==
682 server -> rt : ( execution code path )
683 == Data Dictionary ==
684 rt -> dd : dd::create_table()
685 dd -> ddt : build dd::Table()
686 activate ddt
687 rt <-- ddt : dd:Table instance
688 == Serialized Dictionary Information ==
689 rt -> dd : store()
690 dd -> sdi : dd::sdi::store()
691 sdi -> sdi : sdi_tablespace::store_tbl_sdi()
692 == Storage Engine (Tablespace) ==
693 sdi -> hton : handlerton::sdi()
694 hton -> se : ::sdi() implementation.
695 se -> ts : write metadata in tablespace
696
697 @enduml
698
699 In the data dictionary, creation of a new table calls:
700 - @ref dd::create_dd_user_table()
701 - @ref fill_dd_table_from_create_info()
702
703 The data dictionary code parses the content of the HA_CREATE_INFO
704 input, and builds a @ref dd::Table object, to represent the table metadata.
705 Part of this metadata includes the storage engine name.
706
707 The runtime code then calls @c store() to save this new metadata.
708
709 To store a table metadata, the data dictionary code first serialize it
710 into an sdi format.
711
712 The serialized object is then stored in persistence,
713 either in a tablespace or in a file:
714 - @ref sdi_tablespace::store_tbl_sdi()
715 - @ref sfi_file::store_tbl_sdi()
716
717 When storing data into a tablespace, the storage engine handlerton is
718 invoked, so that the storage engine can ultimately store
719 the table metadata in the tablespace maintained by the storage engine.
720
721 @section CREATE_TABLE_SE Storage Engine
722
723 @startuml
724
725 actor ddl as "CREATE TABLE Query"
726 participant server as "MySQL Server"
727 participant rt as "Runtime"
728 participant sei as "Storage Engine Interface"
729 participant hton as "Storage Engine Handlerton"
730 participant handler as "Storage Engine Handler"
731
732 ddl -> server : DDL QUERY TEXT
733 == ... ==
734 server -> rt : ( execution code path )
735 == Storage Engine (table) ==
736 rt -> sei : ha_create_table()
737 sei -> hton : handlerton::create()
738 hton -> handler : (build a new table handler)
739 activate handler
740 sei <-- handler : storage engine table handler
741 sei -> handler : handler::create()
742
743 @enduml
744
745 When execution of the CREATE TABLE statement
746 reaches the storage engine interface,
747 the SQL layer function @ref ha_create_table()
748 invokes the storage engine @ref handlerton::create()
749 method to instantiate a new storage engine table,
750 represented by @ref handler.
751 The SQL layer then calls @ref handler::create() to create
752 the table inside the storage engine.
753 */
754
755 /**
756 @page PAGE_SQL_Optimizer SQL Optimizer
757
758 The task of query optimizer is to determine the most efficient means for
759 executing queries. The query optimizer consists of the following
760 sub-modules:
761
762 - @ref Query_Resolver
763 - @ref Query_Optimizer
764 - @ref Query_Planner
765 - @ref Query_Executor
766
767 @subpage PAGE_OPT_TRACE
768
769 Additional articles about the query optimizer:
770
771 - @ref PAGE_OPT_TRACE
772 - @ref AGGREGATE_CHECKS
773 */
774 /* clang-format on */
775
776 #include "sql/mysqld.h"
777
778 #include "my_config.h"
779
780 #include "errmsg.h" // init_client_errs
781 #include "ft_global.h"
782 #include "keycache.h" // KEY_CACHE
783 #include "libbinlogevents/include/binlog_event.h"
784 #include "libbinlogevents/include/control_events.h"
785 #include "m_string.h"
786 #include "migrate_keyring.h" // Migrate_keyring
787 #include "my_alloc.h"
788 #include "my_base.h"
789 #include "my_bitmap.h" // MY_BITMAP
790 #include "my_command.h"
791 #include "my_dbug.h"
792 #include "my_default.h" // print_defaults
793 #include "my_dir.h"
794 #include "my_getpwnam.h"
795 #include "my_loglevel.h"
796 #include "my_macros.h"
797 #include "my_shm_defaults.h" // IWYU pragma: keep
798 #include "my_stacktrace.h" // my_set_exception_pointers
799 #include "my_thread_local.h"
800 #include "my_time.h"
801 #include "my_timer.h" // my_timer_initialize
802 #include "myisam.h"
803 #include "mysql/components/services/log_builtins.h"
804 #include "mysql/components/services/log_shared.h"
805 #include "mysql/components/services/mysql_runtime_error_service.h"
806 #include "mysql/plugin.h"
807 #include "mysql/plugin_audit.h"
808 #include "mysql/psi/mysql_cond.h"
809 #include "mysql/psi/mysql_file.h"
810 #include "mysql/psi/mysql_memory.h" // mysql_memory_init
811 #include "mysql/psi/mysql_mutex.h"
812 #include "mysql/psi/mysql_rwlock.h"
813 #include "mysql/psi/mysql_socket.h"
814 #include "mysql/psi/mysql_stage.h"
815 #include "mysql/psi/mysql_statement.h"
816 #include "mysql/psi/mysql_thread.h"
817 #include "mysql/psi/psi_base.h"
818 #include "mysql/psi/psi_cond.h"
819 #include "mysql/psi/psi_data_lock.h"
820 #include "mysql/psi/psi_error.h"
821 #include "mysql/psi/psi_file.h"
822 #include "mysql/psi/psi_idle.h"
823 #include "mysql/psi/psi_mdl.h"
824 #include "mysql/psi/psi_memory.h"
825 #include "mysql/psi/psi_mutex.h"
826 #include "mysql/psi/psi_rwlock.h"
827 #include "mysql/psi/psi_socket.h"
828 #include "mysql/psi/psi_stage.h"
829 #include "mysql/psi/psi_statement.h"
830 #include "mysql/psi/psi_system.h"
831 #include "mysql/psi/psi_table.h"
832 #include "mysql/psi/psi_thread.h"
833 #include "mysql/psi/psi_tls_channel.h"
834 #include "mysql/psi/psi_transaction.h"
835 #include "mysql/service_mysql_alloc.h"
836 #include "mysql/thread_type.h"
837 #include "mysql_com.h"
838 #include "mysql_time.h"
839 #include "mysql_version.h"
840 #include "mysqld_error.h"
841 #include "mysys_err.h" // EXIT_OUT_OF_MEMORY
842 #include "pfs_thread_provider.h"
843 #include "print_version.h"
844 #ifdef _WIN32
845 #include <shellapi.h>
846 #endif
847 #include "sql/auth/auth_common.h" // grant_init
848 #include "sql/auth/sql_authentication.h" // init_rsa_keys
849 #include "sql/auth/sql_security_ctx.h"
850 #include "sql/auto_thd.h" // Auto_THD
851 #include "sql/binlog.h" // mysql_bin_log
852 #include "sql/bootstrap.h" // bootstrap
853 #include "sql/check_stack.h"
854 #include "sql/conn_handler/connection_acceptor.h" // Connection_acceptor
855 #include "sql/conn_handler/connection_handler_impl.h" // Per_thread_connection_handler
856 #include "sql/conn_handler/connection_handler_manager.h" // Connection_handler_manager
857 #include "sql/conn_handler/socket_connection.h" // stmt_info_new_packet
858 #include "sql/current_thd.h" // current_thd
859 #include "sql/dd/cache/dictionary_client.h"
860 #include "sql/debug_sync.h" // debug_sync_end
861 #include "sql/derror.h"
862 #include "sql/event_data_objects.h" // init_scheduler_psi_keys
863 #include "sql/events.h" // Events
864 #include "sql/handler.h"
865 #include "sql/hostname_cache.h" // hostname_cache_init
866 #include "sql/init.h" // unireg_init
867 #include "sql/item.h"
868 #include "sql/item_cmpfunc.h" // Arg_comparator
869 #include "sql/item_create.h"
870 #include "sql/item_func.h"
871 #include "sql/item_strfunc.h" // Item_func_uuid
872 #include "sql/keycaches.h" // get_or_create_key_cache
873 #include "sql/log.h"
874 #include "sql/log_event.h" // Rows_log_event
875 #include "sql/log_resource.h"
876 #include "sql/mdl.h"
877 #include "sql/mdl_context_backup.h" // mdl_context_backup_manager
878 #include "sql/my_decimal.h"
879 #include "sql/mysqld_daemon.h"
880 #include "sql/mysqld_thd_manager.h" // Global_THD_manager
881 #include "sql/opt_costconstantcache.h" // delete_optimizer_cost_module
882 #include "sql/opt_range.h" // range_optimizer_init
883 #include "sql/options_mysqld.h" // OPT_THREAD_CACHE_SIZE
884 #include "sql/partitioning/partition_handler.h" // partitioning_init
885 #include "sql/persisted_variable.h" // Persisted_variables_cache
886 #include "sql/plugin_table.h"
887 #include "sql/protocol.h"
888 #include "sql/psi_memory_key.h" // key_memory_MYSQL_RELAY_LOG_index
889 #include "sql/query_options.h"
890 #include "sql/replication.h" // thd_enter_cond
891 #include "sql/resourcegroups/resource_group_mgr.h" // init, post_init
892 #ifdef _WIN32
893 #include "sql/restart_monitor_win.h"
894 #endif
895 #include "sql/rpl_filter.h"
896 #include "sql/rpl_gtid.h"
897 #include "sql/rpl_gtid_persist.h" // Gtid_table_persistor
898 #include "sql/rpl_handler.h" // RUN_HOOK
899 #include "sql/rpl_info_factory.h"
900 #include "sql/rpl_info_handler.h"
901 #include "sql/rpl_injector.h" // injector
902 #include "sql/rpl_log_encryption.h"
903 #include "sql/rpl_master.h" // max_binlog_dump_events
904 #include "sql/rpl_mi.h"
905 #include "sql/rpl_msr.h" // Multisource_info
906 #include "sql/rpl_rli.h" // Relay_log_info
907 #include "sql/rpl_slave.h" // slave_load_tmpdir
908 #include "sql/rpl_trx_tracking.h"
909 #include "sql/sd_notify.h" // sd_notify_connect
910 #include "sql/session_tracker.h"
911 #include "sql/set_var.h"
912 #include "sql/sp_head.h" // init_sp_psi_keys
913 #include "sql/sql_audit.h" // mysql_audit_general
914 #include "sql/sql_base.h"
915 #include "sql/sql_callback.h" // MUSQL_CALLBACK
916 #include "sql/sql_class.h" // THD
917 #include "sql/sql_connect.h"
918 #include "sql/sql_error.h"
919 #include "sql/sql_initialize.h" // opt_initialize_insecure
920 #include "sql/sql_lex.h"
921 #include "sql/sql_list.h"
922 #include "sql/sql_locale.h" // MY_LOCALE
923 #include "sql/sql_manager.h" // start_handle_manager
924 #include "sql/sql_parse.h" // check_stack_overrun
925 #include "sql/sql_plugin.h" // opt_plugin_dir
926 #include "sql/sql_plugin_ref.h"
927 #include "sql/sql_reload.h" // handle_reload_request
928 #include "sql/sql_restart_server.h" // is_mysqld_managed
929 #include "sql/sql_servers.h"
930 #include "sql/sql_show.h"
931 #include "sql/sql_table.h" // build_table_filename
932 #include "sql/sql_udf.h"
933 #include "sql/ssl_acceptor_context_iterator.h"
934 #include "sql/ssl_acceptor_context_operator.h"
935 #include "sql/ssl_acceptor_context_status.h"
936 #include "sql/ssl_init_callback.h"
937 #include "sql/sys_vars.h" // fixup_enforce_gtid_consistency_...
938 #include "sql/sys_vars_shared.h" // intern_find_sys_var
939 #include "sql/table_cache.h" // table_cache_manager
940 #include "sql/tc_log.h" // tc_log
941 #include "sql/thd_raii.h"
942 #include "sql/thr_malloc.h"
943 #include "sql/transaction.h"
944 #include "sql/tztime.h" // Time_zone
945 #include "sql/xa.h"
946 #include "sql_common.h" // mysql_client_plugin_init
947 #include "sql_string.h"
948 #include "storage/myisam/ha_myisam.h" // HA_RECOVER_OFF
949 #include "storage/perfschema/pfs_services.h"
950 #include "thr_lock.h"
951 #include "thr_mutex.h"
952 #include "typelib.h"
953 #include "violite.h"
954
955 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
956 #include "storage/perfschema/pfs_server.h"
957 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
958
959 #ifdef _WIN32
960 #include "sql/conn_handler/named_pipe_connection.h"
961 #include "sql/conn_handler/shared_memory_connection.h"
962 #include "sql/named_pipe.h"
963 #endif
964
965 #ifdef MY_MSCRT_DEBUG
966 #include <crtdbg.h>
967 #endif
968 #include <errno.h>
969 #include <fcntl.h>
970 #include <fenv.h>
971 #include <limits.h>
972 #ifdef HAVE_GRP_H
973 #include <grp.h>
974 #endif
975 #ifndef _WIN32
976 #include <netdb.h>
977 #endif
978 #ifdef HAVE_NETINET_IN_H
979 #include <netinet/in.h>
980 #endif
981 #include <signal.h>
982 #include <stdarg.h>
983 #include <stddef.h>
984 #include <stdio.h>
985 #include <stdlib.h>
986 #include <string.h>
987 #include <sys/types.h>
988 #ifdef HAVE_SYS_MMAN_H
989 #include <sys/mman.h>
990 #endif
991 #ifdef HAVE_SYS_PRCTL_H
992 #include <sys/prctl.h>
993 #endif
994 #ifdef HAVE_SYS_RESOURCE_H
995 #include <sys/resource.h>
996 #endif
997 #include <sys/stat.h>
998 #ifdef HAVE_UNISTD_H
999 #include <unistd.h>
1000 #endif
1001 #ifdef _WIN32
1002 #include <crtdbg.h>
1003 #include <process.h>
1004 #endif
1005 #include "unicode/uclean.h" // u_cleanup()
1006
1007 #include <algorithm>
1008 #include <atomic>
1009 #include <functional>
1010 #include <new>
1011 #include <string>
1012 #include <vector>
1013
1014 #ifndef EMBEDDED_LIBRARY
1015 #ifdef WITH_LOCK_ORDER
1016 #include "sql/debug_lock_order.h"
1017 #endif /* WITH_LOCK_ORDER */
1018 #endif /* EMBEDDED_LIBRARY */
1019
1020 #ifndef EMBEDDED_LIBRARY
1021 #include "srv_session.h"
1022 #endif
1023
1024 #include <mysql/components/minimal_chassis.h>
1025 #include <mysql/components/services/dynamic_loader_scheme_file.h>
1026 #include <mysql/components/services/mysql_psi_system_service.h>
1027 #include <mysql/components/services/mysql_rwlock_service.h>
1028 #include <mysql/components/services/ongoing_transaction_query_service.h>
1029 #include "sql/auth/dynamic_privileges_impl.h"
1030 #include "sql/dd/dd.h" // dd::shutdown
1031 #include "sql/dd/dd_kill_immunizer.h" // dd::DD_kill_immunizer
1032 #include "sql/dd/dictionary.h" // dd::get_dictionary
1033 #include "sql/dd/ndbinfo_schema/init.h" // dd::ndbinfo::init_schema_and_tables()
1034 #include "sql/dd/performance_schema/init.h" // performance_schema::init
1035 #include "sql/dd/upgrade/server.h" // dd::upgrade::upgrade_system_schemas
1036 #include "sql/dd/upgrade_57/upgrade.h" // dd::upgrade_57::in_progress
1037 #include "sql/server_component/component_sys_var_service_imp.h"
1038 #include "sql/server_component/log_builtins_filter_imp.h"
1039 #include "sql/server_component/log_builtins_imp.h"
1040 #include "sql/server_component/persistent_dynamic_loader_imp.h"
1041 #include "sql/srv_session.h"
1042
1043 using std::max;
1044 using std::min;
1045 using std::vector;
1046
1047 #define mysqld_charset &my_charset_latin1
1048 #define mysqld_default_locale_name "en_US"
1049
1050 #ifdef HAVE_FPU_CONTROL_H
1051 #include <fpu_control.h> // IWYU pragma: keep
1052 #elif defined(__i386__)
1053 #define fpu_control_t unsigned int
1054 #define _FPU_EXTENDED 0x300
1055 #define _FPU_DOUBLE 0x200
1056 #if defined(__GNUC__) || defined(__SUNPRO_CC)
1057 #define _FPU_GETCW(cw) asm volatile("fnstcw %0" : "=m"(*&cw))
1058 #define _FPU_SETCW(cw) asm volatile("fldcw %0" : : "m"(*&cw))
1059 #else
1060 #define _FPU_GETCW(cw) (cw = 0)
1061 #define _FPU_SETCW(cw)
1062 #endif
1063 #endif
setup_fpu()1064 inline void setup_fpu() {
1065 #ifdef HAVE_FEDISABLEEXCEPT
1066 fedisableexcept(FE_ALL_EXCEPT);
1067 #endif
1068
1069 /* Set FPU rounding mode to "round-to-nearest" */
1070 fesetround(FE_TONEAREST);
1071
1072 /*
1073 x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
1074 (double precision) for portable results of floating point operations.
1075 However, there is no need to do so if compiler is using SSE2 for floating
1076 point, double values will be stored and processed in 64 bits anyway.
1077 */
1078 #if defined(__i386__) && !defined(__SSE2_MATH__)
1079 #if !defined(_WIN32)
1080 fpu_control_t cw;
1081 _FPU_GETCW(cw);
1082 cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
1083 _FPU_SETCW(cw);
1084 #endif /* _WIN32 && */
1085 #endif /* __i386__ */
1086 }
1087
1088 extern "C" void handle_fatal_signal(int sig);
1089
1090 /* Constants */
1091
1092 #include "welcome_copyright_notice.h" // ORACLE_WELCOME_COPYRIGHT_NOTICE
1093
1094 const char *show_comp_option_name[] = {"YES", "NO", "DISABLED"};
1095
1096 static const char *tc_heuristic_recover_names[] = {"OFF", "COMMIT", "ROLLBACK",
1097 NullS};
1098 static TYPELIB tc_heuristic_recover_typelib = {
1099 array_elements(tc_heuristic_recover_names) - 1, "",
1100 tc_heuristic_recover_names, nullptr};
1101
1102 const char *first_keyword = "first", *binary_keyword = "BINARY";
1103 const char *my_localhost = "localhost";
1104
1105 bool opt_large_files = sizeof(my_off_t) > 4;
1106 static bool opt_autocommit; ///< for --autocommit command-line option
1107 static get_opt_arg_source source_autocommit;
1108
1109 /*
1110 Used with --help for detailed option
1111 */
1112 bool opt_help = false, opt_verbose = false, opt_validate_config = false;
1113
1114 arg_cmp_func Arg_comparator::comparator_matrix[5] = {
1115 &Arg_comparator::compare_string, // Compare strings
1116 &Arg_comparator::compare_real, // Compare float values
1117 &Arg_comparator::compare_int_signed, // Compare signed int values
1118 &Arg_comparator::compare_row, // Compare row values
1119 &Arg_comparator::compare_decimal}; // Compare decimal values
1120
1121 PSI_file_key key_file_binlog_cache;
1122 PSI_file_key key_file_binlog_index_cache;
1123
1124 #ifdef HAVE_PSI_INTERFACE
1125 static PSI_mutex_key key_LOCK_status;
1126 static PSI_mutex_key key_LOCK_manager;
1127 static PSI_mutex_key key_LOCK_crypt;
1128 static PSI_mutex_key key_LOCK_user_conn;
1129 static PSI_mutex_key key_LOCK_global_system_variables;
1130 static PSI_mutex_key key_LOCK_prepared_stmt_count;
1131 static PSI_mutex_key key_LOCK_sql_slave_skip_counter;
1132 static PSI_mutex_key key_LOCK_slave_net_timeout;
1133 static PSI_mutex_key key_LOCK_slave_trans_dep_tracker;
1134 static PSI_mutex_key key_LOCK_uuid_generator;
1135 static PSI_mutex_key key_LOCK_error_messages;
1136 static PSI_mutex_key key_LOCK_default_password_lifetime;
1137 static PSI_mutex_key key_LOCK_mandatory_roles;
1138 static PSI_mutex_key key_LOCK_password_history;
1139 static PSI_mutex_key key_LOCK_password_reuse_interval;
1140 static PSI_mutex_key key_LOCK_sql_rand;
1141 static PSI_mutex_key key_LOCK_log_throttle_qni;
1142 static PSI_mutex_key key_LOCK_reset_gtid_table;
1143 static PSI_mutex_key key_LOCK_compress_gtid_table;
1144 static PSI_mutex_key key_LOCK_collect_instance_log;
1145 static PSI_mutex_key key_BINLOG_LOCK_commit;
1146 static PSI_mutex_key key_BINLOG_LOCK_commit_queue;
1147 static PSI_mutex_key key_BINLOG_LOCK_done;
1148 static PSI_mutex_key key_BINLOG_LOCK_flush_queue;
1149 static PSI_mutex_key key_BINLOG_LOCK_index;
1150 static PSI_mutex_key key_BINLOG_LOCK_log;
1151 static PSI_mutex_key key_BINLOG_LOCK_binlog_end_pos;
1152 static PSI_mutex_key key_BINLOG_LOCK_sync;
1153 static PSI_mutex_key key_BINLOG_LOCK_sync_queue;
1154 static PSI_mutex_key key_BINLOG_LOCK_xids;
1155 static PSI_rwlock_key key_rwlock_global_sid_lock;
1156 PSI_rwlock_key key_rwlock_gtid_mode_lock;
1157 static PSI_rwlock_key key_rwlock_LOCK_system_variables_hash;
1158 static PSI_rwlock_key key_rwlock_LOCK_sys_init_connect;
1159 static PSI_rwlock_key key_rwlock_LOCK_sys_init_slave;
1160 static PSI_cond_key key_BINLOG_COND_done;
1161 static PSI_cond_key key_BINLOG_update_cond;
1162 static PSI_cond_key key_BINLOG_prep_xids_cond;
1163 static PSI_cond_key key_COND_manager;
1164 static PSI_cond_key key_COND_compress_gtid_table;
1165 static PSI_thread_key key_thread_signal_hand;
1166 static PSI_thread_key key_thread_main;
1167 static PSI_file_key key_file_casetest;
1168 static PSI_file_key key_file_pid;
1169 #if defined(_WIN32)
1170 static PSI_thread_key key_thread_handle_con_namedpipes;
1171 static PSI_thread_key key_thread_handle_con_sharedmem;
1172 static PSI_thread_key key_thread_handle_con_sockets;
1173 static PSI_mutex_key key_LOCK_handler_count;
1174 static PSI_cond_key key_COND_handler_count;
1175 static PSI_thread_key key_thread_handle_shutdown_restart;
1176 static PSI_rwlock_key key_rwlock_LOCK_named_pipe_full_access_group;
1177 #else
1178 static PSI_mutex_key key_LOCK_socket_listener_active;
1179 static PSI_cond_key key_COND_socket_listener_active;
1180 static PSI_mutex_key key_LOCK_start_signal_handler;
1181 static PSI_cond_key key_COND_start_signal_handler;
1182 #endif // _WIN32
1183 static PSI_mutex_key key_LOCK_server_started;
1184 static PSI_cond_key key_COND_server_started;
1185 static PSI_mutex_key key_LOCK_keyring_operations;
1186 static PSI_mutex_key key_LOCK_tls_ctx_options;
1187 static PSI_mutex_key key_LOCK_admin_tls_ctx_options;
1188 static PSI_mutex_key key_LOCK_rotate_binlog_master_key;
1189 #endif /* HAVE_PSI_INTERFACE */
1190
1191 /**
1192 Statement instrumentation key for replication.
1193 */
1194 #ifdef HAVE_PSI_STATEMENT_INTERFACE
1195 PSI_statement_info stmt_info_rpl;
1196 #endif
1197
1198 /* the default log output is log tables */
1199 static bool lower_case_table_names_used = false;
1200 #if !defined(_WIN32)
1201 static bool socket_listener_active = false;
1202 static int pipe_write_fd = -1;
1203 static bool opt_daemonize = false;
1204 #endif
1205 bool opt_debugging = false;
1206 static bool opt_external_locking = false, opt_console = false;
1207 static bool opt_short_log_format = false;
1208 static char *mysqld_user, *mysqld_chroot;
1209 static const char *default_character_set_name;
1210 static const char *character_set_filesystem_name;
1211 static const char *lc_messages;
1212 static const char *lc_time_names_name;
1213 char *my_bind_addr_str;
1214 char *my_admin_bind_addr_str;
1215 uint mysqld_admin_port;
1216 bool listen_admin_interface_in_separate_thread;
1217 static const char *default_collation_name;
1218 const char *default_storage_engine;
1219 const char *default_tmp_storage_engine;
1220 ulonglong temptable_max_ram;
1221 bool temptable_use_mmap;
1222 static char compiled_default_collation_name[] = MYSQL_DEFAULT_COLLATION_NAME;
1223 static bool binlog_format_used = false;
1224
1225 LEX_STRING opt_init_connect, opt_init_slave;
1226
1227 /* Global variables */
1228
1229 LEX_STRING opt_mandatory_roles;
1230 bool opt_mandatory_roles_cache = false;
1231 bool opt_always_activate_granted_roles = false;
1232 bool opt_bin_log;
1233 bool opt_general_log, opt_slow_log, opt_general_log_raw;
1234 ulonglong log_output_options;
1235 bool opt_log_queries_not_using_indexes = false;
1236 ulong opt_log_throttle_queries_not_using_indexes = 0;
1237 bool opt_log_slow_extra = false;
1238 bool opt_disable_networking = false, opt_skip_show_db = false;
1239 bool opt_skip_name_resolve = false;
1240 bool opt_character_set_client_handshake = true;
1241 bool server_id_supplied = false;
1242 static bool opt_endinfo;
1243 bool using_udf_functions;
1244 bool locked_in_memory;
1245 bool opt_using_transactions;
1246 ulong opt_tc_log_size;
1247 std::atomic<int32> connection_events_loop_aborted_flag;
1248 static std::atomic<enum_server_operational_state> server_operational_state{
1249 SERVER_BOOTING};
1250 char *opt_log_error_suppression_list;
1251 char *opt_log_error_services;
1252 char *opt_keyring_migration_user = nullptr;
1253 char *opt_keyring_migration_host = nullptr;
1254 char *opt_keyring_migration_password = nullptr;
1255 char *opt_keyring_migration_socket = nullptr;
1256 char *opt_keyring_migration_source = nullptr;
1257 char *opt_keyring_migration_destination = nullptr;
1258 ulong opt_keyring_migration_port = 0;
1259 bool migrate_connect_options = false;
1260 uint host_cache_size;
1261 ulong log_error_verbosity = 3; // have a non-zero value during early start-up
1262
1263 #if defined(_WIN32)
1264 /*
1265 Thread handle of shutdown event handler thread.
1266 It is used as argument during thread join.
1267 */
1268 my_thread_handle shutdown_restart_thr_handle;
1269
1270 ulong slow_start_timeout;
1271 bool opt_no_monitor = false;
1272 #endif
1273
1274 bool opt_no_dd_upgrade = false;
1275 long opt_upgrade_mode = UPGRADE_AUTO;
1276 bool opt_initialize = false;
1277 bool opt_skip_slave_start = false; ///< If set, slave is not autostarted
1278 bool opt_enable_named_pipe = false;
1279 bool opt_local_infile, opt_slave_compressed_protocol;
1280 bool opt_safe_user_create = false;
1281 bool opt_show_slave_auth_info;
1282 bool opt_log_slave_updates = false;
1283 char *opt_slave_skip_errors;
1284 bool opt_slave_allow_batching = false;
1285
1286 /**
1287 compatibility option:
1288 - index usage hints (USE INDEX without a FOR clause) behave as in 5.0
1289 */
1290 bool old_mode;
1291
1292 /*
1293 Legacy global handlerton. These will be removed (please do not add more).
1294 */
1295 handlerton *heap_hton;
1296 handlerton *temptable_hton;
1297 handlerton *myisam_hton;
1298 handlerton *innodb_hton;
1299
1300 char *opt_disabled_storage_engines;
1301 uint opt_server_id_bits = 0;
1302 ulong opt_server_id_mask = 0;
1303 bool read_only = false, opt_readonly = false;
1304 bool super_read_only = false, opt_super_readonly = false;
1305 bool opt_require_secure_transport = false;
1306 bool relay_log_purge;
1307 bool relay_log_recovery;
1308 bool opt_allow_suspicious_udfs;
1309 const char *opt_secure_file_priv;
1310 bool opt_log_slow_admin_statements = false;
1311 bool opt_log_slow_slave_statements = false;
1312 bool lower_case_file_system = false;
1313 bool opt_large_pages = false;
1314 bool opt_super_large_pages = false;
1315 bool opt_myisam_use_mmap = false;
1316 std::atomic<bool> offline_mode;
1317 uint opt_large_page_size = 0;
1318 uint default_password_lifetime = 0;
1319 bool password_require_current = false;
1320 std::atomic<bool> partial_revokes;
1321 bool opt_partial_revokes;
1322
1323 mysql_mutex_t LOCK_default_password_lifetime;
1324 mysql_mutex_t LOCK_mandatory_roles;
1325 mysql_mutex_t LOCK_password_history;
1326 mysql_mutex_t LOCK_password_reuse_interval;
1327 mysql_mutex_t LOCK_tls_ctx_options;
1328 mysql_mutex_t LOCK_admin_tls_ctx_options;
1329
1330 #if defined(ENABLED_DEBUG_SYNC)
1331 MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout = 0;
1332 #endif /* defined(ENABLED_DEBUG_SYNC) */
1333 bool opt_old_style_user_limits = false, trust_function_creators = false;
1334 bool check_proxy_users = false, mysql_native_password_proxy_users = false,
1335 sha256_password_proxy_users = false;
1336 /*
1337 True if there is at least one per-hour limit for some user, so we should
1338 check them before each query (and possibly reset counters when hour is
1339 changed). False otherwise.
1340 */
1341 volatile bool mqh_used = false;
1342 bool opt_noacl = false;
1343 bool sp_automatic_privileges = true;
1344
1345 int32_t opt_regexp_time_limit;
1346 int32_t opt_regexp_stack_limit;
1347
1348 /** True, if restarted from a cloned database. This information
1349 is needed by GR to set some configurations right after clone. */
1350 bool clone_startup = false;
1351
1352 /** True, if clone recovery has failed. For managed server we
1353 restart server again with old databse files. */
1354 bool clone_recovery_error = false;
1355
1356 ulong binlog_row_event_max_size;
1357 ulong binlog_checksum_options;
1358 ulong binlog_row_metadata;
1359 bool opt_master_verify_checksum = false;
1360 bool opt_slave_sql_verify_checksum = true;
1361 const char *binlog_format_names[] = {"MIXED", "STATEMENT", "ROW", NullS};
1362 bool binlog_gtid_simple_recovery;
1363 ulong binlog_error_action;
1364 const char *binlog_error_action_list[] = {"IGNORE_ERROR", "ABORT_SERVER",
1365 NullS};
1366 uint32 gtid_executed_compression_period = 0;
1367 bool opt_log_unsafe_statements;
1368
1369 const char *timestamp_type_names[] = {"UTC", "SYSTEM", NullS};
1370 ulong opt_log_timestamps;
1371 uint mysqld_port, test_flags, select_errors, ha_open_options;
1372 uint mysqld_port_timeout;
1373 ulong delay_key_write_options;
1374 uint protocol_version;
1375 uint lower_case_table_names;
1376 long tc_heuristic_recover;
1377 ulong back_log, connect_timeout, server_id;
1378 ulong table_cache_size;
1379 ulong table_cache_instances;
1380 ulong table_cache_size_per_instance;
1381 ulong schema_def_size;
1382 ulong stored_program_def_size;
1383 ulong table_def_size;
1384 ulong tablespace_def_size;
1385 ulong what_to_log;
1386 ulong slow_launch_time;
1387 std::atomic<int32> atomic_slave_open_temp_tables{0};
1388 ulong open_files_limit, max_binlog_size, max_relay_log_size;
1389 ulong slave_trans_retries;
1390 uint slave_net_timeout;
1391 ulong slave_exec_mode_options;
1392 ulonglong slave_type_conversions_options;
1393 ulong opt_mts_slave_parallel_workers;
1394 ulonglong opt_mts_pending_jobs_size_max;
1395 ulonglong slave_rows_search_algorithms_options;
1396 bool opt_slave_preserve_commit_order;
1397 #ifndef DBUG_OFF
1398 uint slave_rows_last_search_algorithm_used;
1399 #endif
1400 ulong mts_parallel_option;
1401 ulong binlog_cache_size = 0;
1402 ulonglong max_binlog_cache_size = 0;
1403 ulong slave_max_allowed_packet = 0;
1404 ulong binlog_stmt_cache_size = 0;
1405 int32 opt_binlog_max_flush_queue_time = 0;
1406 long opt_binlog_group_commit_sync_delay = 0;
1407 ulong opt_binlog_group_commit_sync_no_delay_count = 0;
1408 ulonglong max_binlog_stmt_cache_size = 0;
1409 ulong refresh_version; /* Increments on each reload */
1410 std::atomic<query_id_t> atomic_global_query_id{1};
1411 ulong aborted_threads;
1412 ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
1413 ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
1414 ulong delayed_insert_errors, flush_time;
1415 ulong specialflag = 0;
1416 ulong binlog_cache_use = 0, binlog_cache_disk_use = 0;
1417 ulong binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0;
1418 ulong max_connections, max_connect_errors;
1419 ulong rpl_stop_slave_timeout = LONG_TIMEOUT;
1420 bool log_bin_use_v1_row_events = false;
1421 bool thread_cache_size_specified = false;
1422 bool host_cache_size_specified = false;
1423 bool table_definition_cache_specified = false;
1424 ulong locked_account_connection_count = 0;
1425
1426 /**
1427 Limit of the total number of prepared statements in the server.
1428 Is necessary to protect the server against out-of-memory attacks.
1429 */
1430 ulong max_prepared_stmt_count;
1431 /**
1432 Current total number of prepared statements in the server. This number
1433 is exact, and therefore may not be equal to the difference between
1434 `com_stmt_prepare' and `com_stmt_close' (global status variables), as
1435 the latter ones account for all registered attempts to prepare
1436 a statement (including unsuccessful ones). Prepared statements are
1437 currently connection-local: if the same SQL query text is prepared in
1438 two different connections, this counts as two distinct prepared
1439 statements.
1440 */
1441 ulong prepared_stmt_count = 0;
1442 ulong current_pid;
1443 uint sync_binlog_period = 0, sync_relaylog_period = 0,
1444 sync_relayloginfo_period = 0, sync_masterinfo_period = 0,
1445 opt_mts_checkpoint_period, opt_mts_checkpoint_group;
1446 ulong expire_logs_days = 0;
1447 ulong binlog_expire_logs_seconds = 0;
1448 /**
1449 Soft upper limit for number of sp_head objects that can be stored
1450 in the sp_cache for one connection.
1451 */
1452 ulong stored_program_cache_size = 0;
1453 /**
1454 Compatibility option to prevent auto upgrade of old temporals
1455 during certain ALTER TABLE operations.
1456 */
1457 bool avoid_temporal_upgrade;
1458
1459 bool persisted_globals_load = true;
1460
1461 bool opt_keyring_operations = true;
1462
1463 bool opt_table_encryption_privilege_check = false;
1464
1465 const double log_10[] = {
1466 1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009, 1e010,
1467 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019, 1e020, 1e021,
1468 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029, 1e030, 1e031, 1e032,
1469 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039, 1e040, 1e041, 1e042, 1e043,
1470 1e044, 1e045, 1e046, 1e047, 1e048, 1e049, 1e050, 1e051, 1e052, 1e053, 1e054,
1471 1e055, 1e056, 1e057, 1e058, 1e059, 1e060, 1e061, 1e062, 1e063, 1e064, 1e065,
1472 1e066, 1e067, 1e068, 1e069, 1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076,
1473 1e077, 1e078, 1e079, 1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087,
1474 1e088, 1e089, 1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098,
1475 1e099, 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
1476 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, 1e120,
1477 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, 1e130, 1e131,
1478 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 1e140, 1e141, 1e142,
1479 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 1e150, 1e151, 1e152, 1e153,
1480 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, 1e160, 1e161, 1e162, 1e163, 1e164,
1481 1e165, 1e166, 1e167, 1e168, 1e169, 1e170, 1e171, 1e172, 1e173, 1e174, 1e175,
1482 1e176, 1e177, 1e178, 1e179, 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186,
1483 1e187, 1e188, 1e189, 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197,
1484 1e198, 1e199, 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208,
1485 1e209, 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
1486 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, 1e230,
1487 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, 1e240, 1e241,
1488 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, 1e250, 1e251, 1e252,
1489 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, 1e260, 1e261, 1e262, 1e263,
1490 1e264, 1e265, 1e266, 1e267, 1e268, 1e269, 1e270, 1e271, 1e272, 1e273, 1e274,
1491 1e275, 1e276, 1e277, 1e278, 1e279, 1e280, 1e281, 1e282, 1e283, 1e284, 1e285,
1492 1e286, 1e287, 1e288, 1e289, 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296,
1493 1e297, 1e298, 1e299, 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307,
1494 1e308};
1495
1496 /* Index extention. */
1497 const int index_ext_length = 6;
1498 const char *index_ext = ".index";
1499 const int relay_ext_length = 10;
1500 const char *relay_ext = "-relay-bin";
1501 /* True if --log-bin option is used. */
1502 bool log_bin_supplied = false;
1503
1504 time_t server_start_time, flush_status_time;
1505
1506 char server_uuid[UUID_LENGTH + 1];
1507 const char *server_uuid_ptr;
1508 char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
1509 char default_logfile_name[FN_REFLEN];
1510 char default_binlogfile_name[FN_REFLEN];
1511 char default_binlog_index_name[FN_REFLEN + index_ext_length];
1512 char default_relaylogfile_name[FN_REFLEN + relay_ext_length];
1513 char default_relaylog_index_name[FN_REFLEN + relay_ext_length +
1514 index_ext_length];
1515 char *default_tz_name;
1516 static char errorlog_filename_buff[FN_REFLEN];
1517 const char *log_error_dest;
1518 const char *my_share_dir[FN_REFLEN];
1519 char glob_hostname[HOSTNAME_LENGTH + 1];
1520 char mysql_real_data_home[FN_REFLEN], lc_messages_dir[FN_REFLEN],
1521 reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], *opt_init_file;
1522 const char *opt_tc_log_file;
1523 char *lc_messages_dir_ptr;
1524 char mysql_unpacked_real_data_home[FN_REFLEN];
1525 size_t mysql_unpacked_real_data_home_len;
1526 size_t mysql_data_home_len = 1;
1527 uint reg_ext_length;
1528 char logname_path[FN_REFLEN];
1529 char slow_logname_path[FN_REFLEN];
1530 char secure_file_real_path[FN_REFLEN];
1531 Time_zone *default_tz;
1532 char *mysql_data_home = const_cast<char *>(".");
1533 const char *mysql_real_data_home_ptr = mysql_real_data_home;
1534 char *opt_protocol_compression_algorithms;
1535 char server_version[SERVER_VERSION_LENGTH];
1536 const char *mysqld_unix_port;
1537 char *opt_mysql_tmpdir;
1538
1539 /** name of reference on left expression in rewritten IN subquery */
1540 const char *in_left_expr_name = "<left expr>";
1541
1542 my_decimal decimal_zero;
1543 /** Number of connection errors from internal server errors. */
1544 ulong connection_errors_internal = 0;
1545 /** Number of errors when reading the peer address. */
1546 ulong connection_errors_peer_addr = 0;
1547
1548 /* classes for comparation parsing/processing */
1549 Eq_creator eq_creator;
1550 Ne_creator ne_creator;
1551 Equal_creator equal_creator;
1552 Gt_creator gt_creator;
1553 Lt_creator lt_creator;
1554 Ge_creator ge_creator;
1555 Le_creator le_creator;
1556
1557 Rpl_global_filter rpl_global_filter;
1558 Rpl_filter *binlog_filter;
1559
1560 struct System_variables global_system_variables;
1561 struct System_variables max_system_variables;
1562 struct System_status_var global_status_var;
1563
1564 MY_TMPDIR mysql_tmpdir_list;
1565
1566 CHARSET_INFO *system_charset_info, *files_charset_info;
1567 CHARSET_INFO *national_charset_info, *table_alias_charset;
1568 CHARSET_INFO *character_set_filesystem;
1569
1570 MY_LOCALE *my_default_lc_messages;
1571 MY_LOCALE *my_default_lc_time_names;
1572
1573 SHOW_COMP_OPTION have_symlink, have_dlopen, have_query_cache;
1574 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
1575 SHOW_COMP_OPTION have_compress;
1576 SHOW_COMP_OPTION have_profiling;
1577 SHOW_COMP_OPTION have_statement_timeout = SHOW_OPTION_DISABLED;
1578
1579 /* Thread specific variables */
1580
1581 thread_local MEM_ROOT **THR_MALLOC = nullptr;
1582
1583 mysql_mutex_t LOCK_status, LOCK_uuid_generator, LOCK_crypt,
1584 LOCK_global_system_variables, LOCK_user_conn, LOCK_error_messages;
1585 mysql_mutex_t LOCK_sql_rand;
1586
1587 /**
1588 The below lock protects access to two global server variables:
1589 max_prepared_stmt_count and prepared_stmt_count. These variables
1590 set the limit and hold the current total number of prepared statements
1591 in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
1592 server may be fairly high, we need a dedicated lock.
1593 */
1594 mysql_mutex_t LOCK_prepared_stmt_count;
1595
1596 /*
1597 The below two locks are introduced as guards (second mutex) for
1598 the global variables sql_slave_skip_counter and slave_net_timeout
1599 respectively. See fix_slave_skip_counter/fix_slave_net_timeout
1600 for more details
1601 */
1602 mysql_mutex_t LOCK_sql_slave_skip_counter;
1603 mysql_mutex_t LOCK_slave_net_timeout;
1604 mysql_mutex_t LOCK_slave_trans_dep_tracker;
1605 mysql_mutex_t LOCK_log_throttle_qni;
1606 mysql_rwlock_t LOCK_sys_init_connect, LOCK_sys_init_slave;
1607 mysql_rwlock_t LOCK_system_variables_hash;
1608 my_thread_handle signal_thread_id;
1609 sigset_t mysqld_signal_mask;
1610 my_thread_attr_t connection_attrib;
1611 mysql_mutex_t LOCK_server_started;
1612 mysql_cond_t COND_server_started;
1613 mysql_mutex_t LOCK_reset_gtid_table;
1614 mysql_mutex_t LOCK_compress_gtid_table;
1615 mysql_cond_t COND_compress_gtid_table;
1616 mysql_mutex_t LOCK_collect_instance_log;
1617 #if !defined(_WIN32)
1618 mysql_mutex_t LOCK_socket_listener_active;
1619 mysql_cond_t COND_socket_listener_active;
1620 mysql_mutex_t LOCK_start_signal_handler;
1621 mysql_cond_t COND_start_signal_handler;
1622 #endif
1623
1624 /*
1625 The below lock protects access to global server variable
1626 keyring_operations.
1627 */
1628 mysql_mutex_t LOCK_keyring_operations;
1629 /*
1630 The below lock protects to execute commands 'ALTER INSTANCE ROTATE BINLOG
1631 MASTER KEY' and 'SET @@GLOBAL.binlog_encryption=ON/OFF' in parallel.
1632 */
1633 mysql_mutex_t LOCK_rotate_binlog_master_key;
1634
1635 bool mysqld_server_started = false;
1636 /**
1637 Set to true to signal at startup if the process must die.
1638
1639 Needed because kill_mysql() will not do anything before
1640 the server is fully initialized. Thus it now just sets this
1641 flag to on and exits. And then mysqld_main() will check if
1642 the flag is on at the right place and exit the process if it
1643 is.
1644 */
1645 static bool mysqld_process_must_end_at_startup = false;
1646
1647 /* replication parameters, if master_host is not NULL, we are a slave */
1648 uint report_port = 0;
1649 ulong master_retry_count = 0;
1650 const char *master_info_file;
1651 const char *relay_log_info_file;
1652 char *report_user, *report_password, *report_host;
1653 char *opt_relay_logname = nullptr, *opt_relaylog_index_name = nullptr;
1654 /*
1655 True if the --relay-log-index is set by users from
1656 config file or command line.
1657 */
1658 bool opt_relaylog_index_name_supplied = false;
1659 /*
1660 True if the --relay-log is set by users from
1661 config file or command line.
1662 */
1663 bool opt_relay_logname_supplied = false;
1664 /*
1665 True if --log-slave-updates option is set explicitly
1666 on command line or configuration file.
1667 */
1668 bool log_slave_updates_supplied = false;
1669
1670 /*
1671 True if --slave-preserve-commit-order-supplied option is set explicitly
1672 on command line or configuration file.
1673 */
1674 bool slave_preserve_commit_order_supplied = false;
1675 char *opt_general_logname, *opt_slow_logname, *opt_bin_logname;
1676
1677 /*
1678 True if expire_logs_days and binlog_expire_logs_seconds is set
1679 explictly.
1680 */
1681 bool expire_logs_days_supplied = false;
1682 bool binlog_expire_logs_seconds_supplied = false;
1683 /* Static variables */
1684
1685 static bool opt_myisam_log;
1686 static int cleanup_done;
1687 static ulong opt_specialflag;
1688 char *opt_binlog_index_name;
1689 char *mysql_home_ptr, *pidfile_name_ptr;
1690 char *default_auth_plugin;
1691 /**
1692 Memory for allocating command line arguments, after load_defaults().
1693 */
1694 static MEM_ROOT argv_alloc{PSI_NOT_INSTRUMENTED, 512};
1695 /** Remaining command line arguments (count), filtered by handle_options().*/
1696 static int remaining_argc;
1697 /** Remaining command line arguments (arguments), filtered by
1698 * handle_options().*/
1699 static char **remaining_argv;
1700
1701 /**
1702 Holds the "original" (i.e. as on startup) set of arguments.
1703
1704 The argument processing goes as follows:
1705 1. At startup the "original" set of arguments is shallow-copied into
1706 the read only list @ref orig_argv.
1707 2. The config file arguments are read from the config files (.cnf and
1708 persisted read-only) and are appended as command line arguments.
1709 In the process the argv is deep copied because of the expansion
1710 3. The result from 2 is set into @ref remaining_argv / @ref remaining_argc.
1711 4. Then remaining_argv is fed into various consumers:
1712 - the server compiled in set of arguments
1713 - the early plugins
1714 - the rest of the plugins
1715 - the error log
1716 - the components from the persisted dynamic loader init.
1717 All of the above "take away" the values they match from the extended
1718 command line set. And vary the values of @ref my_getopt_skip_unknown
1719 according to their needs (mostly keep it set).
1720 As a result, when the server is done booting up the things that remain
1721 in remaining_argv become less and less.
1722 5. When the bootstrap process is done a check is run:
1723 my_getopt_skip_unknown is set to off and the argument parser is called
1724 on remaining_argv with an empty set of argument definitions.
1725 This ensures that all of the remaining argument values in remaining_argv
1726 are either marked as "loose" (i.e. optional) or are "consumed" by prior
1727 argument list processings.
1728 The side effect of this is that all --loose arguments are also consumed
1729 out of remaining_argv.
1730 6. A check is made if the remaining_argv is an empty list. If not the server
1731 exits.
1732 7. At this point the server is marked as succesfully started.
1733 8. Subsequent argument processings happen when e.g. a plugin is loaded via
1734 @ref mysql_install_plugin or a component registers system variables via
1735 @ref mysql_component_sys_variable_imp::register_variable. However, since
1736 remaining_argv is empty these need to run over the orig_argc/orig_argv.
1737 But argument value assignment would normally "eat" out the values found.
1738 This would mean that the orig_argv array will get shortened and if you
1739 load the same plugin twice for example its system variables will not have
1740 the values supplied the second time they start.
1741 Thus once the server is started (@ref mysqld_server_started is on) any
1742 argument value parsing should happen over a *copy* of orig_argc/orig_argv
1743 that should subsequently be discarded.
1744 @ref remaining_argv should not be consulted anymore at this point.
1745 */
1746 int orig_argc;
1747 char **orig_argv;
1748 namespace {
1749 FILE *nstdout = nullptr;
1750 char my_progpath[FN_REFLEN];
1751 const char *my_orig_progname = nullptr;
1752
1753 /**
1754 This variable holds the exit value of the signal handler thread.
1755 */
1756 std::atomic<int> signal_hand_thr_exit_code(MYSQLD_SUCCESS_EXIT);
1757
1758 /**
1759 Inspects the program name in argv[0] and substitutes the full path
1760 of the executable.
1761
1762 @param argv argument vector (array) for executable.
1763 */
substitute_progpath(char ** argv)1764 void substitute_progpath(char **argv) {
1765 if (test_if_hard_path(argv[0])) return;
1766
1767 #if defined(_WIN32)
1768 if (GetModuleFileName(NULL, my_progpath, sizeof(my_progpath))) {
1769 my_orig_progname = argv[0];
1770 argv[0] = my_progpath;
1771 }
1772 #else
1773 /* If the path has a directory component, use my_realpath()
1774 (implicitly relative to cwd) */
1775 if (strchr(argv[0], FN_LIBCHAR) != nullptr &&
1776 !my_realpath(my_progpath, argv[0], MYF(0))) {
1777 my_orig_progname = argv[0];
1778 argv[0] = my_progpath;
1779 return;
1780 }
1781
1782 // my_realpath() cannot resolve it, it must be a bare executable
1783 // name in path
1784 DBUG_ASSERT(strchr(argv[0], FN_LIBCHAR) == nullptr);
1785
1786 const char *spbegin = getenv("PATH");
1787 if (spbegin == nullptr) spbegin = "";
1788 const char *spend = spbegin + strlen(spbegin);
1789
1790 while (true) {
1791 const char *colonend = std::find(spbegin, spend, ':');
1792 std::string cand{spbegin, colonend};
1793 spbegin = colonend + 1;
1794
1795 cand.append(1, '/');
1796 cand.append(argv[0]);
1797
1798 if (my_access(cand.c_str(), X_OK) == 0) {
1799 if (my_realpath(my_progpath, cand.c_str(), MYF(0))) {
1800 // Fallback to raw cand
1801 DBUG_ASSERT(cand.length() < FN_REFLEN);
1802 std::copy(cand.begin(), cand.end(), my_progpath);
1803 my_progpath[cand.length()] = '\0';
1804 }
1805 my_orig_progname = argv[0];
1806 argv[0] = my_progpath;
1807 break;
1808 }
1809 if (colonend == spend) {
1810 DBUG_ASSERT(false);
1811 break;
1812 }
1813 } // while (true)
1814 #endif // defined(_WIN32)
1815 if (my_orig_progname == nullptr) {
1816 LogErr(WARNING_LEVEL, ER_FAILED_TO_GET_ABSOLUTE_PATH, argv[0]);
1817 }
1818 }
1819 } // namespace
1820
1821 static Connection_acceptor<Mysqld_socket_listener> *mysqld_socket_acceptor =
1822 nullptr;
1823 #ifdef _WIN32
1824 static Named_pipe_listener *named_pipe_listener = NULL;
1825 Connection_acceptor<Named_pipe_listener> *named_pipe_acceptor = NULL;
1826 Connection_acceptor<Shared_mem_listener> *shared_mem_acceptor = NULL;
1827 mysql_rwlock_t LOCK_named_pipe_full_access_group;
1828 char *named_pipe_full_access_group;
1829 #endif
1830
1831 Checkable_rwlock *global_sid_lock = nullptr;
1832 Sid_map *global_sid_map = nullptr;
1833 Gtid_state *gtid_state = nullptr;
1834 Gtid_table_persistor *gtid_table_persistor = nullptr;
1835
1836 /* cache for persisted variables */
1837 static Persisted_variables_cache persisted_variables_cache;
1838
set_remaining_args(int argc,char ** argv)1839 void set_remaining_args(int argc, char **argv) {
1840 remaining_argc = argc;
1841 remaining_argv = argv;
1842 }
1843
get_remaining_argc()1844 int *get_remaining_argc() { return &remaining_argc; }
1845
get_remaining_argv()1846 char ***get_remaining_argv() { return &remaining_argv; }
1847
1848 /*
1849 Multiple threads of execution use the random state maintained in global
1850 sql_rand to generate random numbers. sql_rnd_with_mutex use mutex
1851 LOCK_sql_rand to protect sql_rand across multiple instantiations that use
1852 sql_rand to generate random numbers.
1853 */
sql_rnd_with_mutex()1854 ulong sql_rnd_with_mutex() {
1855 mysql_mutex_lock(&LOCK_sql_rand);
1856 ulong tmp =
1857 (ulong)(my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
1858 mysql_mutex_unlock(&LOCK_sql_rand);
1859 return tmp;
1860 }
1861
get_thd_status_var(THD * thd,bool * aggregated)1862 struct System_status_var *get_thd_status_var(THD *thd, bool *aggregated) {
1863 *aggregated = thd->status_var_aggregated;
1864 return &thd->status_var;
1865 }
1866
option_error_reporter(enum loglevel level,uint ecode,...)1867 static void option_error_reporter(enum loglevel level, uint ecode, ...) {
1868 va_list args;
1869 va_start(args, ecode);
1870
1871 /*
1872 Don't print warnings for --loose options during initialize.
1873 */
1874 if (level == ERROR_LEVEL || !opt_initialize || (log_error_verbosity > 1)) {
1875 error_log_print(level, ecode, args);
1876 }
1877 va_end(args);
1878 }
1879
1880 /**
1881 Character set and collation error reporter that prints to sql error log.
1882 @param level log message level
1883 @param ecode Error code of the error message.
1884
1885 This routine is used to print character set and collation
1886 warnings and errors inside an already running mysqld server,
1887 e.g. when a character set or collation is requested for the very first time
1888 and its initialization does not go well for some reasons.
1889 */
1890
charset_error_reporter(enum loglevel level,uint ecode,...)1891 static void charset_error_reporter(enum loglevel level, uint ecode, ...) {
1892 va_list args;
1893 va_start(args, ecode);
1894 error_log_print(level, ecode, args);
1895 va_end(args);
1896 }
1897
1898 struct rand_struct sql_rand; ///< used by sql_class.cc:THD::THD()
1899
1900 #ifndef _WIN32
1901 PasswdValue user_info;
1902 static my_thread_t main_thread_id;
1903 #endif // !_WIN32
1904
1905 /* OS specific variables */
1906
1907 #ifdef _WIN32
1908 static bool mysqld_early_option = false;
1909 static bool windows_service = false;
1910 static bool use_opt_args;
1911 static int opt_argc;
1912 static char **opt_argv;
1913 static char **my_global_argv = nullptr;
1914 static int my_global_argc;
1915
1916 static mysql_mutex_t LOCK_handler_count;
1917 static mysql_cond_t COND_handler_count;
1918 static HANDLE hEventShutdown;
1919 static HANDLE hEventRestart;
1920 const char *shared_memory_base_name = default_shared_memory_base_name;
1921 bool opt_enable_shared_memory;
1922 static char shutdown_event_name[40];
1923 static char restart_event_name[40];
1924 static NTService Service; ///< Service object for WinNT
1925 #endif /* _WIN32 */
1926
1927 static bool dynamic_plugins_are_initialized = false;
1928
1929 #ifndef DBUG_OFF
1930 static const char *default_dbug_option;
1931 #endif
1932
1933 #ifndef XTRABACKUP
1934 bool opt_use_ssl = true;
1935 bool opt_use_admin_ssl = true;
1936 ulong opt_ssl_fips_mode = SSL_FIPS_MODE_OFF;
1937 #endif
1938
1939 /* Function declarations */
1940
1941 static int mysql_init_variables();
1942 static int get_options(int *argc_ptr, char ***argv_ptr);
1943 static void add_terminator(vector<my_option> *options);
1944 extern "C" bool mysqld_get_one_option(int, const struct my_option *, char *);
1945 static void set_server_version(void);
1946 static int init_thread_environment();
1947 static const char *get_relative_path(const char *path);
1948 static int fix_paths(void);
1949 static int test_if_case_insensitive(const char *dir_name);
1950 static void end_ssl();
1951 static void delete_dictionary_tablespace();
1952
1953 extern "C" void *signal_hand(void *arg);
1954 static bool pid_file_created = false;
1955 static void usage(void);
1956 static void clean_up_mutexes(void);
1957 static bool create_pid_file();
1958 static void mysqld_exit(int exit_code) MY_ATTRIBUTE((noreturn));
1959 static void delete_pid_file(myf flags);
1960 static void clean_up(bool print_message);
1961 static int handle_early_options();
1962 static void adjust_related_options(ulong *requested_open_files);
1963 static void process_bootstrap();
1964 #ifdef HAVE_PSI_INTERFACE
1965 static void init_server_psi_keys();
1966 #endif
1967
1968 /**
1969 Notify any waiters that the server components have been initialized.
1970 Used by the signal handler thread and by Cluster.
1971
1972 @see signal_hand
1973 */
1974
server_components_initialized()1975 static void server_components_initialized() {
1976 mysql_mutex_lock(&LOCK_server_started);
1977 mysqld_server_started = true;
1978 mysql_cond_broadcast(&COND_server_started);
1979 mysql_mutex_unlock(&LOCK_server_started);
1980 }
1981
1982 SERVICE_TYPE(mysql_runtime_error) * error_service;
1983 SERVICE_TYPE(mysql_psi_system_v1) * system_service;
1984 SERVICE_TYPE(mysql_rwlock_v1) * rwlock_service;
1985 SERVICE_TYPE_NO_CONST(registry) * srv_registry;
1986 SERVICE_TYPE(dynamic_loader_scheme_file) * scheme_file_srv;
1987 using loader_type_t = SERVICE_TYPE_NO_CONST(dynamic_loader);
1988 using runtime_error_type_t = SERVICE_TYPE_NO_CONST(mysql_runtime_error);
1989 using psi_system_type_t = SERVICE_TYPE_NO_CONST(mysql_psi_system_v1);
1990 using rwlock_type_t = SERVICE_TYPE_NO_CONST(mysql_rwlock_v1);
1991 using loader_scheme_type_t = SERVICE_TYPE_NO_CONST(dynamic_loader_scheme_file);
1992 extern REQUIRES_SERVICE_PLACEHOLDER(mysql_rwlock_v1);
1993 extern REQUIRES_SERVICE_PLACEHOLDER(mysql_psi_system_v1);
1994 extern bool initialize_minimal_chassis(SERVICE_TYPE_NO_CONST(registry) *
1995 *registry);
1996 extern bool deinitialize_minimal_chassis(SERVICE_TYPE_NO_CONST(registry) *
1997 registry);
1998
1999 /**
2000 Initializes component infrastructure by bootstrapping core component
2001 subsystem.
2002
2003 @return Status of performed operation
2004 @retval false success
2005 @retval true failure
2006 */
component_infrastructure_init()2007 bool component_infrastructure_init() {
2008 if (initialize_minimal_chassis(&srv_registry)) {
2009 LogErr(ERROR_LEVEL, ER_COMPONENTS_INFRASTRUCTURE_BOOTSTRAP);
2010 return true;
2011 }
2012 /* Here minimal_chassis dynamic_loader_scheme_file service has
2013 to be acquired */
2014 srv_registry->acquire(
2015 "dynamic_loader_scheme_file.mysql_minimal_chassis",
2016 reinterpret_cast<my_h_service *>(
2017 const_cast<loader_scheme_type_t **>(&scheme_file_srv)));
2018
2019 srv_registry->acquire("dynamic_loader",
2020 reinterpret_cast<my_h_service *>(
2021 const_cast<loader_type_t **>(&dynamic_loader_srv)));
2022
2023 my_service<SERVICE_TYPE(registry_registration)> registrator(
2024 "registry_registration", srv_registry);
2025
2026 // Sets default file scheme loader for MySQL server.
2027 registrator->set_default(
2028 "dynamic_loader_scheme_file.mysql_server_path_filter");
2029
2030 // Sets default rw_lock for MySQL server.
2031 registrator->set_default("mysql_rwlock_v1.mysql_server");
2032 srv_registry->acquire("mysql_rwlock_v1.mysql_server",
2033 reinterpret_cast<my_h_service *>(
2034 const_cast<rwlock_type_t **>(&rwlock_service)));
2035 mysql_service_mysql_rwlock_v1 =
2036 reinterpret_cast<SERVICE_TYPE(mysql_rwlock_v1) *>(rwlock_service);
2037
2038 // Sets default psi_system event service for MySQL server.
2039 registrator->set_default("mysql_psi_system_v1.mysql_server");
2040 srv_registry->acquire("mysql_psi_system_v1.mysql_server",
2041 reinterpret_cast<my_h_service *>(
2042 const_cast<psi_system_type_t **>(&system_service)));
2043 /* This service variable is needed for mysql_unload_plugin */
2044 mysql_service_mysql_psi_system_v1 =
2045 reinterpret_cast<SERVICE_TYPE(mysql_psi_system_v1) *>(system_service);
2046
2047 // Sets default mysql_runtime_error for MySQL server.
2048 registrator->set_default("mysql_runtime_error.mysql_server");
2049 srv_registry->acquire(
2050 "mysql_runtime_error.mysql_server",
2051 reinterpret_cast<my_h_service *>(
2052 const_cast<runtime_error_type_t **>(&error_service)));
2053 /* This service variable is needed where ever mysql_error_service_printf()
2054 service api is used */
2055 mysql_service_mysql_runtime_error =
2056 reinterpret_cast<SERVICE_TYPE(mysql_runtime_error) *>(error_service);
2057
2058 return false;
2059 }
2060
2061 /**
2062 This function is used to initialize the mysql_server component services.
2063 */
server_component_init()2064 static void server_component_init() { mysql_comp_sys_var_services_init(); }
2065
2066 /**
2067 Initializes MySQL Server component infrastructure part by initialize of
2068 dynamic loader persistence.
2069
2070 @return Status of performed operation
2071 @retval false success
2072 @retval true failure
2073 */
2074
mysql_component_infrastructure_init()2075 static bool mysql_component_infrastructure_init() {
2076 /* We need a temporary THD during boot */
2077 Auto_THD thd;
2078 Disable_autocommit_guard autocommit_guard(thd.thd);
2079 dd::cache::Dictionary_client::Auto_releaser scope_releaser(
2080 thd.thd->dd_client());
2081 if (persistent_dynamic_loader_init(thd.thd)) {
2082 LogErr(ERROR_LEVEL, ER_COMPONENTS_PERSIST_LOADER_BOOTSTRAP);
2083 trans_rollback_stmt(thd.thd);
2084 // Full rollback in case we have THD::transaction_rollback_request.
2085 trans_rollback(thd.thd);
2086 return true;
2087 }
2088 server_component_init();
2089 return trans_commit_stmt(thd.thd) || trans_commit(thd.thd);
2090 }
2091
2092 /**
2093 De-initializes Component infrastructure by de-initialization of the MySQL
2094 Server services (persistent dynamic loader) followed by de-initailization of
2095 the core Components infrostructure.
2096
2097 @return Status of performed operation
2098 @retval false success
2099 @retval true failure
2100 */
component_infrastructure_deinit()2101 bool component_infrastructure_deinit() {
2102 persistent_dynamic_loader_deinit();
2103
2104 srv_registry->release(reinterpret_cast<my_h_service>(
2105 const_cast<loader_scheme_type_t *>(scheme_file_srv)));
2106 srv_registry->release(reinterpret_cast<my_h_service>(
2107 const_cast<loader_type_t *>(dynamic_loader_srv)));
2108 srv_registry->release(reinterpret_cast<my_h_service>(
2109 const_cast<runtime_error_type_t *>(error_service)));
2110 srv_registry->release(reinterpret_cast<my_h_service>(
2111 const_cast<psi_system_type_t *>(system_service)));
2112 srv_registry->release(reinterpret_cast<my_h_service>(
2113 const_cast<rwlock_type_t *>(rwlock_service)));
2114
2115 if (deinitialize_minimal_chassis(srv_registry)) {
2116 LogErr(ERROR_LEVEL, ER_COMPONENTS_INFRASTRUCTURE_SHUTDOWN);
2117 return true;
2118 }
2119 return false;
2120 }
2121
2122 /**
2123 Block and wait until server components have been initialized.
2124 */
2125
server_components_init_wait()2126 static void server_components_init_wait() {
2127 mysql_mutex_lock(&LOCK_server_started);
2128 while (!mysqld_server_started)
2129 mysql_cond_wait(&COND_server_started, &LOCK_server_started);
2130 mysql_mutex_unlock(&LOCK_server_started);
2131 }
2132
2133 /****************************************************************************
2134 ** Code to end mysqld
2135 ****************************************************************************/
2136
2137 /**
2138 This class implements callback function used by close_connections()
2139 to set KILL_CONNECTION flag on all thds in thd list.
2140 If m_kill_dump_thread_flag is not set it kills all other threads
2141 except dump threads. If this flag is set, it kills dump threads.
2142 */
2143 class Set_kill_conn : public Do_THD_Impl {
2144 private:
2145 int m_dump_thread_count;
2146 bool m_kill_dump_threads_flag;
2147
2148 public:
Set_kill_conn()2149 Set_kill_conn() : m_dump_thread_count(0), m_kill_dump_threads_flag(false) {}
2150
set_dump_thread_flag()2151 void set_dump_thread_flag() { m_kill_dump_threads_flag = true; }
2152
get_dump_thread_count() const2153 int get_dump_thread_count() const { return m_dump_thread_count; }
2154
operator ()(THD * killing_thd)2155 virtual void operator()(THD *killing_thd) {
2156 DBUG_PRINT("quit", ("Informing thread %u that it's time to die",
2157 killing_thd->thread_id()));
2158 if (!m_kill_dump_threads_flag) {
2159 // We skip slave threads & scheduler on this first loop through.
2160 if (killing_thd->slave_thread) return;
2161
2162 if (killing_thd->get_command() == COM_BINLOG_DUMP ||
2163 killing_thd->get_command() == COM_BINLOG_DUMP_GTID) {
2164 ++m_dump_thread_count;
2165 return;
2166 }
2167 DBUG_EXECUTE_IF("Check_dump_thread_is_alive", {
2168 DBUG_ASSERT(killing_thd->get_command() != COM_BINLOG_DUMP &&
2169 killing_thd->get_command() != COM_BINLOG_DUMP_GTID);
2170 };);
2171 }
2172 mysql_mutex_lock(&killing_thd->LOCK_thd_data);
2173
2174 if (killing_thd->kill_immunizer) {
2175 /*
2176 If killing_thd is in kill immune mode (i.e. operation on new DD tables
2177 is in progress) then just save state_to_set with THD::kill_immunizer
2178 object.
2179
2180 While exiting kill immune mode, awake() is called again with the killed
2181 state saved in THD::kill_immunizer object.
2182 */
2183 killing_thd->kill_immunizer->save_killed_state(THD::KILL_CONNECTION);
2184 } else {
2185 killing_thd->killed = THD::KILL_CONNECTION;
2186
2187 MYSQL_CALLBACK(Connection_handler_manager::event_functions,
2188 post_kill_notification, (killing_thd));
2189 }
2190
2191 if (killing_thd->is_killable && killing_thd->kill_immunizer == nullptr) {
2192 mysql_mutex_lock(&killing_thd->LOCK_current_cond);
2193 if (killing_thd->current_cond.load()) {
2194 mysql_mutex_lock(killing_thd->current_mutex);
2195 mysql_cond_broadcast(killing_thd->current_cond);
2196 mysql_mutex_unlock(killing_thd->current_mutex);
2197 }
2198 mysql_mutex_unlock(&killing_thd->LOCK_current_cond);
2199 }
2200 mysql_mutex_unlock(&killing_thd->LOCK_thd_data);
2201 }
2202 };
2203
2204 /**
2205 This class implements callback function used by close_connections()
2206 to close vio connection for all thds in thd list
2207 */
2208 class Call_close_conn : public Do_THD_Impl {
2209 public:
Call_close_conn(bool server_shutdown)2210 Call_close_conn(bool server_shutdown) : is_server_shutdown(server_shutdown) {}
2211
operator ()(THD * closing_thd)2212 virtual void operator()(THD *closing_thd) {
2213 if (closing_thd->get_protocol()->connection_alive()) {
2214 LEX_CSTRING main_sctx_user = closing_thd->m_main_security_ctx.user();
2215 LogErr(WARNING_LEVEL, ER_FORCE_CLOSE_THREAD, my_progname,
2216 (long)closing_thd->thread_id(),
2217 (main_sctx_user.length ? main_sctx_user.str : ""));
2218 /*
2219 Do not generate MYSQL_AUDIT_CONNECTION_DISCONNECT event, when closing
2220 thread close sessions. Each session will generate DISCONNECT event by
2221 itself.
2222 */
2223 close_connection(closing_thd, 0, is_server_shutdown, false);
2224 }
2225 }
2226
2227 private:
2228 bool is_server_shutdown;
2229 };
2230
close_connections(void)2231 static void close_connections(void) {
2232 DBUG_TRACE;
2233 (void)RUN_HOOK(server_state, before_server_shutdown, (nullptr));
2234
2235 Per_thread_connection_handler::kill_blocked_pthreads();
2236
2237 uint dump_thread_count = 0;
2238 uint dump_thread_kill_retries = 8;
2239
2240 // Close listeners.
2241 if (mysqld_socket_acceptor != nullptr)
2242 mysqld_socket_acceptor->close_listener();
2243 #ifdef _WIN32
2244 if (named_pipe_acceptor != NULL) named_pipe_acceptor->close_listener();
2245
2246 if (shared_mem_acceptor != NULL) shared_mem_acceptor->close_listener();
2247 #endif
2248
2249 /*
2250 First signal all threads that it's time to die
2251 This will give the threads some time to gracefully abort their
2252 statements and inform their clients that the server is about to die.
2253 */
2254
2255 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
2256 LogErr(INFORMATION_LEVEL, ER_DEPART_WITH_GRACE,
2257 static_cast<int>(thd_manager->get_thd_count()));
2258
2259 Set_kill_conn set_kill_conn;
2260 thd_manager->do_for_all_thd(&set_kill_conn);
2261 LogErr(INFORMATION_LEVEL, ER_SHUTTING_DOWN_SLAVE_THREADS);
2262 end_slave();
2263
2264 if (set_kill_conn.get_dump_thread_count()) {
2265 /*
2266 Replication dump thread should be terminated after the clients are
2267 terminated. Wait for few more seconds for other sessions to end.
2268 */
2269 while (thd_manager->get_thd_count() > dump_thread_count &&
2270 dump_thread_kill_retries) {
2271 sleep(1);
2272 dump_thread_kill_retries--;
2273 }
2274 set_kill_conn.set_dump_thread_flag();
2275 thd_manager->do_for_all_thd(&set_kill_conn);
2276 }
2277
2278 // Disable the event scheduler
2279 Events::stop();
2280
2281 if (thd_manager->get_thd_count() > 0) sleep(2); // Give threads time to die
2282
2283 /*
2284 Force remaining threads to die by closing the connection to the client
2285 This will ensure that threads that are waiting for a command from the
2286 client on a blocking read call are aborted.
2287 */
2288
2289 LogErr(INFORMATION_LEVEL, ER_DISCONNECTING_REMAINING_CLIENTS,
2290 static_cast<int>(thd_manager->get_thd_count()));
2291
2292 Call_close_conn call_close_conn(true);
2293 thd_manager->do_for_all_thd(&call_close_conn);
2294
2295 (void)RUN_HOOK(server_state, after_server_shutdown, (nullptr));
2296
2297 /*
2298 All threads have now been aborted. Stop event scheduler thread
2299 after aborting all client connections, otherwise user may
2300 start/stop event scheduler after Events::deinit() deallocates
2301 scheduler object(static member in Events class)
2302 */
2303 Events::deinit();
2304 DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)",
2305 thd_manager->get_thd_count()));
2306 thd_manager->wait_till_no_thd();
2307 /*
2308 Connection threads might take a little while to go down after removing from
2309 global thread list. Give it some time.
2310 */
2311 Connection_handler_manager::wait_till_no_connection();
2312
2313 delete_slave_info_objects();
2314 DBUG_PRINT("quit", ("close_connections thread"));
2315 }
2316
signal_restart_server()2317 bool signal_restart_server() {
2318 if (!is_mysqld_managed()) {
2319 my_error(ER_RESTART_SERVER_FAILED, MYF(0),
2320 "mysqld is not managed by supervisor process");
2321 return true;
2322 }
2323
2324 #ifdef _WIN32
2325 if (!SetEvent(hEventRestart)) {
2326 LogErr(ERROR_LEVEL, ER_SET_EVENT_FAILED, GetLastError());
2327 my_error(ER_RESTART_SERVER_FAILED, MYF(0), "Internal operation failure");
2328 return true;
2329 }
2330 #else
2331
2332 if (pthread_kill(signal_thread_id.thread, SIGUSR2)) {
2333 DBUG_PRINT("error", ("Got error %d from pthread_kill", errno));
2334 my_error(ER_RESTART_SERVER_FAILED, MYF(0), "Internal operation failure");
2335 return true;
2336 }
2337 #endif
2338 return false;
2339 }
2340
kill_mysql(void)2341 void kill_mysql(void) {
2342 DBUG_TRACE;
2343
2344 if (!mysqld_server_started) {
2345 mysqld_process_must_end_at_startup = true;
2346 return;
2347 }
2348 #if defined(_WIN32)
2349 {
2350 if (!SetEvent(hEventShutdown)) {
2351 DBUG_PRINT("error", ("Got error: %ld from SetEvent", GetLastError()));
2352 }
2353 /*
2354 or:
2355 HANDLE hEvent=OpenEvent(0, false, "MySqlShutdown");
2356 SetEvent(hEventShutdown);
2357 CloseHandle(hEvent);
2358 */
2359 }
2360 #else
2361 if (pthread_kill(signal_thread_id.thread, SIGTERM)) {
2362 DBUG_PRINT("error", ("Got error %d from pthread_kill",
2363 errno)); /* purecov: inspected */
2364 }
2365 #endif
2366 DBUG_PRINT("quit", ("After pthread_kill"));
2367 }
2368
unireg_abort(int exit_code)2369 static void unireg_abort(int exit_code) {
2370 DBUG_TRACE;
2371
2372 if (errno) {
2373 sysd::notify("ERRNO=", errno, "\n");
2374 }
2375
2376 if (opt_initialize && exit_code && !opt_validate_config)
2377 LogErr(ERROR_LEVEL,
2378 mysql_initialize_directory_freshly_created
2379 ? ER_DATA_DIRECTORY_UNUSABLE_DELETABLE
2380 : ER_DATA_DIRECTORY_UNUSABLE,
2381 mysql_real_data_home);
2382
2383 // At this point it does not make sense to buffer more messages.
2384 // Just flush what we have and write directly to stderr.
2385 flush_error_log_messages();
2386
2387 if (opt_help) usage();
2388
2389 bool daemon_launcher_quiet =
2390 (IF_WIN(false, opt_daemonize) && !mysqld::runtime::is_daemon() &&
2391 !is_help_or_validate_option());
2392
2393 if (!daemon_launcher_quiet && exit_code) LogErr(ERROR_LEVEL, ER_ABORTING);
2394
2395 mysql_audit_notify(MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN,
2396 MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_ABORT, exit_code);
2397 #ifndef _WIN32
2398 if (signal_thread_id.thread != 0) {
2399 // Make sure the signal thread isn't blocked when we are trying to exit.
2400 server_components_initialized();
2401
2402 pthread_kill(signal_thread_id.thread, SIGTERM);
2403 my_thread_join(&signal_thread_id, nullptr);
2404 }
2405 signal_thread_id.thread = 0;
2406
2407 if (mysqld::runtime::is_daemon()) {
2408 mysqld::runtime::signal_parent(pipe_write_fd, 0);
2409 }
2410 #endif
2411 clean_up(!is_help_or_validate_option() && !daemon_launcher_quiet &&
2412 (exit_code || !opt_initialize)); /* purecov: inspected */
2413 DBUG_PRINT("quit", ("done with cleanup in unireg_abort"));
2414 mysqld_exit(exit_code);
2415 }
2416
clean_up_mysqld_mutexes()2417 void clean_up_mysqld_mutexes() { clean_up_mutexes(); }
2418
mysqld_exit(int exit_code)2419 static void mysqld_exit(int exit_code) {
2420 DBUG_ASSERT(
2421 (exit_code >= MYSQLD_SUCCESS_EXIT && exit_code <= MYSQLD_ABORT_EXIT) ||
2422 exit_code == MYSQLD_RESTART_EXIT);
2423 mysql_audit_finalize();
2424 Srv_session::module_deinit();
2425 delete_optimizer_cost_module();
2426 clean_up_mutexes();
2427 my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
2428 destroy_error_log();
2429 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
2430 shutdown_performance_schema();
2431 #endif
2432
2433 #ifdef WITH_LOCK_ORDER
2434 LO_cleanup();
2435 #endif
2436
2437 #if defined(_WIN32)
2438 if (hEventShutdown) CloseHandle(hEventShutdown);
2439 close_service_status_pipe_in_mysqld();
2440 #endif // _WIN32
2441
2442 exit(exit_code); /* purecov: inspected */
2443 }
2444
2445 /**
2446 GTID cleanup destroys objects and reset their pointer.
2447 Function is reentrant.
2448 */
gtid_server_cleanup()2449 void gtid_server_cleanup() {
2450 if (gtid_state != nullptr) {
2451 delete gtid_state;
2452 gtid_state = nullptr;
2453 }
2454 if (global_sid_map != nullptr) {
2455 delete global_sid_map;
2456 global_sid_map = nullptr;
2457 }
2458 if (global_sid_lock != nullptr) {
2459 delete global_sid_lock;
2460 global_sid_lock = nullptr;
2461 }
2462 if (gtid_table_persistor != nullptr) {
2463 delete gtid_table_persistor;
2464 gtid_table_persistor = nullptr;
2465 }
2466 }
2467
2468 /**
2469 GTID initialization.
2470
2471 @return true if allocation does not succeed
2472 false if OK
2473 */
gtid_server_init()2474 bool gtid_server_init() {
2475 global_gtid_mode.set(
2476 static_cast<Gtid_mode::value_type>(Gtid_mode::sysvar_mode));
2477 bool res = (!(global_sid_lock = new Checkable_rwlock(
2478 #ifdef HAVE_PSI_INTERFACE
2479 key_rwlock_global_sid_lock
2480 #endif
2481 )) ||
2482 !(global_sid_map = new Sid_map(global_sid_lock)) ||
2483 !(gtid_state = new Gtid_state(global_sid_lock, global_sid_map)) ||
2484 !(gtid_table_persistor = new Gtid_table_persistor()));
2485
2486 if (res) {
2487 gtid_server_cleanup();
2488 }
2489 return res;
2490 }
2491
2492 // Free connection acceptors
free_connection_acceptors()2493 static void free_connection_acceptors() {
2494 delete mysqld_socket_acceptor;
2495 mysqld_socket_acceptor = nullptr;
2496
2497 #ifdef _WIN32
2498 delete named_pipe_acceptor;
2499 named_pipe_acceptor = NULL;
2500 delete shared_mem_acceptor;
2501 shared_mem_acceptor = NULL;
2502 #endif
2503 }
2504
clean_up(bool print_message)2505 static void clean_up(bool print_message) {
2506 DBUG_PRINT("exit", ("clean_up"));
2507 if (cleanup_done++) return; /* purecov: inspected */
2508
2509 ha_pre_dd_shutdown();
2510 dd::shutdown();
2511
2512 Events::deinit();
2513 stop_handle_manager();
2514
2515 memcached_shutdown();
2516
2517 /*
2518 make sure that handlers finish up
2519 what they have that is dependent on the binlog
2520 */
2521 if (print_message && (!is_help_or_validate_option() || opt_verbose))
2522 LogErr(INFORMATION_LEVEL, ER_BINLOG_END);
2523 ha_binlog_end(current_thd);
2524
2525 injector::free_instance();
2526 mysql_bin_log.cleanup();
2527
2528 if (use_slave_mask) bitmap_free(&slave_error_mask);
2529 my_tz_free();
2530 servers_free(true);
2531 acl_free(true);
2532 grant_free();
2533 hostname_cache_free();
2534 range_optimizer_free();
2535 item_func_sleep_free();
2536 lex_free(); /* Free some memory */
2537 item_create_cleanup();
2538 if (!opt_noacl) udf_unload_udfs();
2539 table_def_start_shutdown();
2540 plugin_shutdown();
2541 gtid_server_cleanup(); // after plugin_shutdown
2542 delete_optimizer_cost_module();
2543 ha_end();
2544 if (tc_log) {
2545 tc_log->close();
2546 tc_log = nullptr;
2547 }
2548
2549 if (dd::upgrade_57::in_progress()) delete_dictionary_tablespace();
2550
2551 Recovered_xa_transactions::destroy();
2552 delegates_destroy();
2553 transaction_cache_free();
2554 MDL_context_backup_manager::destroy();
2555 table_def_free();
2556 mdl_destroy();
2557 key_caches.delete_elements();
2558 multi_keycache_free();
2559 query_logger.cleanup();
2560 free_tmpdir(&mysql_tmpdir_list);
2561 my_free(opt_bin_logname);
2562 free_max_user_conn();
2563 end_slave_list();
2564 delete binlog_filter;
2565 rpl_channel_filters.clean_up();
2566 end_ssl();
2567 vio_end();
2568 u_cleanup();
2569 #if defined(ENABLED_DEBUG_SYNC)
2570 /* End the debug sync facility. See debug_sync.cc. */
2571 debug_sync_end();
2572 #endif /* defined(ENABLED_DEBUG_SYNC) */
2573
2574 delete_pid_file(MYF(0));
2575
2576 if (print_message && my_default_lc_messages && server_start_time)
2577 LogErr(SYSTEM_LEVEL, ER_SERVER_SHUTDOWN_COMPLETE, my_progname,
2578 server_version, MYSQL_COMPILATION_COMMENT_SERVER);
2579 cleanup_errmsgs();
2580
2581 free_connection_acceptors();
2582 Connection_handler_manager::destroy_instance();
2583
2584 if (!is_help_or_validate_option() && !opt_initialize)
2585 resourcegroups::Resource_group_mgr::destroy_instance();
2586 mysql_client_plugin_deinit();
2587
2588 Global_THD_manager::destroy_instance();
2589
2590 my_free(const_cast<char *>(log_bin_basename));
2591 my_free(const_cast<char *>(log_bin_index));
2592 my_free(const_cast<char *>(relay_log_basename));
2593 my_free(const_cast<char *>(relay_log_index));
2594 free_list(opt_early_plugin_load_list_ptr);
2595 free_list(opt_plugin_load_list_ptr);
2596
2597 /*
2598 Is this the best place for components deinit? It may be changed when new
2599 dependencies are discovered, possibly being divided into separate points
2600 where all dependencies are still ok.
2601 */
2602 log_error_stage_set(LOG_ERROR_STAGE_SHUTTING_DOWN);
2603 log_builtins_error_stack(LOG_ERROR_SERVICES_DEFAULT, false, nullptr);
2604 #ifdef HAVE_PSI_THREAD_INTERFACE
2605 if (!is_help_or_validate_option() && !opt_initialize) {
2606 unregister_pfs_notification_service();
2607 unregister_pfs_resource_group_service();
2608 }
2609 #endif
2610 deinit_tls_psi_keys();
2611 component_infrastructure_deinit();
2612 /*
2613 component unregister_variable() api depends on system_variable_hash.
2614 component_infrastructure_deinit() interns calls the deinit funtion
2615 of components which are loaded, and the deinit functions can have
2616 the component system unregister_ variable() api's, hence we need
2617 to call the sys_var_end() after component_infrastructure_deinit()
2618 */
2619 sys_var_end();
2620 free_status_vars();
2621
2622 finish_client_errs();
2623 deinit_errmessage(); // finish server errs
2624 DBUG_PRINT("quit", ("Error messages freed"));
2625
2626 if (have_statement_timeout == SHOW_OPTION_YES) my_timer_deinitialize();
2627
2628 have_statement_timeout = SHOW_OPTION_DISABLED;
2629
2630 persisted_variables_cache.cleanup();
2631
2632 udf_deinit_globals();
2633 /*
2634 The following lines may never be executed as the main thread may have
2635 killed us
2636 */
2637 DBUG_PRINT("quit", ("done with cleanup"));
2638 } /* clean_up */
2639
clean_up_mutexes()2640 static void clean_up_mutexes() {
2641 mysql_mutex_destroy(&LOCK_log_throttle_qni);
2642 mysql_mutex_destroy(&LOCK_status);
2643 mysql_mutex_destroy(&LOCK_manager);
2644 mysql_mutex_destroy(&LOCK_crypt);
2645 mysql_mutex_destroy(&LOCK_user_conn);
2646 mysql_rwlock_destroy(&LOCK_sys_init_connect);
2647 mysql_rwlock_destroy(&LOCK_sys_init_slave);
2648 mysql_mutex_destroy(&LOCK_global_system_variables);
2649 mysql_rwlock_destroy(&LOCK_system_variables_hash);
2650 mysql_mutex_destroy(&LOCK_uuid_generator);
2651 mysql_mutex_destroy(&LOCK_sql_rand);
2652 mysql_mutex_destroy(&LOCK_prepared_stmt_count);
2653 mysql_mutex_destroy(&LOCK_sql_slave_skip_counter);
2654 mysql_mutex_destroy(&LOCK_slave_net_timeout);
2655 mysql_mutex_destroy(&LOCK_slave_trans_dep_tracker);
2656 mysql_mutex_destroy(&LOCK_error_messages);
2657 mysql_mutex_destroy(&LOCK_default_password_lifetime);
2658 mysql_mutex_destroy(&LOCK_mandatory_roles);
2659 mysql_mutex_destroy(&LOCK_server_started);
2660 mysql_cond_destroy(&COND_server_started);
2661 mysql_mutex_destroy(&LOCK_reset_gtid_table);
2662 mysql_mutex_destroy(&LOCK_compress_gtid_table);
2663 mysql_cond_destroy(&COND_compress_gtid_table);
2664 mysql_mutex_destroy(&LOCK_collect_instance_log);
2665 mysql_mutex_destroy(&LOCK_password_history);
2666 mysql_mutex_destroy(&LOCK_password_reuse_interval);
2667 mysql_cond_destroy(&COND_manager);
2668 #ifdef _WIN32
2669 mysql_cond_destroy(&COND_handler_count);
2670 mysql_mutex_destroy(&LOCK_handler_count);
2671 mysql_rwlock_destroy(&LOCK_named_pipe_full_access_group);
2672 #endif
2673 #ifndef _WIN32
2674 mysql_cond_destroy(&COND_socket_listener_active);
2675 mysql_mutex_destroy(&LOCK_socket_listener_active);
2676 mysql_cond_destroy(&COND_start_signal_handler);
2677 mysql_mutex_destroy(&LOCK_start_signal_handler);
2678 #endif
2679 mysql_mutex_destroy(&LOCK_keyring_operations);
2680 mysql_mutex_destroy(&LOCK_tls_ctx_options);
2681 mysql_mutex_destroy(&LOCK_rotate_binlog_master_key);
2682 mysql_mutex_destroy(&LOCK_admin_tls_ctx_options);
2683 }
2684
2685 /****************************************************************************
2686 ** Init IP and UNIX socket
2687 ****************************************************************************/
2688
set_ports()2689 static void set_ports() {
2690 char *env;
2691 if (!mysqld_port &&
2692 !opt_disable_networking) { // Get port if not from commandline
2693 mysqld_port = MYSQL_PORT;
2694
2695 /*
2696 if builder specifically requested a default port, use that
2697 (even if it coincides with our factory default).
2698 only if they didn't do we check /etc/services (and, failing
2699 on that, fall back to the factory default of 3306).
2700 either default can be overridden by the environment variable
2701 MYSQL_TCP_PORT, which in turn can be overridden with command
2702 line options.
2703 */
2704
2705 #if MYSQL_PORT_DEFAULT == 0
2706 struct servent *serv_ptr;
2707 if ((serv_ptr = getservbyname("mysql", "tcp")))
2708 mysqld_port = ntohs((u_short)serv_ptr->s_port); /* purecov: inspected */
2709 #endif
2710 if ((env = getenv("MYSQL_TCP_PORT")))
2711 mysqld_port = (uint)atoi(env); /* purecov: inspected */
2712 }
2713 if (!mysqld_unix_port) {
2714 #ifdef _WIN32
2715 mysqld_unix_port = (char *)MYSQL_NAMEDPIPE;
2716 #else
2717 mysqld_unix_port = MYSQL_UNIX_ADDR;
2718 #endif
2719 if ((env = getenv("MYSQL_UNIX_PORT")))
2720 mysqld_unix_port = env; /* purecov: inspected */
2721 }
2722 }
2723
2724 #if !defined(_WIN32)
2725 /* Change to run as another user if started with --user */
2726
check_user(const char * user)2727 static PasswdValue check_user(const char *user) {
2728 uid_t user_id = geteuid();
2729
2730 PasswdValue tmp_user_info =
2731 (user == nullptr ? PasswdValue{} : my_getpwnam(user));
2732
2733 // Don't bother if we aren't superuser
2734 if (user_id) {
2735 if (user) {
2736 /* Don't give a warning, if real user is same as given with --user */
2737 if ((tmp_user_info.IsVoid() || user_id != tmp_user_info.pw_uid))
2738 LogErr(WARNING_LEVEL, ER_USER_REQUIRES_ROOT);
2739 }
2740 return PasswdValue{};
2741 }
2742 DBUG_ASSERT(user_id == 0); // we are running as root
2743
2744 if (!user) {
2745 if (!opt_initialize && !is_help_or_validate_option()) {
2746 LogErr(ERROR_LEVEL, ER_REALLY_RUN_AS_ROOT);
2747 unireg_abort(MYSQLD_ABORT_EXIT);
2748 }
2749 return PasswdValue{};
2750 }
2751 /* purecov: begin tested */
2752 if (!strcmp(user, "root"))
2753 return PasswdValue{}; // Avoid problem with dynamic libraries
2754
2755 if (tmp_user_info.IsVoid()) {
2756 // Allow a numeric uid to be used
2757 const char *pos;
2758 for (pos = user; my_isdigit(mysqld_charset, *pos); pos++)
2759 ;
2760 if (*pos) // Not numeric id
2761 goto err;
2762
2763 tmp_user_info = my_getpwuid(atoi(user));
2764 if (tmp_user_info.IsVoid()) goto err;
2765 }
2766 return tmp_user_info;
2767 /* purecov: end */
2768
2769 err:
2770 LogErr(ERROR_LEVEL, ER_USER_WHAT_USER, user);
2771 unireg_abort(MYSQLD_ABORT_EXIT);
2772
2773 return PasswdValue{};
2774 }
2775
2776 namespace mysqld_funcs_unit_test {
check_user_drv(const char * user)2777 PasswdValue check_user_drv(const char *user) { return check_user(user); }
2778 } // namespace mysqld_funcs_unit_test
2779
set_user(const char * user,const PasswdValue & user_info_arg)2780 static void set_user(const char *user, const PasswdValue &user_info_arg) {
2781 /* purecov: begin tested */
2782 DBUG_ASSERT(user_info_arg.IsVoid() == false);
2783 #ifdef HAVE_INITGROUPS
2784 initgroups(user, user_info_arg.pw_gid);
2785 #endif
2786 if (setgid(user_info_arg.pw_gid) == -1) {
2787 LogErr(ERROR_LEVEL, ER_FAIL_SETGID, strerror(errno));
2788 unireg_abort(MYSQLD_ABORT_EXIT);
2789 }
2790 if (setuid(user_info_arg.pw_uid) == -1) {
2791 LogErr(ERROR_LEVEL, ER_FAIL_SETUID, strerror(errno));
2792 unireg_abort(MYSQLD_ABORT_EXIT);
2793 }
2794
2795 #ifdef HAVE_SYS_PRCTL_H
2796 if (test_flags & TEST_CORE_ON_SIGNAL) {
2797 /* inform kernel that process is dumpable */
2798 (void)prctl(PR_SET_DUMPABLE, 1);
2799 }
2800 #endif
2801
2802 /* purecov: end */
2803 }
2804
set_effective_user(const PasswdValue & user_info_arg)2805 static void set_effective_user(const PasswdValue &user_info_arg) {
2806 DBUG_ASSERT(user_info_arg.IsVoid() == false);
2807 if (setregid((gid_t)-1, user_info_arg.pw_gid) == -1) {
2808 LogErr(ERROR_LEVEL, ER_FAIL_SETREGID, strerror(errno));
2809 unireg_abort(MYSQLD_ABORT_EXIT);
2810 }
2811 if (setreuid((uid_t)-1, user_info_arg.pw_uid) == -1) {
2812 LogErr(ERROR_LEVEL, ER_FAIL_SETREUID, strerror(errno));
2813 unireg_abort(MYSQLD_ABORT_EXIT);
2814 }
2815 }
2816
2817 /** Change root user if started with @c --chroot . */
set_root(const char * path)2818 static void set_root(const char *path) {
2819 if (chroot(path) == -1) {
2820 LogErr(ERROR_LEVEL, ER_FAIL_CHROOT, strerror(errno));
2821 unireg_abort(MYSQLD_ABORT_EXIT);
2822 }
2823 my_setwd("/", MYF(0));
2824 }
2825 #endif // !_WIN32
2826
2827 /**
2828 Check that an address value is a wildcard IP value,
2829 that is it has either the value 0.0.0.0 for IPv4 or the value ::1 in
2830 case IPv6, or has the specially treated symbol * as its value.
2831
2832 @param address_value Address value to check
2833 @param address_length Address length
2834
2835 @return true in case the address value is a wildcard value, else false.
2836 */
check_address_is_wildcard(const char * address_value,size_t address_length)2837 bool check_address_is_wildcard(const char *address_value,
2838 size_t address_length) {
2839 return
2840 // Wildcard is not allowed in case a comma separated list of
2841 // addresses is specified
2842 native_strncasecmp(address_value, MY_BIND_ALL_ADDRESSES,
2843 address_length) == 0 ||
2844 // The specially treated address :: is not allowed in case
2845 // a comma separated list of addresses is specified
2846 native_strncasecmp(address_value, ipv6_all_addresses, address_length) ==
2847 0 ||
2848 // The specially treated address 0.0.0.0 is not allowed in case
2849 // a comma separated list of addresses is specified
2850 native_strncasecmp(address_value, ipv4_all_addresses, address_length) ==
2851 0;
2852 }
2853
2854 /**
2855 Take a string representing host or ip address followed by
2856 optional delimiter '/' and namespace name and put address part
2857 and namespace part into corresponding output parameters.
2858
2859 @param begin_address_value start of a string containing an address value
2860 @param end_address_value pointer to an end of string containing
2861 an address value. Has the value nullptr in case
2862 address value not continue
2863 @param [out] address_value address value extracted from address string
2864 @param [out] network_namespace network namespace extracted from
2865 the address string value if any
2866
2867 @return false on success, true on address format error
2868 */
parse_address_string(const char * begin_address_value,const char * end_address_value,std::string * address_value,std::string * network_namespace)2869 static bool parse_address_string(const char *begin_address_value,
2870 const char *end_address_value,
2871 std::string *address_value,
2872 std::string *network_namespace) {
2873 const char *namespace_separator = strchr(begin_address_value, '/');
2874
2875 if (namespace_separator != nullptr) {
2876 if (begin_address_value == namespace_separator)
2877 /*
2878 Parse error: there is no character before '/',
2879 that is missed address value
2880 */
2881 return true;
2882
2883 if (namespace_separator < end_address_value) {
2884 if (end_address_value - namespace_separator == 1)
2885 /*
2886 Parse error: there is no character immediately after '/',
2887 that is missed namespace name.
2888 */
2889 return true;
2890
2891 /*
2892 Found namespace delimiter. Extract namespace and address values
2893 */
2894 *address_value = std::string(begin_address_value, namespace_separator);
2895 *network_namespace =
2896 std::string(namespace_separator + 1, end_address_value);
2897 } else if (end_address_value != nullptr)
2898 /*
2899 This branch corresponds to the case when namespace separator is located
2900 after the last character of the address subvalue being processed.
2901 For example, if the following string '192.168.1.1,172.1.1.1/red'
2902 passed into the function create_bind_address_info_from_string(),
2903 then during handling of the address 192.168.1.1 search of '/'
2904 will return a position after the end of the sub string 192.168.1.1
2905 (in the next sub string 172.1.1.1/red) that should be ignored.
2906 */
2907 *address_value = std::string(begin_address_value, end_address_value);
2908 else {
2909 /*
2910 This branch corresponds to the case when namespace separator is located
2911 at the last part of address values. For example,
2912 this branch is executed during handling of the following value
2913 192.168.1.1,::1,::1/greeen for the option --bind-address.
2914 */
2915 *address_value = std::string(begin_address_value, namespace_separator);
2916 *network_namespace = std::string(namespace_separator + 1);
2917 if (*(namespace_separator + 1) == 0)
2918 /*
2919 Parse error: there is no character immediately
2920 after '/' - a namespace name missed.
2921 */
2922 return true;
2923 }
2924 } else {
2925 /*
2926 Regular address without network namespace found.
2927 */
2928 *address_value = end_address_value != nullptr
2929 ? std::string(begin_address_value, end_address_value)
2930 : std::string(begin_address_value);
2931 }
2932
2933 return false;
2934 }
2935
2936 /**
2937 Parse a value of address sub string with checking of address string format,
2938 extract address part and namespace part of the address value, and store
2939 their values into the argument valid_bind_addresses.
2940
2941 @return false on success, true on address format error
2942 */
create_bind_address_info_from_string(const char * begin_address_value,const char * end_address_value,std::list<Bind_address_info> * valid_bind_addresses)2943 static bool create_bind_address_info_from_string(
2944 const char *begin_address_value, const char *end_address_value,
2945 std::list<Bind_address_info> *valid_bind_addresses) {
2946 Bind_address_info bind_address_info;
2947 std::string address_value, network_namespace;
2948
2949 if (parse_address_string(begin_address_value, end_address_value,
2950 &address_value, &network_namespace))
2951 return true;
2952
2953 if (network_namespace.empty())
2954 bind_address_info = Bind_address_info(address_value);
2955 else {
2956 /*
2957 Wildcard value is not allowed in case network namespace specified
2958 for address value in the option bind-address.
2959 */
2960 if (check_address_is_wildcard(address_value.c_str(),
2961 address_value.length())) {
2962 LogErr(ERROR_LEVEL,
2963 ER_NETWORK_NAMESPACE_NOT_ALLOWED_FOR_WILDCARD_ADDRESS);
2964 return true;
2965 }
2966
2967 bind_address_info = Bind_address_info(address_value, network_namespace);
2968 }
2969
2970 valid_bind_addresses->emplace_back(bind_address_info);
2971
2972 return false;
2973 }
2974
2975 /**
2976 Check acceptable value(s) of parameter bind-address
2977
2978 @param bind_address Value of the parameter bind-address
2979 @param[out] valid_bind_addresses List of addresses to listen and their
2980 corresponding network namespaces if set.
2981
2982 @return false on success, true on failure
2983 */
check_bind_address_has_valid_value(const char * bind_address,std::list<Bind_address_info> * valid_bind_addresses)2984 static bool check_bind_address_has_valid_value(
2985 const char *bind_address,
2986 std::list<Bind_address_info> *valid_bind_addresses) {
2987 if (strlen(bind_address) == 0)
2988 // Empty value for bind_address is an error
2989 return true;
2990
2991 const char *comma_separator = strchr(bind_address, ',');
2992 const char *begin_of_value = bind_address;
2993 const bool multiple_bind_addresses = (comma_separator != nullptr);
2994
2995 if (comma_separator == begin_of_value)
2996 // Return an error if a value of bind_address begins with comma
2997 return true;
2998
2999 while (comma_separator != nullptr) {
3000 Bind_address_info bind_address_info;
3001 std::string address_value, network_namespace;
3002 /*
3003 Wildcard value is not allowed in case multi-addresses value specified
3004 for the option bind-address.
3005 */
3006 if (check_address_is_wildcard(begin_of_value,
3007 comma_separator - begin_of_value)) {
3008 LogErr(ERROR_LEVEL, ER_WILDCARD_NOT_ALLOWED_FOR_MULTIADDRESS_BIND);
3009
3010 return true;
3011 }
3012
3013 if (create_bind_address_info_from_string(begin_of_value, comma_separator,
3014 valid_bind_addresses))
3015 return true;
3016
3017 begin_of_value = comma_separator + 1;
3018 comma_separator = strchr(begin_of_value, ',');
3019 if (comma_separator == begin_of_value)
3020 // Return an error if a value of bind_address has two adjacent commas
3021 return true;
3022 }
3023
3024 /*
3025 Wildcard value is not allowed in case multi-addresses value specified
3026 for the option bind-address.
3027 */
3028 if (multiple_bind_addresses &&
3029 (check_address_is_wildcard(begin_of_value, strlen(begin_of_value)) ||
3030 strlen(begin_of_value) == 0))
3031 return true;
3032
3033 if (create_bind_address_info_from_string(begin_of_value, comma_separator,
3034 valid_bind_addresses))
3035 return true;
3036
3037 return false;
3038 }
3039
3040 /**
3041 Check acceptable value(s) of the parameter admin-address
3042
3043 @param admin_bind_addr_str Value of the parameter admin-address
3044 @param[out] admin_address_info List of addresses to listen and their
3045 corresponding network namespaces if set.
3046
3047 @return false on success, true on failure
3048 */
check_admin_address_has_valid_value(const char * admin_bind_addr_str,Bind_address_info * admin_address_info)3049 static bool check_admin_address_has_valid_value(
3050 const char *admin_bind_addr_str, Bind_address_info *admin_address_info) {
3051 std::string address_value, network_namespace;
3052
3053 if (parse_address_string(admin_bind_addr_str, nullptr, &address_value,
3054 &network_namespace))
3055 return true;
3056
3057 if (check_address_is_wildcard(address_value.c_str(),
3058 address_value.length())) {
3059 if (!network_namespace.empty())
3060 LogErr(ERROR_LEVEL,
3061 ER_NETWORK_NAMESPACE_NOT_ALLOWED_FOR_WILDCARD_ADDRESS);
3062
3063 return true;
3064 }
3065
3066 if (network_namespace.empty())
3067 *admin_address_info = Bind_address_info(address_value);
3068 else
3069 *admin_address_info = Bind_address_info(address_value, network_namespace);
3070
3071 return false;
3072 }
3073
network_init(void)3074 static bool network_init(void) {
3075 if (opt_initialize) return false;
3076
3077 #ifdef HAVE_SYS_UN_H
3078 std::string const unix_sock_name(mysqld_unix_port ? mysqld_unix_port : "");
3079 #else
3080 std::string const unix_sock_name("");
3081 #endif
3082
3083 std::list<Bind_address_info> bind_addresses_info;
3084
3085 if (!opt_disable_networking || unix_sock_name != "") {
3086 if (my_bind_addr_str != nullptr &&
3087 check_bind_address_has_valid_value(my_bind_addr_str,
3088 &bind_addresses_info)) {
3089 LogErr(ERROR_LEVEL, ER_INVALID_VALUE_OF_BIND_ADDRESSES, my_bind_addr_str);
3090 return true;
3091 }
3092
3093 Bind_address_info admin_address_info;
3094 if (!opt_disable_networking) {
3095 if (my_admin_bind_addr_str != nullptr &&
3096 check_admin_address_has_valid_value(my_admin_bind_addr_str,
3097 &admin_address_info)) {
3098 LogErr(ERROR_LEVEL, ER_INVALID_ADMIN_ADDRESS, my_admin_bind_addr_str);
3099 return true;
3100 }
3101 /*
3102 Port 0 is interpreted by implementations of TCP protocol
3103 as a hint to find a first free port value to use and bind to it.
3104 On the other hand, the option mysqld_admin_port can be assigned
3105 the value 0 if a user specified a value that is out of allowable
3106 range of values. Therefore, to avoid a case when an operating
3107 system binds admin interface to am arbitrary selected port value,
3108 set it explicitly to the value MYSQL_ADMIN_PORT in case it has value 0.
3109 */
3110 if (mysqld_admin_port == 0) mysqld_admin_port = MYSQL_ADMIN_PORT;
3111 }
3112 Mysqld_socket_listener *mysqld_socket_listener = new (std::nothrow)
3113 Mysqld_socket_listener(bind_addresses_info, mysqld_port,
3114 admin_address_info, mysqld_admin_port,
3115 admin_address_info.address.empty()
3116 ? false
3117 : listen_admin_interface_in_separate_thread,
3118 back_log, mysqld_port_timeout, unix_sock_name);
3119 if (mysqld_socket_listener == nullptr) return true;
3120
3121 mysqld_socket_acceptor = new (std::nothrow)
3122 Connection_acceptor<Mysqld_socket_listener>(mysqld_socket_listener);
3123 if (mysqld_socket_acceptor == nullptr) {
3124 delete mysqld_socket_listener;
3125 mysqld_socket_listener = nullptr;
3126 return true;
3127 }
3128
3129 if (mysqld_socket_acceptor->init_connection_acceptor())
3130 return true; // mysqld_socket_acceptor would be freed in unireg_abort.
3131
3132 if (report_port == 0) report_port = mysqld_port;
3133
3134 if (!opt_disable_networking) DBUG_ASSERT(report_port != 0);
3135 }
3136 #ifdef _WIN32
3137 // Create named pipe
3138 if (opt_enable_named_pipe) {
3139 std::string pipe_name = mysqld_unix_port ? mysqld_unix_port : "";
3140
3141 named_pipe_listener = new (std::nothrow) Named_pipe_listener(&pipe_name);
3142 if (named_pipe_listener == NULL) return true;
3143
3144 named_pipe_acceptor = new (std::nothrow)
3145 Connection_acceptor<Named_pipe_listener>(named_pipe_listener);
3146 if (named_pipe_acceptor == NULL) {
3147 delete named_pipe_listener;
3148 named_pipe_listener = NULL;
3149 return true;
3150 }
3151
3152 if (named_pipe_acceptor->init_connection_acceptor())
3153 return true; // named_pipe_acceptor would be freed in unireg_abort.
3154 }
3155
3156 // Setup shared_memory acceptor
3157 if (opt_enable_shared_memory) {
3158 std::string shared_mem_base_name =
3159 shared_memory_base_name ? shared_memory_base_name : "";
3160
3161 Shared_mem_listener *shared_mem_listener =
3162 new (std::nothrow) Shared_mem_listener(&shared_mem_base_name);
3163 if (shared_mem_listener == NULL) return true;
3164
3165 shared_mem_acceptor = new (std::nothrow)
3166 Connection_acceptor<Shared_mem_listener>(shared_mem_listener);
3167 if (shared_mem_acceptor == NULL) {
3168 delete shared_mem_listener;
3169 shared_mem_listener = NULL;
3170 return true;
3171 }
3172
3173 if (shared_mem_acceptor->init_connection_acceptor())
3174 return true; // shared_mem_acceptor would be freed in unireg_abort.
3175 }
3176 #endif // _WIN32
3177 return false;
3178 }
3179
3180 #ifdef _WIN32
3181 static uint handler_count = 0;
3182
decrement_handler_count()3183 static inline void decrement_handler_count() {
3184 mysql_mutex_lock(&LOCK_handler_count);
3185 handler_count--;
3186 mysql_cond_signal(&COND_handler_count);
3187 mysql_mutex_unlock(&LOCK_handler_count);
3188 }
3189
socket_conn_event_handler(void * arg)3190 extern "C" void *socket_conn_event_handler(void *arg) {
3191 my_thread_init();
3192
3193 Connection_acceptor<Mysqld_socket_listener> *conn_acceptor =
3194 static_cast<Connection_acceptor<Mysqld_socket_listener> *>(arg);
3195 conn_acceptor->connection_event_loop();
3196
3197 decrement_handler_count();
3198 my_thread_end();
3199 return 0;
3200 }
3201
named_pipe_conn_event_handler(void * arg)3202 extern "C" void *named_pipe_conn_event_handler(void *arg) {
3203 my_thread_init();
3204
3205 Connection_acceptor<Named_pipe_listener> *conn_acceptor =
3206 static_cast<Connection_acceptor<Named_pipe_listener> *>(arg);
3207 conn_acceptor->connection_event_loop();
3208
3209 decrement_handler_count();
3210 my_thread_end();
3211 return 0;
3212 }
3213
shared_mem_conn_event_handler(void * arg)3214 extern "C" void *shared_mem_conn_event_handler(void *arg) {
3215 my_thread_init();
3216
3217 Connection_acceptor<Shared_mem_listener> *conn_acceptor =
3218 static_cast<Connection_acceptor<Shared_mem_listener> *>(arg);
3219 conn_acceptor->connection_event_loop();
3220
3221 decrement_handler_count();
3222 my_thread_end();
3223 return 0;
3224 }
3225
setup_conn_event_handler_threads()3226 void setup_conn_event_handler_threads() {
3227 my_thread_handle hThread;
3228
3229 DBUG_TRACE;
3230
3231 if ((!have_tcpip || opt_disable_networking) && !opt_enable_shared_memory &&
3232 !opt_enable_named_pipe) {
3233 LogErr(ERROR_LEVEL, ER_WIN_LISTEN_BUT_HOW);
3234 unireg_abort(MYSQLD_ABORT_EXIT); // Will not return
3235 }
3236
3237 mysql_mutex_lock(&LOCK_handler_count);
3238 handler_count = 0;
3239
3240 if (opt_enable_named_pipe) {
3241 int error = mysql_thread_create(
3242 key_thread_handle_con_namedpipes, &hThread, &connection_attrib,
3243 named_pipe_conn_event_handler, named_pipe_acceptor);
3244 if (!error)
3245 handler_count++;
3246 else
3247 LogErr(WARNING_LEVEL, ER_CANT_CREATE_NAMED_PIPES_THREAD, error);
3248 }
3249
3250 if (have_tcpip && !opt_disable_networking) {
3251 int error = mysql_thread_create(
3252 key_thread_handle_con_sockets, &hThread, &connection_attrib,
3253 socket_conn_event_handler, mysqld_socket_acceptor);
3254 if (!error)
3255 handler_count++;
3256 else
3257 LogErr(WARNING_LEVEL, ER_CANT_CREATE_TCPIP_THREAD, error);
3258 }
3259
3260 if (opt_enable_shared_memory) {
3261 int error = mysql_thread_create(
3262 key_thread_handle_con_sharedmem, &hThread, &connection_attrib,
3263 shared_mem_conn_event_handler, shared_mem_acceptor);
3264 if (!error)
3265 handler_count++;
3266 else
3267 LogErr(WARNING_LEVEL, ER_CANT_CREATE_SHM_THREAD, error);
3268 }
3269
3270 // Block until all connection listener threads have exited.
3271 while (handler_count > 0)
3272 mysql_cond_wait(&COND_handler_count, &LOCK_handler_count);
3273 mysql_mutex_unlock(&LOCK_handler_count);
3274 }
3275
3276 /*
3277 On Windows, we use native SetConsoleCtrlHandler for handle events like Ctrl-C
3278 with graceful shutdown.
3279 Also, we do not use signal(), but SetUnhandledExceptionFilter instead - as it
3280 provides possibility to pass the exception to just-in-time debugger, collect
3281 dumps and potentially also the exception and thread context used to output
3282 callstack.
3283 */
3284
console_event_handler(DWORD type)3285 static BOOL WINAPI console_event_handler(DWORD type) {
3286 DBUG_TRACE;
3287 if (type == CTRL_C_EVENT) {
3288 /*
3289 Do not shutdown before startup is finished and shutdown
3290 thread is initialized. Otherwise there is a race condition
3291 between main thread doing initialization and CTRL-C thread doing
3292 cleanup, which can result into crash.
3293 */
3294 if (hEventShutdown)
3295 kill_mysql();
3296 else
3297 LogErr(WARNING_LEVEL, ER_NOT_RIGHT_NOW);
3298 return true;
3299 }
3300 return false;
3301 }
3302
3303 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
3304 #define DEBUGGER_ATTACH_TIMEOUT 120
3305 /*
3306 Wait for debugger to attach and break into debugger. If debugger is not
3307 attached, resume after timeout.
3308 */
wait_for_debugger(int timeout_sec)3309 static void wait_for_debugger(int timeout_sec) {
3310 if (!IsDebuggerPresent()) {
3311 int i;
3312 printf("Waiting for debugger to attach, pid=%u\n", GetCurrentProcessId());
3313 fflush(stdout);
3314 for (i = 0; i < timeout_sec; i++) {
3315 Sleep(1000);
3316 if (IsDebuggerPresent()) {
3317 /* Break into debugger */
3318 __debugbreak();
3319 return;
3320 }
3321 }
3322 printf("pid=%u, debugger not attached after %d seconds, resuming\n",
3323 GetCurrentProcessId(), timeout_sec);
3324 fflush(stdout);
3325 }
3326 }
3327 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
3328
my_unhandler_exception_filter(EXCEPTION_POINTERS * ex_pointers)3329 LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers) {
3330 static BOOL first_time = true;
3331 if (!first_time) {
3332 /*
3333 This routine can be called twice, typically
3334 when detaching in JIT debugger.
3335 Return EXCEPTION_EXECUTE_HANDLER to terminate process.
3336 */
3337 return EXCEPTION_EXECUTE_HANDLER;
3338 }
3339 first_time = false;
3340 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
3341 /*
3342 Unfortunately there is no clean way to debug unhandled exception filters,
3343 as debugger does not stop there(also documented in MSDN)
3344 To overcome, one could put a MessageBox, but this will not work in service.
3345 Better solution is to print error message and sleep some minutes
3346 until debugger is attached
3347 */
3348 wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT);
3349 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
3350 __try {
3351 my_set_exception_pointers(ex_pointers);
3352 handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
3353 } __except (EXCEPTION_EXECUTE_HANDLER) {
3354 DWORD written;
3355 const char msg[] = "Got exception in exception handler!\n";
3356 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msg, sizeof(msg) - 1, &written,
3357 NULL);
3358 }
3359 /*
3360 Return EXCEPTION_CONTINUE_SEARCH to give JIT debugger
3361 (drwtsn32 or vsjitdebugger) possibility to attach,
3362 if JIT debugger is configured.
3363 Windows Error reporting might generate a dump here.
3364 */
3365 return EXCEPTION_CONTINUE_SEARCH;
3366 }
3367
my_init_signals()3368 void my_init_signals() {
3369 if (opt_console) SetConsoleCtrlHandler(console_event_handler, true);
3370
3371 /* Avoid MessageBox()es*/
3372 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
3373 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3374 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
3375 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3376 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
3377 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3378
3379 /*
3380 Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (),
3381 because it would prevent JIT debugger and Windows error reporting
3382 from working. We need WER or JIT-debugging, since our own unhandled
3383 exception filter is not guaranteed to work in all situation
3384 (like heap corruption or stack overflow)
3385 */
3386 SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS |
3387 SEM_NOOPENFILEERRORBOX);
3388 SetUnhandledExceptionFilter(my_unhandler_exception_filter);
3389 }
3390
3391 #else // !_WIN32
3392
3393 extern "C" {
empty_signal_handler(int sig MY_ATTRIBUTE ((unused)))3394 static void empty_signal_handler(int sig MY_ATTRIBUTE((unused))) {}
3395 }
3396
my_init_signals()3397 void my_init_signals() {
3398 DBUG_TRACE;
3399 struct sigaction sa;
3400 (void)sigemptyset(&sa.sa_mask);
3401
3402 if (!(test_flags & TEST_NO_STACKTRACE) ||
3403 (test_flags & TEST_CORE_ON_SIGNAL)) {
3404 #ifdef HAVE_STACKTRACE
3405 my_init_stacktrace();
3406 #endif
3407
3408 if (test_flags & TEST_CORE_ON_SIGNAL) {
3409 // Change limits so that we will get a core file.
3410 struct rlimit rl;
3411 rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
3412 if (setrlimit(RLIMIT_CORE, &rl)) LogErr(WARNING_LEVEL, ER_CORE_VALUES);
3413 }
3414
3415 /*
3416 SA_RESETHAND resets handler action to default when entering handler.
3417 SA_NODEFER allows receiving the same signal during handler.
3418 E.g. SIGABRT during our signal handler will dump core (default action).
3419 */
3420 sa.sa_flags = SA_RESETHAND | SA_NODEFER;
3421 sa.sa_handler = handle_fatal_signal;
3422 // Treat these as fatal and handle them.
3423 sigaction(SIGABRT, &sa, nullptr);
3424 sigaction(SIGFPE, &sa, nullptr);
3425 // Handle these as well, except for ASAN/UBSAN builds:
3426 // we let sanitizer runtime handle them instead.
3427 #if defined(HANDLE_FATAL_SIGNALS)
3428 sigaction(SIGBUS, &sa, nullptr);
3429 sigaction(SIGILL, &sa, nullptr);
3430 sigaction(SIGSEGV, &sa, nullptr);
3431 #endif
3432 }
3433
3434 // Ignore SIGPIPE
3435 sa.sa_flags = 0;
3436 sa.sa_handler = SIG_IGN;
3437 (void)sigaction(SIGPIPE, &sa, nullptr);
3438
3439 // SIGALRM is used to interrupt the socket listener.
3440 sa.sa_handler = empty_signal_handler;
3441 (void)sigaction(SIGALRM, &sa, nullptr);
3442
3443 // Fix signals if ignored by parents (can happen on Mac OS X).
3444 sa.sa_handler = SIG_DFL;
3445 (void)sigaction(SIGTERM, &sa, nullptr);
3446 (void)sigaction(SIGHUP, &sa, nullptr);
3447 (void)sigaction(SIGUSR1, &sa, nullptr);
3448
3449 (void)sigemptyset(&mysqld_signal_mask);
3450 /*
3451 Block SIGQUIT, SIGHUP, SIGTERM, SIGUSR1 and SIGUSR2.
3452 The signal handler thread does sigwait() on these.
3453 */
3454 (void)sigaddset(&mysqld_signal_mask, SIGQUIT);
3455 (void)sigaddset(&mysqld_signal_mask, SIGHUP);
3456 (void)sigaddset(&mysqld_signal_mask, SIGTERM);
3457 (void)sigaddset(&mysqld_signal_mask, SIGTSTP);
3458 (void)sigaddset(&mysqld_signal_mask, SIGUSR1);
3459 (void)sigaddset(&mysqld_signal_mask, SIGUSR2);
3460 /*
3461 Block SIGINT unless debugging to prevent Ctrl+C from causing
3462 unclean shutdown of the server.
3463 */
3464 if (!(test_flags & TEST_SIGINT)) (void)sigaddset(&mysqld_signal_mask, SIGINT);
3465 pthread_sigmask(SIG_SETMASK, &mysqld_signal_mask, nullptr);
3466 }
3467
start_signal_handler()3468 static void start_signal_handler() {
3469 int error;
3470 my_thread_attr_t thr_attr;
3471 DBUG_TRACE;
3472
3473 (void)my_thread_attr_init(&thr_attr);
3474 (void)pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
3475 (void)my_thread_attr_setdetachstate(&thr_attr, MY_THREAD_CREATE_JOINABLE);
3476
3477 size_t guardize = 0;
3478 (void)pthread_attr_getguardsize(&thr_attr, &guardize);
3479 #if defined(__ia64__) || defined(__ia64)
3480 /*
3481 Peculiar things with ia64 platforms - it seems we only have half the
3482 stack size in reality, so we have to double it here
3483 */
3484 guardize = my_thread_stack_size;
3485 #endif
3486 if (0 !=
3487 my_thread_attr_setstacksize(&thr_attr, my_thread_stack_size + guardize)) {
3488 DBUG_ASSERT(false);
3489 }
3490
3491 /*
3492 Set main_thread_id so that SIGTERM/SIGQUIT/SIGKILL/SIGUSR2 can interrupt
3493 the socket listener successfully.
3494 */
3495 main_thread_id = my_thread_self();
3496
3497 mysql_mutex_lock(&LOCK_start_signal_handler);
3498 if ((error = mysql_thread_create(key_thread_signal_hand, &signal_thread_id,
3499 &thr_attr, signal_hand, nullptr))) {
3500 LogErr(ERROR_LEVEL, ER_CANT_CREATE_INTERRUPT_THREAD, error, errno);
3501 flush_error_log_messages();
3502 exit(MYSQLD_ABORT_EXIT);
3503 }
3504 mysql_cond_wait(&COND_start_signal_handler, &LOCK_start_signal_handler);
3505 mysql_mutex_unlock(&LOCK_start_signal_handler);
3506
3507 (void)my_thread_attr_destroy(&thr_attr);
3508 }
3509
3510 /** This thread handles SIGTERM, SIGQUIT, SIGHUP, SIGUSR1 and SIGUSR2 signals.
3511 */
3512 /* ARGSUSED */
signal_hand(void * arg MY_ATTRIBUTE ((unused)))3513 extern "C" void *signal_hand(void *arg MY_ATTRIBUTE((unused))) {
3514 my_thread_init();
3515
3516 sigset_t set;
3517 (void)sigemptyset(&set);
3518 (void)sigaddset(&set, SIGTERM);
3519 (void)sigaddset(&set, SIGQUIT);
3520 (void)sigaddset(&set, SIGHUP);
3521 (void)sigaddset(&set, SIGUSR1);
3522 (void)sigaddset(&set, SIGUSR2);
3523
3524 /*
3525 Signal to start_signal_handler that we are ready.
3526 This works by waiting for start_signal_handler to free mutex,
3527 after which we signal it that we are ready.
3528 */
3529 mysql_mutex_lock(&LOCK_start_signal_handler);
3530 mysql_cond_broadcast(&COND_start_signal_handler);
3531 mysql_mutex_unlock(&LOCK_start_signal_handler);
3532
3533 /*
3534 Wait until that all server components have been successfully initialized.
3535 This step is mandatory since signal processing can be done safely only when
3536 all server components have been initialized.
3537 */
3538 server_components_init_wait();
3539 for (;;) {
3540 int sig = 0;
3541 int rc;
3542 bool error;
3543 #ifdef __APPLE__
3544 while ((rc = sigwait(&set, &sig)) == EINTR) {
3545 }
3546 error = rc != 0;
3547 #else
3548 siginfo_t sig_info;
3549 while ((rc = sigwaitinfo(&set, &sig_info)) == -1 && errno == EINTR) {
3550 }
3551 error = rc == -1;
3552 if (!error) sig = sig_info.si_signo;
3553 #endif // __APPLE__
3554 if (error)
3555 sql_print_error(
3556 "Fatal error in signal handling thread. sigwait/sigwaitinfo returned "
3557 "error %d\n. Exiting signal handler "
3558 "thread.",
3559 errno);
3560
3561 if (error || cleanup_done) {
3562 my_thread_end();
3563 my_thread_exit(nullptr); // Safety
3564 return nullptr; // Avoid compiler warnings
3565 }
3566 switch (sig) {
3567 case SIGUSR2:
3568 signal_hand_thr_exit_code = MYSQLD_RESTART_EXIT;
3569 #ifndef __APPLE__ // Mac OS doesn't have sigwaitinfo.
3570 // Log a note if mysqld is restarted via kill command.
3571 if (sig_info.si_pid != getpid()) {
3572 sql_print_information(
3573 "Received signal SIGUSR2."
3574 " Restarting mysqld (Version %s)",
3575 server_version);
3576 }
3577 #endif // __APPLE__
3578 // fall through
3579 case SIGTERM:
3580 case SIGQUIT:
3581 #ifndef __APPLE__ // Mac OS doesn't have sigwaitinfo.
3582 if (sig_info.si_pid != getpid())
3583 LogErr(SYSTEM_LEVEL, ER_SERVER_SHUTDOWN_INFO, "<via user signal>",
3584 server_version, MYSQL_COMPILATION_COMMENT_SERVER);
3585 #else
3586 LogErr(SYSTEM_LEVEL, ER_SERVER_SHUTDOWN_INFO, "<via user signal>",
3587 server_version, MYSQL_COMPILATION_COMMENT_SERVER);
3588 #endif // __APPLE__
3589 // Switch to the file log message processing.
3590 query_logger.set_handlers((log_output_options != LOG_NONE) ? LOG_FILE
3591 : LOG_NONE);
3592 DBUG_PRINT("info",
3593 ("Got signal: %d connection_events_loop_aborted: %d", sig,
3594 connection_events_loop_aborted()));
3595 if (!connection_events_loop_aborted()) {
3596 // Mark abort for threads.
3597 set_connection_events_loop_aborted(true);
3598 #ifdef HAVE_PSI_THREAD_INTERFACE
3599 // Delete the instrumentation for the signal thread.
3600 PSI_THREAD_CALL(delete_current_thread)();
3601 #endif /* HAVE_PSI_THREAD_INTERFACE */
3602 /*
3603 Kill the socket listener.
3604 The main thread will then set socket_listener_active= false,
3605 and wait for us to finish all the cleanup below.
3606 */
3607 mysql_mutex_lock(&LOCK_socket_listener_active);
3608 while (socket_listener_active) {
3609 DBUG_PRINT("info", ("Killing socket listener"));
3610 if (pthread_kill(main_thread_id, SIGALRM)) {
3611 DBUG_ASSERT(false);
3612 break;
3613 }
3614 mysql_cond_wait(&COND_socket_listener_active,
3615 &LOCK_socket_listener_active);
3616 }
3617 mysql_mutex_unlock(&LOCK_socket_listener_active);
3618
3619 close_connections();
3620 }
3621 my_thread_end();
3622 my_thread_exit(nullptr);
3623 return nullptr; // Avoid compiler warnings
3624 break;
3625 case SIGHUP:
3626 if (!connection_events_loop_aborted()) {
3627 int not_used;
3628 handle_reload_request(
3629 nullptr,
3630 (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST | REFRESH_GRANT |
3631 REFRESH_THREADS | REFRESH_HOSTS),
3632 nullptr, ¬_used); // Flush logs
3633 // Reenable query logs after the options were reloaded.
3634 query_logger.set_handlers(log_output_options);
3635 }
3636 break;
3637 case SIGUSR1:
3638 if (!connection_events_loop_aborted()) {
3639 int not_used;
3640 handle_reload_request(
3641 nullptr,
3642 (REFRESH_ERROR_LOG | /**< Rotate only the error log */
3643 REFRESH_GENERAL_LOG | /**< Flush the general log */
3644 REFRESH_SLOW_LOG), /**< Flush the slow query log */
3645 nullptr, ¬_used); // Flush logs
3646 // Reenable query logs after the options were reloaded.
3647 query_logger.set_handlers(log_output_options);
3648 }
3649 break;
3650 default:
3651 break; /* purecov: tested */
3652 }
3653 }
3654 return nullptr; /* purecov: deadcode */
3655 }
3656
3657 #endif // !_WIN32
3658
3659 /**
3660 All global error messages are sent here where the first one is stored
3661 for the client.
3662 */
3663 /* ARGSUSED */
3664 extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
3665
my_message_sql(uint error,const char * str,myf MyFlags)3666 void my_message_sql(uint error, const char *str, myf MyFlags) {
3667 THD *thd = current_thd;
3668 DBUG_TRACE;
3669 DBUG_PRINT("error", ("error: %u message: '%s'", error, str));
3670
3671 DBUG_ASSERT(str != nullptr);
3672 /*
3673 An error should have a valid error number (!= 0), so it can be caught
3674 in stored procedures by SQL exception handlers.
3675 Calling my_error() with error == 0 is a bug.
3676 Remaining known places to fix:
3677 - storage/myisam/mi_create.c, my_printf_error()
3678 TODO:
3679 DBUG_ASSERT(error != 0);
3680 */
3681
3682 if (error == 0) {
3683 /* At least, prevent new abuse ... */
3684 DBUG_ASSERT(strncmp(str, "MyISAM table", 12) == 0);
3685 error = ER_UNKNOWN_ERROR;
3686 }
3687
3688 /* Caller wishes to inform client, and one is attached. */
3689 if (thd) {
3690 (void)thd->raise_condition(error, nullptr, Sql_condition::SL_ERROR, str,
3691 MyFlags & ME_FATALERROR);
3692
3693 /*
3694 Now for an argument check.
3695 We're asserting after rather than before raising the
3696 condition to make the culprit easier to track down.
3697
3698 Messages intended for the error-log are in the range
3699 starting at ER_SERVER_RANGE_START (error_code 10,000);
3700 messages intended for sending to a client are in the
3701 range below ER_SERVER_RANGE_START. If a message is to
3702 be sent to both a client and the error log, it must
3703 be added twice (once in each range), and two separate
3704 calls (e.g. my_error() and LogErr()) must be added to
3705 the code.
3706
3707 Only error-codes from the client range should be seen
3708 in this if(). If your patch asserts here, one of two
3709 things probably happened:
3710
3711 - You added a new message to messages_to_error_log.txt:
3712 The message was added to the server range, but code
3713 was added that tries to send the message to a client
3714 (my_error(), push_warning_printf(), etc.).
3715
3716 => Move the new message to messages_to_clients.txt.
3717 The copied message should be added at the end of
3718 the range for the lowest server version you're adding
3719 the message to.
3720 Rebuild the server; rerun your test.
3721
3722 - You used an existing message:
3723 The existing message is intended for use with
3724 the error-log (it appears in messages_to_error_log.txt),
3725 but the new code tries to send it to a client (my_error(),
3726 push_warning_printf(), etc.).
3727
3728 => Copy the existing message to messages_to_clients.txt.
3729 - The copied message should be added at the end of
3730 the range for the lowest server version you're adding
3731 the message to.
3732 - The copied message will need its own symbol;
3733 if in doubt, call the copy of ER_EXAMPLE_MESSAGE
3734 ER_DA_EXAMPLE_MESSAGE (as this version is for use
3735 with the diagnostics area).
3736 Then make sure that your new code references
3737 this new symbol when it sends the message
3738 to a client.
3739 Rebuild the server; rerun your test.
3740
3741 We'll assert this here (rather than in raise_condition) as
3742 SQL's SIGNAL command also calls raise_condition, and SIGNAL
3743 is currently allowed to set any error-code (regardless of
3744 range). SIGNALing an error-code from the error-log range
3745 will not result in writing to that log to prevent abuse.
3746 */
3747 DBUG_ASSERT(error < ER_SERVER_RANGE_START);
3748 }
3749
3750 /* When simulating OOM, skip writing to error log to avoid mtr errors */
3751 DBUG_EXECUTE_IF("simulate_out_of_memory", return;);
3752
3753 /*
3754 Caller wishes to send to both the client and the error-log.
3755 This is legacy behaviour that is no longer legal as errors flagged
3756 to a client and those sent to the error-log are in different
3757 numeric ranges now. If you own code that does this, see about
3758 updating it by splitting it into two calls, one sending status
3759 to the client, the other sending it to the error-log using
3760 LogErr() and friends.
3761 */
3762 if (MyFlags & ME_ERRORLOG) {
3763 /*
3764 We've removed most uses of ME_ERRORLOG in the server.
3765 This leaves three possible cases, in which we'll rewrite
3766 the error-code from one in the client-range to one in
3767 the error-log range here:
3768
3769 - EE_OUTOFMEMORY: Correct to ER_SERVER_OUT_OF_RESOURCES so
3770 mysys can remain logger-agnostic.
3771
3772 - HA_* range: Correct to catch-all ER_SERVER_HANDLER_ERROR.
3773
3774 - otherwise: Flag as using info from the diagnostics area
3775 (ER_ERROR_INFO_FROM_DA). This is a failsafe;
3776 if your code triggers it, your code is probably
3777 wrong.
3778 */
3779 if ((error == EE_OUTOFMEMORY) || (error == HA_ERR_OUT_OF_MEM))
3780 error = ER_SERVER_OUT_OF_RESOURCES;
3781 else if (error <= HA_ERR_LAST)
3782 error = ER_SERVER_HANDLER_ERROR;
3783
3784 if (error < ER_SERVER_RANGE_START)
3785 LogEvent()
3786 .type(LOG_TYPE_ERROR)
3787 .prio(ERROR_LEVEL)
3788 .errcode(ER_ERROR_INFO_FROM_DA)
3789 .lookup(ER_ERROR_INFO_FROM_DA, error, str);
3790 else
3791 LogEvent()
3792 .type(LOG_TYPE_ERROR)
3793 .prio(ERROR_LEVEL)
3794 .errcode(error)
3795 .verbatim(str);
3796
3797 /*
3798 This is no longer supported behaviour except for the cases
3799 outlined above, so flag anything else in debug builds!
3800 (We're bailing after rather than before printing to make the
3801 culprit easier to track down.)
3802 */
3803 DBUG_ASSERT((error == ER_FEATURE_NOT_AVAILABLE) ||
3804 (error >= ER_SERVER_RANGE_START));
3805 }
3806
3807 /*
3808 Caller wishes to send to client, but none is attached, so we send
3809 to error-log instead.
3810 */
3811 else if (!thd) {
3812 LogEvent()
3813 .type(LOG_TYPE_ERROR)
3814 .subsys(LOG_SUBSYSTEM_TAG)
3815 .prio(ERROR_LEVEL)
3816 .errcode((error < ER_SERVER_RANGE_START)
3817 ? ER_SERVER_NO_SESSION_TO_SEND_TO
3818 : error)
3819 .lookup(ER_SERVER_NO_SESSION_TO_SEND_TO, error, str);
3820 }
3821 }
3822
3823 extern "C" void *my_str_malloc_mysqld(size_t size);
3824 extern "C" void my_str_free_mysqld(void *ptr);
3825 extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size);
3826
my_str_malloc_mysqld(size_t size)3827 void *my_str_malloc_mysqld(size_t size) {
3828 return my_malloc(key_memory_my_str_malloc, size, MYF(MY_FAE));
3829 }
3830
my_str_free_mysqld(void * ptr)3831 void my_str_free_mysqld(void *ptr) { my_free(ptr); }
3832
my_str_realloc_mysqld(void * ptr,size_t size)3833 void *my_str_realloc_mysqld(void *ptr, size_t size) {
3834 return my_realloc(key_memory_my_str_malloc, ptr, size, MYF(MY_FAE));
3835 }
3836
3837 const char *load_default_groups[] = {
3838 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
3839 "mysql_cluster",
3840 #endif
3841 "mysqld", "server", MYSQL_BASE_VERSION, nullptr, nullptr};
3842
3843 #if defined(_WIN32)
3844 static const int load_default_groups_sz =
3845 sizeof(load_default_groups) / sizeof(load_default_groups[0]);
3846 #endif
3847
3848 /**
3849 This function is used to check for stack overrun for pathological
3850 cases of regular expressions and 'like' expressions.
3851 The call to current_thd is quite expensive, so we try to avoid it
3852 for the normal cases.
3853 The size of each stack frame for the wildcmp() routines is ~128 bytes,
3854 so checking *every* recursive call is not necessary.
3855 */
3856 extern "C" {
check_enough_stack_size(int recurse_level)3857 static int check_enough_stack_size(int recurse_level) {
3858 uchar stack_top;
3859 if (recurse_level % 16 != 0) return 0;
3860
3861 THD *my_thd = current_thd;
3862 if (my_thd != nullptr)
3863 return check_stack_overrun(my_thd, STACK_MIN_SIZE * 4, &stack_top);
3864 return 0;
3865 }
3866 } // extern "C"
3867
3868 SHOW_VAR com_status_vars[] = {
3869 {"admin_commands", (char *)offsetof(System_status_var, com_other),
3870 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3871 {"assign_to_keycache",
3872 (char *)offsetof(System_status_var,
3873 com_stat[(uint)SQLCOM_ASSIGN_TO_KEYCACHE]),
3874 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3875 {"alter_db",
3876 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_DB]),
3877 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3878 {"alter_event",
3879 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_EVENT]),
3880 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3881 {"alter_function",
3882 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_FUNCTION]),
3883 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3884 {"alter_instance",
3885 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_INSTANCE]),
3886 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3887 {"alter_procedure",
3888 (char *)offsetof(System_status_var,
3889 com_stat[(uint)SQLCOM_ALTER_PROCEDURE]),
3890 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3891 {"alter_resource_group",
3892 (char *)offsetof(System_status_var,
3893 com_stat[(uint)SQLCOM_ALTER_RESOURCE_GROUP]),
3894 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3895 {"alter_server",
3896 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_SERVER]),
3897 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3898 {"alter_table",
3899 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_TABLE]),
3900 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3901 {"alter_tablespace",
3902 (char *)offsetof(System_status_var,
3903 com_stat[(uint)SQLCOM_ALTER_TABLESPACE]),
3904 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3905 {"alter_user",
3906 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_USER]),
3907 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3908 {"alter_user_default_role",
3909 (char *)offsetof(System_status_var,
3910 com_stat[(uint)SQLCOM_ALTER_USER_DEFAULT_ROLE]),
3911 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3912 {"analyze",
3913 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ANALYZE]),
3914 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3915 {"begin", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_BEGIN]),
3916 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3917 {"binlog",
3918 (char *)offsetof(System_status_var,
3919 com_stat[(uint)SQLCOM_BINLOG_BASE64_EVENT]),
3920 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3921 {"call_procedure",
3922 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CALL]),
3923 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3924 {"change_db",
3925 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CHANGE_DB]),
3926 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3927 {"change_master",
3928 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CHANGE_MASTER]),
3929 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3930 {"change_repl_filter",
3931 (char *)offsetof(System_status_var,
3932 com_stat[(uint)SQLCOM_CHANGE_REPLICATION_FILTER]),
3933 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3934 {"check", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CHECK]),
3935 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3936 {"checksum",
3937 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CHECKSUM]),
3938 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3939 {"clone", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CLONE]),
3940 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3941 {"commit",
3942 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_COMMIT]),
3943 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3944 {"create_db",
3945 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_DB]),
3946 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3947 {"create_event",
3948 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_EVENT]),
3949 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3950 {"create_function",
3951 (char *)offsetof(System_status_var,
3952 com_stat[(uint)SQLCOM_CREATE_SPFUNCTION]),
3953 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3954 {"create_index",
3955 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_INDEX]),
3956 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3957 {"create_procedure",
3958 (char *)offsetof(System_status_var,
3959 com_stat[(uint)SQLCOM_CREATE_PROCEDURE]),
3960 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3961 {"create_role",
3962 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_ROLE]),
3963 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3964 {"create_server",
3965 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_SERVER]),
3966 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3967 {"create_table",
3968 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_TABLE]),
3969 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3970 {"create_resource_group",
3971 (char *)offsetof(System_status_var,
3972 com_stat[(uint)SQLCOM_CREATE_RESOURCE_GROUP]),
3973 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3974 {"create_trigger",
3975 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_TRIGGER]),
3976 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3977 {"create_udf",
3978 (char *)offsetof(System_status_var,
3979 com_stat[(uint)SQLCOM_CREATE_FUNCTION]),
3980 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3981 {"create_user",
3982 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_USER]),
3983 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3984 {"create_view",
3985 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_VIEW]),
3986 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3987 {"create_spatial_reference_system",
3988 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_SRS]),
3989 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3990 {"dealloc_sql",
3991 (char *)offsetof(System_status_var,
3992 com_stat[(uint)SQLCOM_DEALLOCATE_PREPARE]),
3993 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3994 {"delete",
3995 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DELETE]),
3996 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3997 {"delete_multi",
3998 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DELETE_MULTI]),
3999 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4000 {"do", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DO]),
4001 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4002 {"drop_db",
4003 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_DB]),
4004 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4005 {"drop_event",
4006 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_EVENT]),
4007 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4008 {"drop_function",
4009 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_FUNCTION]),
4010 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4011 {"drop_index",
4012 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_INDEX]),
4013 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4014 {"drop_procedure",
4015 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_PROCEDURE]),
4016 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4017 {"drop_resource_group",
4018 (char *)offsetof(System_status_var,
4019 com_stat[(uint)SQLCOM_DROP_RESOURCE_GROUP]),
4020 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4021 {"drop_role",
4022 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_ROLE]),
4023 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4024 {"drop_server",
4025 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_SERVER]),
4026 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4027 {"drop_spatial_reference_system",
4028 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_SRS]),
4029 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4030 {"drop_table",
4031 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_TABLE]),
4032 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4033 {"drop_trigger",
4034 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_TRIGGER]),
4035 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4036 {"drop_user",
4037 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_USER]),
4038 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4039 {"drop_view",
4040 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_VIEW]),
4041 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4042 {"empty_query",
4043 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_EMPTY_QUERY]),
4044 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4045 {"execute_sql",
4046 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_EXECUTE]),
4047 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4048 {"explain_other",
4049 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_EXPLAIN_OTHER]),
4050 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4051 {"flush", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_FLUSH]),
4052 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4053 {"get_diagnostics",
4054 (char *)offsetof(System_status_var,
4055 com_stat[(uint)SQLCOM_GET_DIAGNOSTICS]),
4056 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4057 {"grant", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_GRANT]),
4058 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4059 {"grant_roles",
4060 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_GRANT_ROLE]),
4061 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4062 {"ha_close",
4063 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_HA_CLOSE]),
4064 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4065 {"ha_open",
4066 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_HA_OPEN]),
4067 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4068 {"ha_read",
4069 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_HA_READ]),
4070 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4071 {"help", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_HELP]),
4072 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4073 {"import",
4074 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_IMPORT]),
4075 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4076 {"insert",
4077 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_INSERT]),
4078 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4079 {"insert_select",
4080 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_INSERT_SELECT]),
4081 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4082 {"install_component",
4083 (char *)offsetof(System_status_var,
4084 com_stat[(uint)SQLCOM_INSTALL_COMPONENT]),
4085 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4086 {"install_plugin",
4087 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_INSTALL_PLUGIN]),
4088 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4089 {"kill", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_KILL]),
4090 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4091 {"load", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_LOAD]),
4092 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4093 {"lock_instance",
4094 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_LOCK_INSTANCE]),
4095 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4096 {"lock_tables",
4097 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_LOCK_TABLES]),
4098 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4099 {"optimize",
4100 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_OPTIMIZE]),
4101 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4102 {"preload_keys",
4103 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_PRELOAD_KEYS]),
4104 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4105 {"prepare_sql",
4106 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_PREPARE]),
4107 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4108 {"purge", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_PURGE]),
4109 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4110 {"purge_before_date",
4111 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_PURGE_BEFORE]),
4112 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4113 {"release_savepoint",
4114 (char *)offsetof(System_status_var,
4115 com_stat[(uint)SQLCOM_RELEASE_SAVEPOINT]),
4116 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4117 {"rename_table",
4118 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RENAME_TABLE]),
4119 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4120 {"rename_user",
4121 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RENAME_USER]),
4122 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4123 {"repair",
4124 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REPAIR]),
4125 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4126 {"replace",
4127 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REPLACE]),
4128 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4129 {"replace_select",
4130 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REPLACE_SELECT]),
4131 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4132 {"reset", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RESET]),
4133 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4134 {"resignal",
4135 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RESIGNAL]),
4136 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4137 {"restart",
4138 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RESTART_SERVER]),
4139 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4140 {"revoke",
4141 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REVOKE]),
4142 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4143 {"revoke_all",
4144 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REVOKE_ALL]),
4145 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4146 {"revoke_roles",
4147 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REVOKE_ROLE]),
4148 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4149 {"rollback",
4150 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ROLLBACK]),
4151 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4152 {"rollback_to_savepoint",
4153 (char *)offsetof(System_status_var,
4154 com_stat[(uint)SQLCOM_ROLLBACK_TO_SAVEPOINT]),
4155 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4156 {"savepoint",
4157 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SAVEPOINT]),
4158 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4159 {"select",
4160 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SELECT]),
4161 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4162 {"set_option",
4163 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SET_OPTION]),
4164 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4165 {"set_password",
4166 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SET_PASSWORD]),
4167 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4168 {"set_resource_group",
4169 (char *)offsetof(System_status_var,
4170 com_stat[(uint)SQLCOM_SET_RESOURCE_GROUP]),
4171 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4172 {"set_role",
4173 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SET_ROLE]),
4174 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4175 {"signal",
4176 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SIGNAL]),
4177 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4178 {"show_binlog_events",
4179 (char *)offsetof(System_status_var,
4180 com_stat[(uint)SQLCOM_SHOW_BINLOG_EVENTS]),
4181 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4182 {"show_binlogs",
4183 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_BINLOGS]),
4184 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4185 {"show_charsets",
4186 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_CHARSETS]),
4187 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4188 {"show_collations",
4189 (char *)offsetof(System_status_var,
4190 com_stat[(uint)SQLCOM_SHOW_COLLATIONS]),
4191 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4192 {"show_create_db",
4193 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_CREATE_DB]),
4194 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4195 {"show_create_event",
4196 (char *)offsetof(System_status_var,
4197 com_stat[(uint)SQLCOM_SHOW_CREATE_EVENT]),
4198 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4199 {"show_create_func",
4200 (char *)offsetof(System_status_var,
4201 com_stat[(uint)SQLCOM_SHOW_CREATE_FUNC]),
4202 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4203 {"show_create_proc",
4204 (char *)offsetof(System_status_var,
4205 com_stat[(uint)SQLCOM_SHOW_CREATE_PROC]),
4206 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4207 {"show_create_table",
4208 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_CREATE]),
4209 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4210 {"show_create_trigger",
4211 (char *)offsetof(System_status_var,
4212 com_stat[(uint)SQLCOM_SHOW_CREATE_TRIGGER]),
4213 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4214 {"show_databases",
4215 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_DATABASES]),
4216 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4217 {"show_engine_logs",
4218 (char *)offsetof(System_status_var,
4219 com_stat[(uint)SQLCOM_SHOW_ENGINE_LOGS]),
4220 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4221 {"show_engine_mutex",
4222 (char *)offsetof(System_status_var,
4223 com_stat[(uint)SQLCOM_SHOW_ENGINE_MUTEX]),
4224 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4225 {"show_engine_status",
4226 (char *)offsetof(System_status_var,
4227 com_stat[(uint)SQLCOM_SHOW_ENGINE_STATUS]),
4228 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4229 {"show_events",
4230 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_EVENTS]),
4231 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4232 {"show_errors",
4233 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_ERRORS]),
4234 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4235 {"show_fields",
4236 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_FIELDS]),
4237 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4238 {"show_function_code",
4239 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_FUNC_CODE]),
4240 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4241 {"show_function_status",
4242 (char *)offsetof(System_status_var,
4243 com_stat[(uint)SQLCOM_SHOW_STATUS_FUNC]),
4244 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4245 {"show_grants",
4246 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_GRANTS]),
4247 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4248 {"show_keys",
4249 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_KEYS]),
4250 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4251 {"show_master_status",
4252 (char *)offsetof(System_status_var,
4253 com_stat[(uint)SQLCOM_SHOW_MASTER_STAT]),
4254 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4255 {"show_open_tables",
4256 (char *)offsetof(System_status_var,
4257 com_stat[(uint)SQLCOM_SHOW_OPEN_TABLES]),
4258 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4259 {"show_plugins",
4260 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_PLUGINS]),
4261 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4262 {"show_privileges",
4263 (char *)offsetof(System_status_var,
4264 com_stat[(uint)SQLCOM_SHOW_PRIVILEGES]),
4265 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4266 {"show_procedure_code",
4267 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_PROC_CODE]),
4268 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4269 {"show_procedure_status",
4270 (char *)offsetof(System_status_var,
4271 com_stat[(uint)SQLCOM_SHOW_STATUS_PROC]),
4272 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4273 {"show_processlist",
4274 (char *)offsetof(System_status_var,
4275 com_stat[(uint)SQLCOM_SHOW_PROCESSLIST]),
4276 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4277 {"show_profile",
4278 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_PROFILE]),
4279 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4280 {"show_profiles",
4281 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_PROFILES]),
4282 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4283 {"show_relaylog_events",
4284 (char *)offsetof(System_status_var,
4285 com_stat[(uint)SQLCOM_SHOW_RELAYLOG_EVENTS]),
4286 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4287 {"show_slave_hosts",
4288 (char *)offsetof(System_status_var,
4289 com_stat[(uint)SQLCOM_SHOW_SLAVE_HOSTS]),
4290 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4291 {"show_slave_status",
4292 (char *)offsetof(System_status_var,
4293 com_stat[(uint)SQLCOM_SHOW_SLAVE_STAT]),
4294 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4295 {"show_status",
4296 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_STATUS]),
4297 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4298 {"show_storage_engines",
4299 (char *)offsetof(System_status_var,
4300 com_stat[(uint)SQLCOM_SHOW_STORAGE_ENGINES]),
4301 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4302 {"show_table_status",
4303 (char *)offsetof(System_status_var,
4304 com_stat[(uint)SQLCOM_SHOW_TABLE_STATUS]),
4305 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4306 {"show_tables",
4307 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_TABLES]),
4308 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4309 {"show_triggers",
4310 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_TRIGGERS]),
4311 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4312 {"show_variables",
4313 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_VARIABLES]),
4314 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4315 {"show_warnings",
4316 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_WARNS]),
4317 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4318 {"show_create_user",
4319 (char *)offsetof(System_status_var,
4320 com_stat[(uint)SQLCOM_SHOW_CREATE_USER]),
4321 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4322 {"shutdown",
4323 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHUTDOWN]),
4324 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4325 {"slave_start",
4326 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SLAVE_START]),
4327 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4328 {"slave_stop",
4329 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SLAVE_STOP]),
4330 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4331 {"group_replication_start",
4332 (char *)offsetof(System_status_var,
4333 com_stat[(uint)SQLCOM_START_GROUP_REPLICATION]),
4334 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4335 {"group_replication_stop",
4336 (char *)offsetof(System_status_var,
4337 com_stat[(uint)SQLCOM_STOP_GROUP_REPLICATION]),
4338 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4339 {"stmt_execute", (char *)offsetof(System_status_var, com_stmt_execute),
4340 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4341 {"stmt_close", (char *)offsetof(System_status_var, com_stmt_close),
4342 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4343 {"stmt_fetch", (char *)offsetof(System_status_var, com_stmt_fetch),
4344 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4345 {"stmt_prepare", (char *)offsetof(System_status_var, com_stmt_prepare),
4346 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4347 {"stmt_reset", (char *)offsetof(System_status_var, com_stmt_reset),
4348 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4349 {"stmt_send_long_data",
4350 (char *)offsetof(System_status_var, com_stmt_send_long_data),
4351 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4352 {"truncate",
4353 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_TRUNCATE]),
4354 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4355 {"uninstall_component",
4356 (char *)offsetof(System_status_var,
4357 com_stat[(uint)SQLCOM_UNINSTALL_COMPONENT]),
4358 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4359 {"uninstall_plugin",
4360 (char *)offsetof(System_status_var,
4361 com_stat[(uint)SQLCOM_UNINSTALL_PLUGIN]),
4362 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4363 {"unlock_instance",
4364 (char *)offsetof(System_status_var,
4365 com_stat[(uint)SQLCOM_UNLOCK_INSTANCE]),
4366 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4367 {"unlock_tables",
4368 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_UNLOCK_TABLES]),
4369 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4370 {"update",
4371 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_UPDATE]),
4372 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4373 {"update_multi",
4374 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_UPDATE_MULTI]),
4375 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4376 {"xa_commit",
4377 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_COMMIT]),
4378 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4379 {"xa_end",
4380 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_END]),
4381 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4382 {"xa_prepare",
4383 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_PREPARE]),
4384 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4385 {"xa_recover",
4386 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_RECOVER]),
4387 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4388 {"xa_rollback",
4389 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_ROLLBACK]),
4390 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4391 {"xa_start",
4392 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_START]),
4393 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4394 {NullS, NullS, SHOW_LONG, SHOW_SCOPE_ALL}};
4395
4396 LEX_CSTRING sql_statement_names[(uint)SQLCOM_END + 1];
4397
init_sql_statement_names()4398 static void init_sql_statement_names() {
4399 char *first_com = (char *)offsetof(System_status_var, com_stat[0]);
4400 char *last_com =
4401 (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_END]);
4402 int record_size = (char *)offsetof(System_status_var, com_stat[1]) -
4403 (char *)offsetof(System_status_var, com_stat[0]);
4404 char *ptr;
4405 uint i;
4406 uint com_index;
4407
4408 for (i = 0; i < ((uint)SQLCOM_END + 1); i++)
4409 sql_statement_names[i] = {STRING_WITH_LEN("")};
4410
4411 SHOW_VAR *var = &com_status_vars[0];
4412 while (var->name != nullptr) {
4413 ptr = var->value;
4414 if ((first_com <= ptr) && (ptr <= last_com)) {
4415 com_index = ((int)(ptr - first_com)) / record_size;
4416 DBUG_ASSERT(com_index < (uint)SQLCOM_END);
4417 sql_statement_names[com_index].str = var->name;
4418 /* TODO: Change SHOW_VAR::name to a LEX_STRING, to avoid strlen() */
4419 sql_statement_names[com_index].length = strlen(var->name);
4420 }
4421 var++;
4422 }
4423
4424 DBUG_ASSERT(strcmp(sql_statement_names[(uint)SQLCOM_SELECT].str, "select") ==
4425 0);
4426 DBUG_ASSERT(strcmp(sql_statement_names[(uint)SQLCOM_SIGNAL].str, "signal") ==
4427 0);
4428
4429 sql_statement_names[(uint)SQLCOM_END].str = "error";
4430 }
4431
4432 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4433 PSI_statement_info sql_statement_info[(uint)SQLCOM_END + 1];
4434 PSI_statement_info com_statement_info[(uint)COM_END + 1];
4435
4436 /**
4437 Initialize the command names array.
4438 Since we do not want to maintain a separate array,
4439 this is populated from data mined in com_status_vars,
4440 which already has one name for each command.
4441 */
init_sql_statement_info()4442 static void init_sql_statement_info() {
4443 uint i;
4444
4445 for (i = 0; i < ((uint)SQLCOM_END + 1); i++) {
4446 sql_statement_info[i].m_name = sql_statement_names[i].str;
4447 sql_statement_info[i].m_flags = 0;
4448 sql_statement_info[i].m_documentation = PSI_DOCUMENT_ME;
4449 }
4450
4451 /* "statement/sql/error" represents broken queries (syntax error). */
4452 sql_statement_info[(uint)SQLCOM_END].m_name = "error";
4453 sql_statement_info[(uint)SQLCOM_END].m_flags = 0;
4454 sql_statement_info[(uint)SQLCOM_END].m_documentation =
4455 "Invalid SQL queries (syntax error).";
4456
4457 /* "statement/sql/clone" will mutate to clone plugin statement */
4458 sql_statement_info[(uint)SQLCOM_CLONE].m_flags = PSI_FLAG_MUTABLE;
4459 }
4460
init_com_statement_info()4461 static void init_com_statement_info() {
4462 uint index;
4463
4464 for (index = 0; index < (uint)COM_END + 1; index++) {
4465 com_statement_info[index].m_name = command_name[index].str;
4466 com_statement_info[index].m_flags = 0;
4467 com_statement_info[index].m_documentation = PSI_DOCUMENT_ME;
4468 }
4469
4470 /* "statement/abstract/query" can mutate into "statement/sql/..." */
4471 com_statement_info[(uint)COM_QUERY].m_flags = PSI_FLAG_MUTABLE;
4472 com_statement_info[(uint)COM_QUERY].m_documentation =
4473 "SQL query just received from the network. "
4474 "At this point, the real statement type is unknown, "
4475 "the type will be refined after SQL parsing.";
4476
4477 /* "statement/com/clone" will mutate to clone plugin statement */
4478 com_statement_info[(uint)COM_CLONE].m_flags = PSI_FLAG_MUTABLE;
4479 }
4480 #endif
4481
4482 /**
4483 Create a replication file name or base for file names.
4484
4485 @param key Instrumentation key used to track allocations
4486 @param[in] opt Value of option, or NULL
4487 @param[in] def Default value if option value is not set.
4488 @param[in] ext Extension to use for the path
4489
4490 @returns Pointer to string containing the full file path, or NULL if
4491 it was not possible to create the path.
4492 */
rpl_make_log_name(PSI_memory_key key,const char * opt,const char * def,const char * ext)4493 static inline const char *rpl_make_log_name(PSI_memory_key key, const char *opt,
4494 const char *def, const char *ext) {
4495 DBUG_TRACE;
4496 DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", (opt && opt[0]) ? opt : "",
4497 def, ext));
4498 char buff[FN_REFLEN];
4499 /*
4500 opt[0] needs to be checked to make sure opt name is not an empty
4501 string, incase it is an empty string default name will be considered
4502 */
4503 const char *base = (opt && opt[0]) ? opt : def;
4504 unsigned int options = MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH;
4505
4506 /* mysql_real_data_home_ptr may be null if no value of datadir has been
4507 specified through command-line or througha cnf file. If that is the
4508 case we make mysql_real_data_home_ptr point to mysql_real_data_home
4509 which, in that case holds the default path for data-dir.
4510 */
4511
4512 DBUG_EXECUTE_IF("emulate_empty_datadir_param",
4513 { mysql_real_data_home_ptr = nullptr; };);
4514
4515 if (mysql_real_data_home_ptr == nullptr)
4516 mysql_real_data_home_ptr = mysql_real_data_home;
4517
4518 if (fn_format(buff, base, mysql_real_data_home_ptr, ext, options))
4519 return my_strdup(key, buff, MYF(0));
4520 else
4521 return nullptr;
4522 }
4523
init_common_variables()4524 int init_common_variables() {
4525 umask(((~my_umask) & 0666));
4526 my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
4527 tzset(); // Set tzname
4528
4529 max_system_variables.pseudo_thread_id = (my_thread_id)~0;
4530 server_start_time = flush_status_time = my_time(0);
4531
4532 binlog_filter = new Rpl_filter;
4533 if (!binlog_filter) {
4534 LogErr(ERROR_LEVEL, ER_RPL_BINLOG_FILTERS_OOM, strerror(errno));
4535 return 1;
4536 }
4537
4538 if (init_thread_environment() || mysql_init_variables()) return 1;
4539
4540 {
4541 struct tm tm_tmp;
4542 localtime_r(&server_start_time, &tm_tmp);
4543 #ifdef _WIN32
4544 strmake(system_time_zone, _tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
4545 sizeof(system_time_zone) - 1);
4546 #else
4547 strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
4548 sizeof(system_time_zone) - 1);
4549 #endif
4550 }
4551 /*
4552 We set SYSTEM time zone as reasonable default and
4553 also for failure of my_tz_init() and bootstrap mode.
4554 If user explicitly set time zone with --default-time-zone
4555 option we will change this value in my_tz_init().
4556 */
4557 global_system_variables.time_zone = my_tz_SYSTEM;
4558
4559 #ifdef HAVE_PSI_INTERFACE
4560 /*
4561 Complete the mysql_bin_log initialization.
4562 Instrumentation keys are known only after the performance schema
4563 initialization, and can not be set in the MYSQL_BIN_LOG constructor (called
4564 before main()).
4565 */
4566 mysql_bin_log.set_psi_keys(
4567 key_BINLOG_LOCK_index, key_BINLOG_LOCK_commit,
4568 key_BINLOG_LOCK_commit_queue, key_BINLOG_LOCK_done,
4569 key_BINLOG_LOCK_flush_queue, key_BINLOG_LOCK_log,
4570 key_BINLOG_LOCK_binlog_end_pos, key_BINLOG_LOCK_sync,
4571 key_BINLOG_LOCK_sync_queue, key_BINLOG_LOCK_xids, key_BINLOG_COND_done,
4572 key_BINLOG_update_cond, key_BINLOG_prep_xids_cond, key_file_binlog,
4573 key_file_binlog_index, key_file_binlog_cache,
4574 key_file_binlog_index_cache);
4575 #endif
4576
4577 /*
4578 Init mutexes for the global MYSQL_BIN_LOG objects.
4579 As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
4580 global MYSQL_BIN_LOGs in their constructors, because then they would be
4581 inited before MY_INIT(). So we do it here.
4582 */
4583 mysql_bin_log.init_pthread_objects();
4584
4585 /* TODO: remove this when my_time_t is 64 bit compatible */
4586 if (!is_time_t_valid_for_timestamp(server_start_time)) {
4587 LogErr(ERROR_LEVEL, ER_UNSUPPORTED_DATE);
4588 return 1;
4589 }
4590
4591 if (gethostname(glob_hostname, sizeof(glob_hostname)) < 0) {
4592 strmake(glob_hostname, STRING_WITH_LEN("localhost"));
4593 LogErr(WARNING_LEVEL, ER_CALL_ME_LOCALHOST, glob_hostname);
4594 strmake(default_logfile_name, STRING_WITH_LEN("mysql"));
4595 } else
4596 strmake(default_logfile_name, glob_hostname,
4597 sizeof(default_logfile_name) - 5);
4598
4599 strmake(default_binlogfile_name, STRING_WITH_LEN("binlog"));
4600 if (opt_initialize || opt_initialize_insecure) {
4601 /*
4602 System tables initialization are not binary logged (regardless
4603 --log-bin option).
4604
4605 Disable binary log while executing any user script sourced while
4606 initializing system except if explicitly requested.
4607 */
4608 opt_bin_log = false;
4609 }
4610
4611 strmake(pidfile_name, default_logfile_name, sizeof(pidfile_name) - 5);
4612 my_stpcpy(fn_ext(pidfile_name), ".pid"); // Add proper extension
4613
4614 /*
4615 The default-storage-engine entry in my_long_options should have a
4616 non-null default value. It was earlier intialized as
4617 (longlong)"MyISAM" in my_long_options but this triggered a
4618 compiler error in the Sun Studio 12 compiler. As a work-around we
4619 set the def_value member to 0 in my_long_options and initialize it
4620 to the correct value here.
4621
4622 From MySQL 5.5 onwards, the default storage engine is InnoDB.
4623 */
4624 default_storage_engine = "InnoDB";
4625 default_tmp_storage_engine = default_storage_engine;
4626
4627 /*
4628 Add server status variables to the dynamic list of
4629 status variables that is shown by SHOW STATUS.
4630 Later, in plugin_register_builtin_and_init_core_se(),
4631 plugin_register_dynamic_and_init_all() and
4632 mysql_install_plugin(), new entries could be added
4633 to that list.
4634 */
4635 if (add_status_vars(status_vars)) return 1; // an error was already reported
4636
4637 #ifndef DBUG_OFF
4638 /*
4639 We have few debug-only commands in com_status_vars, only visible in debug
4640 builds. for simplicity we enable the assert only in debug builds
4641
4642 There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
4643 (TODO strictly speaking they shouldn't be here, should not have Com_ prefix
4644 that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)
4645
4646 Com_admin_commands => com_other
4647 Com_stmt_close => com_stmt_close
4648 Com_stmt_execute => com_stmt_execute
4649 Com_stmt_fetch => com_stmt_fetch
4650 Com_stmt_prepare => com_stmt_prepare
4651 Com_stmt_reprepare => com_stmt_reprepare
4652 Com_stmt_reset => com_stmt_reset
4653 Com_stmt_send_long_data => com_stmt_send_long_data
4654
4655 With this correction the number of Com_ variables (number of elements in
4656 the array, excluding the last element - terminator) must match the number
4657 of SQLCOM_ constants.
4658 */
4659 static_assert(sizeof(com_status_vars) / sizeof(com_status_vars[0]) - 1 ==
4660 SQLCOM_END + 7,
4661 "");
4662 #endif
4663
4664 if (get_options(&remaining_argc, &remaining_argv)) return 1;
4665
4666 /*
4667 The opt_bin_log can be false (binary log is disabled) only if
4668 --skip-log-bin/--disable-log-bin is configured or while the
4669 system is initializing.
4670 */
4671 if (!opt_bin_log) {
4672 /*
4673 The log-slave-updates should be disabled if binary log is disabled
4674 and --log-slave-updates option is not set explicitly on command
4675 line or configuration file.
4676 */
4677 if (!log_slave_updates_supplied) opt_log_slave_updates = false;
4678 /*
4679 The slave-preserve-commit-order should be disabled if binary log is
4680 disabled and --slave-preserve-commit-order option is not set
4681 explicitly on command line or configuration file.
4682 */
4683 if (!slave_preserve_commit_order_supplied)
4684 opt_slave_preserve_commit_order = false;
4685 }
4686
4687 if (opt_protocol_compression_algorithms) {
4688 if ((opt_protocol_compression_algorithms[0] == 0) ||
4689 (validate_compression_attributes(
4690 std::string(opt_protocol_compression_algorithms), std::string(),
4691 true))) {
4692 /*
4693 --protocol-compression-algorithms is set to invalid value, resetting
4694 its value to default "zlib,zstd,uncompressed"
4695 */
4696 opt_protocol_compression_algorithms =
4697 const_cast<char *>(PROTOCOL_COMPRESSION_DEFAULT_VALUE);
4698 LogErr(WARNING_LEVEL, ER_PROTOCOL_COMPRESSION_RESET_LOG);
4699 }
4700 }
4701 update_parser_max_mem_size();
4702
4703 if (set_default_auth_plugin(default_auth_plugin,
4704 strlen(default_auth_plugin))) {
4705 LogErr(ERROR_LEVEL, ER_AUTH_CANT_SET_DEFAULT_PLUGIN);
4706 return 1;
4707 }
4708 set_server_version();
4709
4710 if (!is_help_or_validate_option()) {
4711 LogErr(INFORMATION_LEVEL, ER_BASEDIR_SET_TO, mysql_home);
4712 }
4713
4714 if (!opt_validate_config && (opt_initialize || opt_initialize_insecure)) {
4715 LogErr(SYSTEM_LEVEL, ER_STARTING_INIT, my_progname, server_version,
4716 (ulong)getpid());
4717 } else if (!is_help_or_validate_option()) {
4718 LogErr(SYSTEM_LEVEL, ER_STARTING_AS, my_progname, server_version,
4719 (ulong)getpid());
4720 }
4721 if (opt_help && !opt_verbose) unireg_abort(MYSQLD_SUCCESS_EXIT);
4722
4723 DBUG_PRINT("info", ("%s Ver %s for %s on %s\n", my_progname, server_version,
4724 SYSTEM_TYPE, MACHINE_TYPE));
4725
4726 #ifdef HAVE_LINUX_LARGE_PAGES
4727 /* Initialize large page size */
4728 if (opt_large_pages && (opt_large_page_size = my_get_large_page_size())) {
4729 DBUG_PRINT("info",
4730 ("Large page set, large_page_size = %d", opt_large_page_size));
4731 } else {
4732 opt_large_pages = false;
4733 /*
4734 Either not configured to use large pages or Linux haven't
4735 been compiled with large page support
4736 */
4737 }
4738 #endif /* HAVE_LINUX_LARGE_PAGES */
4739 #ifdef HAVE_SOLARIS_LARGE_PAGES
4740 #define LARGE_PAGESIZE (4 * 1024 * 1024) /* 4MB */
4741 #define SUPER_LARGE_PAGESIZE (256 * 1024 * 1024) /* 256MB */
4742 if (opt_large_pages) {
4743 /*
4744 tell the kernel that we want to use 4/256MB page for heap storage
4745 and also for the stack. We use 4 MByte as default and if the
4746 super-large-page is set we increase it to 256 MByte. 256 MByte
4747 is for server installations with GBytes of RAM memory where
4748 the MySQL Server will have page caches and other memory regions
4749 measured in a number of GBytes.
4750 We use as big pages as possible which isn't bigger than the above
4751 desired page sizes.
4752 */
4753 int nelem;
4754 size_t max_desired_page_size;
4755 if (opt_super_large_pages)
4756 max_desired_page_size = SUPER_LARGE_PAGESIZE;
4757 else
4758 max_desired_page_size = LARGE_PAGESIZE;
4759 nelem = getpagesizes(NULL, 0);
4760 if (nelem > 0) {
4761 size_t *pagesize = (size_t *)malloc(sizeof(size_t) * nelem);
4762 if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0) {
4763 size_t max_page_size = 0;
4764 for (int i = 0; i < nelem; i++) {
4765 if (pagesize[i] > max_page_size &&
4766 pagesize[i] <= max_desired_page_size)
4767 max_page_size = pagesize[i];
4768 }
4769 free(pagesize);
4770 if (max_page_size > 0) {
4771 struct memcntl_mha mpss;
4772
4773 mpss.mha_cmd = MHA_MAPSIZE_BSSBRK;
4774 mpss.mha_pagesize = max_page_size;
4775 mpss.mha_flags = 0;
4776 memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
4777 mpss.mha_cmd = MHA_MAPSIZE_STACK;
4778 memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
4779 }
4780 }
4781 }
4782 }
4783 #endif /* HAVE_SOLARIS_LARGE_PAGES */
4784
4785 longlong default_value;
4786 sys_var *var;
4787 /* Calculate and update default value for thread_cache_size. */
4788 if ((default_value = 8 + max_connections / 100) > 100) default_value = 100;
4789 var = intern_find_sys_var(STRING_WITH_LEN("thread_cache_size"));
4790 var->update_default(default_value);
4791
4792 /* Calculate and update default value for host_cache_size. */
4793 if ((default_value = 128 + max_connections) > 628 &&
4794 (default_value = 628 + ((max_connections - 500) / 20)) > 2000)
4795 default_value = 2000;
4796 var = intern_find_sys_var(STRING_WITH_LEN("host_cache_size"));
4797 var->update_default(default_value);
4798
4799 /* Fix thread_cache_size. */
4800 if (!thread_cache_size_specified &&
4801 (Per_thread_connection_handler::max_blocked_pthreads =
4802 8 + max_connections / 100) > 100)
4803 Per_thread_connection_handler::max_blocked_pthreads = 100;
4804
4805 /* Fix host_cache_size. */
4806 if (!host_cache_size_specified &&
4807 (host_cache_size = 128 + max_connections) > 628 &&
4808 (host_cache_size = 628 + ((max_connections - 500) / 20)) > 2000)
4809 host_cache_size = 2000;
4810
4811 /* Fix back_log */
4812 if (back_log == 0 && (back_log = max_connections) > 65535) back_log = 65535;
4813
4814 unireg_init(opt_specialflag); /* Set up extern variables */
4815 while (!(my_default_lc_messages =
4816 my_locale_by_name(nullptr, lc_messages, strlen(lc_messages)))) {
4817 LogErr(ERROR_LEVEL, ER_FAILED_TO_FIND_LOCALE_NAME, lc_messages);
4818 if (!my_strcasecmp(&my_charset_latin1, lc_messages,
4819 mysqld_default_locale_name))
4820 return 1;
4821 lc_messages = mysqld_default_locale_name;
4822 }
4823 global_system_variables.lc_messages = my_default_lc_messages;
4824 if (init_errmessage()) /* Read error messages from file */
4825 return 1;
4826 init_client_errs();
4827
4828 mysql_client_plugin_init();
4829 if (item_create_init()) return 1;
4830 item_init();
4831 range_optimizer_init();
4832 my_string_stack_guard = check_enough_stack_size;
4833 /*
4834 Process a comma-separated character set list and choose
4835 the first available character set. This is mostly for
4836 test purposes, to be able to start "mysqld" even if
4837 the requested character set is not available (see bug#18743).
4838 */
4839 for (;;) {
4840 char *next_character_set_name =
4841 strchr(const_cast<char *>(default_character_set_name), ',');
4842 if (next_character_set_name) *next_character_set_name++ = '\0';
4843 if (!(default_charset_info = get_charset_by_csname(
4844 default_character_set_name, MY_CS_PRIMARY, MYF(MY_WME)))) {
4845 if (next_character_set_name) {
4846 default_character_set_name = next_character_set_name;
4847 default_collation_name = nullptr; // Ignore collation
4848 } else
4849 return 1; // Eof of the list
4850 } else {
4851 warn_on_deprecated_charset(nullptr, default_charset_info,
4852 default_character_set_name,
4853 "--character-set-server");
4854 break;
4855 }
4856 }
4857
4858 if (default_collation_name) {
4859 CHARSET_INFO *default_collation;
4860 default_collation = get_charset_by_name(default_collation_name, MYF(0));
4861 if (!default_collation) {
4862 LogErr(ERROR_LEVEL, ER_FAILED_TO_FIND_COLLATION_NAME,
4863 default_collation_name);
4864 return 1;
4865 }
4866 if (!my_charset_same(default_charset_info, default_collation)) {
4867 LogErr(ERROR_LEVEL, ER_INVALID_COLLATION_FOR_CHARSET,
4868 default_collation_name, default_charset_info->csname);
4869 return 1;
4870 }
4871 warn_on_deprecated_collation(nullptr, default_collation,
4872 "--collation-server");
4873 default_charset_info = default_collation;
4874 }
4875 /* Set collactions that depends on the default collation */
4876 global_system_variables.collation_server = default_charset_info;
4877 global_system_variables.collation_database = default_charset_info;
4878 global_system_variables.default_collation_for_utf8mb4 =
4879 &my_charset_utf8mb4_0900_ai_ci;
4880
4881 if (is_supported_parser_charset(default_charset_info)) {
4882 global_system_variables.collation_connection = default_charset_info;
4883 global_system_variables.character_set_results = default_charset_info;
4884 global_system_variables.character_set_client = default_charset_info;
4885 } else {
4886 LogErr(INFORMATION_LEVEL, ER_FIXING_CLIENT_CHARSET,
4887 default_charset_info->csname, my_charset_latin1.csname);
4888 global_system_variables.collation_connection = &my_charset_latin1;
4889 global_system_variables.character_set_results = &my_charset_latin1;
4890 global_system_variables.character_set_client = &my_charset_latin1;
4891 }
4892
4893 if (!(character_set_filesystem = get_charset_by_csname(
4894 character_set_filesystem_name, MY_CS_PRIMARY, MYF(MY_WME))))
4895 return 1;
4896 else
4897 warn_on_deprecated_charset(nullptr, character_set_filesystem,
4898 character_set_filesystem_name,
4899 "--character-set-filesystem");
4900 global_system_variables.character_set_filesystem = character_set_filesystem;
4901
4902 if (lex_init()) {
4903 LogErr(ERROR_LEVEL, ER_OOM);
4904 return 1;
4905 }
4906
4907 while (!(my_default_lc_time_names = my_locale_by_name(
4908 nullptr, lc_time_names_name, strlen(lc_time_names_name)))) {
4909 LogErr(ERROR_LEVEL, ER_FAILED_TO_FIND_LOCALE_NAME, lc_time_names_name);
4910 if (!my_strcasecmp(&my_charset_latin1, lc_time_names_name,
4911 mysqld_default_locale_name))
4912 return 1;
4913 lc_time_names_name = mysqld_default_locale_name;
4914 }
4915 global_system_variables.lc_time_names = my_default_lc_time_names;
4916
4917 /* check log options and issue warnings if needed */
4918 if (opt_general_log && opt_general_logname &&
4919 !(log_output_options & LOG_FILE) && !(log_output_options & LOG_NONE))
4920 LogErr(WARNING_LEVEL, ER_LOG_FILES_GIVEN_LOG_OUTPUT_IS_TABLE,
4921 "--general-log-file option");
4922
4923 if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE) &&
4924 !(log_output_options & LOG_NONE))
4925 LogErr(WARNING_LEVEL, ER_LOG_FILES_GIVEN_LOG_OUTPUT_IS_TABLE,
4926 "--slow-query-log-file option");
4927
4928 if (opt_general_logname &&
4929 !is_valid_log_name(opt_general_logname, strlen(opt_general_logname))) {
4930 LogErr(ERROR_LEVEL, ER_LOG_FILE_INVALID, "--general_log_file",
4931 opt_general_logname);
4932 return 1;
4933 }
4934
4935 if (opt_slow_logname &&
4936 !is_valid_log_name(opt_slow_logname, strlen(opt_slow_logname))) {
4937 LogErr(ERROR_LEVEL, ER_LOG_FILE_INVALID, "--slow_query_log_file",
4938 opt_slow_logname);
4939 return 1;
4940 }
4941
4942 set_mysqld_opt_tracking_mode();
4943 if (global_system_variables.transaction_write_set_extraction ==
4944 HASH_ALGORITHM_OFF &&
4945 mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode !=
4946 DEPENDENCY_TRACKING_COMMIT_ORDER) {
4947 LogErr(ERROR_LEVEL,
4948 ER_TX_EXTRACTION_ALGORITHM_FOR_BINLOG_TX_DEPEDENCY_TRACKING,
4949 "XXHASH64 or MURMUR32", "WRITESET or WRITESET_SESSION");
4950 return 1;
4951 } else
4952 mysql_bin_log.m_dependency_tracker.tracking_mode_changed();
4953
4954 #define FIX_LOG_VAR(VAR, ALT) \
4955 if (!VAR || !*VAR) VAR = ALT;
4956
4957 FIX_LOG_VAR(opt_general_logname,
4958 make_query_log_name(logname_path, QUERY_LOG_GENERAL));
4959 FIX_LOG_VAR(opt_slow_logname,
4960 make_query_log_name(slow_logname_path, QUERY_LOG_SLOW));
4961
4962 #if defined(ENABLED_DEBUG_SYNC)
4963 /* Initialize the debug sync facility. See debug_sync.cc. */
4964 if (debug_sync_init()) return 1; /* purecov: tested */
4965 #endif /* defined(ENABLED_DEBUG_SYNC) */
4966
4967 if (opt_validate_config) return 0;
4968
4969 /* create the data directory if requested */
4970 if (unlikely(opt_initialize) &&
4971 initialize_create_data_directory(mysql_real_data_home))
4972 return 1;
4973
4974 /*
4975 Ensure that lower_case_table_names is set on system where we have case
4976 insensitive names. If this is not done the users MyISAM tables will
4977 get corrupted if accesses with names of different case.
4978 */
4979 DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
4980 lower_case_file_system = test_if_case_insensitive(mysql_real_data_home);
4981 if (!lower_case_table_names && lower_case_file_system == 1) {
4982 if (lower_case_table_names_used) {
4983 LogErr(ERROR_LEVEL, ER_LOWER_CASE_TABLE_NAMES_CS_DD_ON_CI_FS_UNSUPPORTED);
4984 return 1;
4985 } else {
4986 LogErr(WARNING_LEVEL, ER_LOWER_CASE_TABLE_NAMES_USING_2,
4987 mysql_real_data_home);
4988 lower_case_table_names = 2;
4989 }
4990 } else if (lower_case_table_names == 2 &&
4991 !(lower_case_file_system =
4992 (test_if_case_insensitive(mysql_real_data_home) == 1))) {
4993 LogErr(WARNING_LEVEL, ER_LOWER_CASE_TABLE_NAMES_USING_0,
4994 mysql_real_data_home);
4995 lower_case_table_names = 0;
4996 } else {
4997 lower_case_file_system =
4998 (test_if_case_insensitive(mysql_real_data_home) == 1);
4999 }
5000
5001 /* Reset table_alias_charset, now that lower_case_table_names is set. */
5002 table_alias_charset =
5003 (lower_case_table_names ? &my_charset_utf8_tolower_ci : &my_charset_bin);
5004
5005 /*
5006 Build do_table and ignore_table rules to hashes
5007 after the resetting of table_alias_charset.
5008 */
5009 if (rpl_global_filter.build_do_table_hash() ||
5010 rpl_global_filter.build_ignore_table_hash()) {
5011 LogErr(ERROR_LEVEL, ER_CANT_HASH_DO_AND_IGNORE_RULES);
5012 return 1;
5013 }
5014
5015 /*
5016 Reset the P_S view for global replication filter at
5017 the end of server startup.
5018 */
5019 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5020 rpl_global_filter.wrlock();
5021 rpl_global_filter.reset_pfs_view();
5022 rpl_global_filter.unlock();
5023 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
5024
5025 if (rpl_channel_filters.build_do_and_ignore_table_hashes()) return 1;
5026
5027 return 0;
5028 }
5029
init_thread_environment()5030 static int init_thread_environment() {
5031 mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
5032 mysql_mutex_init(key_LOCK_manager, &LOCK_manager, MY_MUTEX_INIT_FAST);
5033 mysql_mutex_init(key_LOCK_crypt, &LOCK_crypt, MY_MUTEX_INIT_FAST);
5034 mysql_mutex_init(key_LOCK_user_conn, &LOCK_user_conn, MY_MUTEX_INIT_FAST);
5035 mysql_mutex_init(key_LOCK_global_system_variables,
5036 &LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
5037 mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash,
5038 &LOCK_system_variables_hash);
5039 mysql_mutex_init(key_LOCK_prepared_stmt_count, &LOCK_prepared_stmt_count,
5040 MY_MUTEX_INIT_FAST);
5041 mysql_mutex_init(key_LOCK_sql_slave_skip_counter,
5042 &LOCK_sql_slave_skip_counter, MY_MUTEX_INIT_FAST);
5043 mysql_mutex_init(key_LOCK_slave_net_timeout, &LOCK_slave_net_timeout,
5044 MY_MUTEX_INIT_FAST);
5045 mysql_mutex_init(key_LOCK_slave_trans_dep_tracker,
5046 &LOCK_slave_trans_dep_tracker, MY_MUTEX_INIT_FAST);
5047 mysql_mutex_init(key_LOCK_error_messages, &LOCK_error_messages,
5048 MY_MUTEX_INIT_FAST);
5049 mysql_mutex_init(key_LOCK_uuid_generator, &LOCK_uuid_generator,
5050 MY_MUTEX_INIT_FAST);
5051 mysql_mutex_init(key_LOCK_sql_rand, &LOCK_sql_rand, MY_MUTEX_INIT_FAST);
5052 mysql_mutex_init(key_LOCK_log_throttle_qni, &LOCK_log_throttle_qni,
5053 MY_MUTEX_INIT_FAST);
5054 mysql_mutex_init(key_LOCK_default_password_lifetime,
5055 &LOCK_default_password_lifetime, MY_MUTEX_INIT_FAST);
5056 mysql_mutex_init(key_LOCK_mandatory_roles, &LOCK_mandatory_roles,
5057 MY_MUTEX_INIT_FAST);
5058 mysql_mutex_init(key_LOCK_password_history, &LOCK_password_history,
5059 MY_MUTEX_INIT_FAST);
5060 mysql_mutex_init(key_LOCK_password_reuse_interval,
5061 &LOCK_password_reuse_interval, MY_MUTEX_INIT_FAST);
5062 mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
5063 mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
5064 mysql_cond_init(key_COND_manager, &COND_manager);
5065 mysql_mutex_init(key_LOCK_server_started, &LOCK_server_started,
5066 MY_MUTEX_INIT_FAST);
5067 mysql_cond_init(key_COND_server_started, &COND_server_started);
5068 mysql_mutex_init(key_LOCK_reset_gtid_table, &LOCK_reset_gtid_table,
5069 MY_MUTEX_INIT_FAST);
5070 mysql_mutex_init(key_LOCK_compress_gtid_table, &LOCK_compress_gtid_table,
5071 MY_MUTEX_INIT_FAST);
5072 mysql_mutex_init(key_LOCK_collect_instance_log, &LOCK_collect_instance_log,
5073 MY_MUTEX_INIT_FAST);
5074 mysql_cond_init(key_COND_compress_gtid_table, &COND_compress_gtid_table);
5075 Events::init_mutexes();
5076 #if defined(_WIN32)
5077 mysql_mutex_init(key_LOCK_handler_count, &LOCK_handler_count,
5078 MY_MUTEX_INIT_FAST);
5079 mysql_cond_init(key_COND_handler_count, &COND_handler_count);
5080 mysql_rwlock_init(key_rwlock_LOCK_named_pipe_full_access_group,
5081 &LOCK_named_pipe_full_access_group);
5082 #else
5083 mysql_mutex_init(key_LOCK_socket_listener_active,
5084 &LOCK_socket_listener_active, MY_MUTEX_INIT_FAST);
5085 mysql_cond_init(key_COND_socket_listener_active,
5086 &COND_socket_listener_active);
5087 mysql_mutex_init(key_LOCK_start_signal_handler, &LOCK_start_signal_handler,
5088 MY_MUTEX_INIT_FAST);
5089 mysql_cond_init(key_COND_start_signal_handler, &COND_start_signal_handler);
5090 #endif // _WIN32
5091 /* Parameter for threads created for connections */
5092 (void)my_thread_attr_init(&connection_attrib);
5093 my_thread_attr_setdetachstate(&connection_attrib, MY_THREAD_CREATE_DETACHED);
5094 #ifndef _WIN32
5095 pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
5096 #endif
5097
5098 mysql_mutex_init(key_LOCK_keyring_operations, &LOCK_keyring_operations,
5099 MY_MUTEX_INIT_FAST);
5100 mysql_mutex_init(key_LOCK_tls_ctx_options, &LOCK_tls_ctx_options,
5101 MY_MUTEX_INIT_FAST);
5102 mysql_mutex_init(key_LOCK_rotate_binlog_master_key,
5103 &LOCK_rotate_binlog_master_key, MY_MUTEX_INIT_FAST);
5104 mysql_mutex_init(key_LOCK_admin_tls_ctx_options, &LOCK_admin_tls_ctx_options,
5105 MY_MUTEX_INIT_FAST);
5106 return 0;
5107 }
5108
5109 #if !defined(__sun)
5110 /* TODO: remove the !defined(__sun) when bug 23285559 is out of the picture */
5111
5112 static PSI_memory_key key_memory_openssl = PSI_NOT_INSTRUMENTED;
5113
5114 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
5115 #define FILE_LINE_ARGS
5116 #else
5117 #define FILE_LINE_ARGS , const char *, int
5118 #endif
5119
my_openssl_malloc(size_t size FILE_LINE_ARGS)5120 static void *my_openssl_malloc(size_t size FILE_LINE_ARGS) {
5121 return my_malloc(key_memory_openssl, size, MYF(MY_WME));
5122 }
my_openssl_realloc(void * ptr,size_t size FILE_LINE_ARGS)5123 static void *my_openssl_realloc(void *ptr, size_t size FILE_LINE_ARGS) {
5124 return my_realloc(key_memory_openssl, ptr, size, MYF(MY_WME));
5125 }
my_openssl_free(void * ptr FILE_LINE_ARGS)5126 static void my_openssl_free(void *ptr FILE_LINE_ARGS) { return my_free(ptr); }
5127 #endif /* !defined(__sun) */
5128
init_ssl()5129 static void init_ssl() {
5130 #if !defined(__sun)
5131 #if defined(HAVE_PSI_MEMORY_INTERFACE)
5132 static PSI_memory_info all_openssl_memory[] = {
5133 {&key_memory_openssl, "openssl_malloc", 0, 0,
5134 "All memory used by openSSL"}};
5135 mysql_memory_register("mysqld_openssl", all_openssl_memory,
5136 (int)array_elements(all_openssl_memory));
5137 #endif /* defined(HAVE_PSI_MEMORY_INTERFACE) */
5138 int ret = CRYPTO_set_mem_functions(my_openssl_malloc, my_openssl_realloc,
5139 my_openssl_free);
5140 if (ret == 0)
5141 LogErr(WARNING_LEVEL, ER_SSL_MEMORY_INSTRUMENTATION_INIT_FAILED,
5142 "CRYPTO_set_mem_functions");
5143 #endif /* !defined(__sun) */
5144 ssl_start();
5145 }
5146
init_ssl_communication()5147 static int init_ssl_communication() {
5148 #if !defined(XTRABACKUP)
5149 char ssl_err_string[OPENSSL_ERROR_LENGTH] = {'\0'};
5150 int ret_fips_mode = set_fips_mode(opt_ssl_fips_mode, ssl_err_string);
5151 if (ret_fips_mode != 1) {
5152 LogErr(ERROR_LEVEL, ER_SSL_FIPS_MODE_ERROR, ssl_err_string);
5153 return 1;
5154 }
5155 if (TLS_channel::singleton_init(&mysql_main, mysql_main_channel, opt_use_ssl,
5156 &server_main_callback, opt_initialize))
5157 return 1;
5158
5159 /*
5160 The default value of --admin-ssl is ON. If it is set
5161 to off, we should treat it as an explicit attempt to
5162 set TLS off for admin channel and thereby not use
5163 main channel's TLS configuration.
5164 */
5165 if (!opt_use_admin_ssl) g_admin_ssl_configured = true;
5166
5167 bool initialize_admin_tls =
5168 (!opt_initialize && (my_admin_bind_addr_str != nullptr))
5169 ? opt_use_admin_ssl
5170 : false;
5171
5172 Ssl_init_callback_server_admin server_admin_callback;
5173 if (TLS_channel::singleton_init(&mysql_admin, mysql_admin_channel,
5174 initialize_admin_tls, &server_admin_callback,
5175 opt_initialize))
5176 return 1;
5177
5178 if (initialize_admin_tls && !g_admin_ssl_configured) {
5179 Lock_and_access_ssl_acceptor_context context(mysql_main);
5180 if (context.have_ssl())
5181 LogErr(SYSTEM_LEVEL, ER_TLS_CONFIGURATION_REUSED,
5182 mysql_admin_channel.c_str(), mysql_main_channel.c_str());
5183 }
5184 #endif
5185
5186 #if OPENSSL_VERSION_NUMBER < 0x10100000L
5187 ERR_remove_thread_state(0);
5188 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
5189
5190 if (init_rsa_keys()) return 1;
5191 return 0;
5192 }
5193
end_ssl()5194 static void end_ssl() {
5195 TLS_channel::singleton_deinit(mysql_main);
5196 TLS_channel::singleton_deinit(mysql_admin);
5197 deinit_rsa_keys();
5198 }
5199
5200 /**
5201 Generate a UUID and save it into server_uuid variable.
5202
5203 @return Retur 0 or 1 if an error occurred.
5204 */
generate_server_uuid()5205 static int generate_server_uuid() {
5206 THD *thd;
5207 Item_func_uuid *func_uuid;
5208 String uuid;
5209
5210 /*
5211 To be able to run this from boot, we allocate a temporary THD
5212 */
5213 if (!(thd = new THD)) {
5214 LogErr(ERROR_LEVEL, ER_NO_THD_NO_UUID);
5215 return 1;
5216 }
5217 thd->thread_stack = (char *)&thd;
5218 thd->store_globals();
5219
5220 /*
5221 Initialize the variables which are used during "uuid generator
5222 initialization" with values that should normally differ between
5223 mysqlds on the same host. This avoids that another mysqld started
5224 at the same time on the same host get the same "server_uuid".
5225 */
5226
5227 const time_t save_server_start_time = server_start_time;
5228 server_start_time += ((ulonglong)current_pid << 48) + current_pid;
5229 thd->status_var.bytes_sent = (ulonglong)thd;
5230
5231 lex_start(thd);
5232 func_uuid = new (thd->mem_root) Item_func_uuid();
5233 func_uuid->fixed = true;
5234 func_uuid->val_str(&uuid);
5235
5236 // Restore global variables used for salting
5237 server_start_time = save_server_start_time;
5238
5239 delete thd;
5240
5241 strncpy(server_uuid, uuid.c_ptr(), UUID_LENGTH);
5242 DBUG_EXECUTE_IF("server_uuid_deterministic",
5243 memcpy(server_uuid, "00000000-1111-0000-1111-000000000000",
5244 UUID_LENGTH););
5245 server_uuid[UUID_LENGTH] = '\0';
5246 return 0;
5247 }
5248
5249 /**
5250 Save all options which was auto-generated by server-self into the given file.
5251
5252 @param fname The name of the file in which the auto-generated options will b
5253 e saved.
5254
5255 @return Return 0 or 1 if an error occurred.
5256 */
flush_auto_options(const char * fname)5257 static int flush_auto_options(const char *fname) {
5258 File fd;
5259 IO_CACHE io_cache;
5260 int result = 0;
5261
5262 if ((fd = my_open(fname, O_CREAT | O_RDWR, MYF(MY_WME))) < 0) {
5263 LogErr(ERROR_LEVEL, ER_AUTO_OPTIONS_FAILED, "file", fname, my_errno());
5264 return 1;
5265 }
5266
5267 if (init_io_cache(&io_cache, fd, IO_SIZE * 2, WRITE_CACHE, 0L, false,
5268 MYF(MY_WME))) {
5269 LogErr(ERROR_LEVEL, ER_AUTO_OPTIONS_FAILED, "a cache on ", fname,
5270 my_errno());
5271 my_close(fd, MYF(MY_WME));
5272 return 1;
5273 }
5274
5275 my_b_seek(&io_cache, 0L);
5276 my_b_printf(&io_cache, "%s\n", "[auto]");
5277 my_b_printf(&io_cache, "server-uuid=%s\n", server_uuid);
5278
5279 if (flush_io_cache(&io_cache) || my_sync(fd, MYF(MY_WME))) result = 1;
5280
5281 my_close(fd, MYF(MY_WME));
5282 end_io_cache(&io_cache);
5283 return result;
5284 }
5285
5286 /**
5287 File 'auto.cnf' resides in the data directory to hold values of options that
5288 server evaluates itself and that needs to be durable to sustain the server
5289 restart. There is only a section ['auto'] in the file. All these options are
5290 in the section. Only one option exists now, it is server_uuid.
5291 Note, the user may not supply any literal value to these auto-options, and
5292 only allowed to trigger (re)evaluation.
5293 For instance, 'server_uuid' value will be evaluated and stored if there is
5294 no corresponding line in the file.
5295 Because of the specifics of the auto-options, they need a seperate storage.
5296 Meanwhile, it is the 'auto.cnf' that has the same structure as 'my.cnf'.
5297
5298 @todo consider to implement sql-query-able persistent storage by WL#5279.
5299 @return Return 0 or 1 if an error occurred.
5300 */
init_server_auto_options()5301 static int init_server_auto_options() {
5302 bool flush = false;
5303 char fname[FN_REFLEN];
5304 char name[] = "auto";
5305 char *name_ptr = name;
5306 const char *groups[] = {"auto", nullptr};
5307 char *uuid = nullptr;
5308 my_option auto_options[] = {
5309 {"server-uuid", 0, "", &uuid, &uuid, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
5310 0, nullptr, 0, nullptr},
5311 {nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
5312 0, nullptr, 0, nullptr}};
5313
5314 DBUG_TRACE;
5315
5316 if (nullptr == fn_format(fname, "auto.cnf", mysql_data_home, "",
5317 MY_UNPACK_FILENAME | MY_SAFE_PATH))
5318 return 1;
5319
5320 /* load_defaults require argv[0] is not null */
5321 char **argv = &name_ptr;
5322 int argc = 1;
5323 if (!check_file_permissions(fname, false)) {
5324 /*
5325 Found a world writable file hence removing it as it is dangerous to write
5326 a new UUID into the same file.
5327 */
5328 my_delete(fname, MYF(MY_WME));
5329 LogErr(WARNING_LEVEL, ER_WRITABLE_CONFIG_REMOVED, fname);
5330 }
5331
5332 /* load all options in 'auto.cnf'. */
5333 MEM_ROOT alloc{PSI_NOT_INSTRUMENTED, 512};
5334 if (my_load_defaults(fname, groups, &argc, &argv, &alloc, nullptr)) return 1;
5335
5336 if (handle_options(&argc, &argv, auto_options, mysqld_get_one_option))
5337 return 1;
5338
5339 DBUG_PRINT("info", ("uuid=%p=%s server_uuid=%s", uuid, uuid, server_uuid));
5340 if (uuid) {
5341 if (!binary_log::Uuid::is_valid(uuid, binary_log::Uuid::TEXT_LENGTH)) {
5342 LogErr(ERROR_LEVEL, ER_UUID_INVALID);
5343 goto err;
5344 }
5345 /*
5346 Uuid::is_valid() cannot do strict check on the length as it will be
5347 called by GTID::is_valid() as well (GTID = UUID:seq_no). We should
5348 explicitly add the *length check* here in this function.
5349
5350 If UUID length is less than '36' (UUID_LENGTH), that error case would have
5351 got caught in above is_valid check. The below check is to make sure that
5352 length is not greater than UUID_LENGTH i.e., there are no extra characters
5353 (Garbage) at the end of the valid UUID.
5354 */
5355 if (strlen(uuid) > UUID_LENGTH) {
5356 LogErr(ERROR_LEVEL, ER_UUID_SCRUB, UUID_LENGTH);
5357 goto err;
5358 }
5359 strcpy(server_uuid, uuid);
5360 } else {
5361 DBUG_PRINT("info", ("generating server_uuid"));
5362 flush = true;
5363 /* server_uuid will be set in the function */
5364 if (generate_server_uuid()) goto err;
5365 DBUG_PRINT("info", ("generated server_uuid=%s", server_uuid));
5366 if (opt_initialize || opt_initialize_insecure) {
5367 LogErr(INFORMATION_LEVEL, ER_CREATING_NEW_UUID_FIRST_START, server_uuid);
5368
5369 } else {
5370 LogErr(WARNING_LEVEL, ER_CREATING_NEW_UUID, server_uuid);
5371 }
5372 }
5373
5374 if (flush) return flush_auto_options(fname);
5375 return 0;
5376 err:
5377 return 1;
5378 }
5379
initialize_storage_engine(const char * se_name,const char * se_kind,plugin_ref * dest_plugin)5380 static bool initialize_storage_engine(const char *se_name, const char *se_kind,
5381 plugin_ref *dest_plugin) {
5382 LEX_CSTRING name = {se_name, strlen(se_name)};
5383 plugin_ref plugin;
5384 handlerton *hton;
5385 if ((plugin = ha_resolve_by_name(nullptr, &name, false)))
5386 hton = plugin_data<handlerton *>(plugin);
5387 else {
5388 LogErr(ERROR_LEVEL, ER_UNKNOWN_UNSUPPORTED_STORAGE_ENGINE, se_name);
5389 return true;
5390 }
5391 if (!ha_storage_engine_is_enabled(hton)) {
5392 if (!opt_initialize) {
5393 LogErr(ERROR_LEVEL, ER_DEFAULT_SE_UNAVAILABLE, se_kind, se_name);
5394 return true;
5395 }
5396 DBUG_ASSERT(*dest_plugin);
5397 } else {
5398 /*
5399 Need to unlock as global_system_variables.table_plugin
5400 was acquired during plugin_register_builtin_and_init_core_se()
5401 */
5402 plugin_ref old_dest_plugin = *dest_plugin;
5403 *dest_plugin = plugin;
5404 plugin_unlock(nullptr, old_dest_plugin);
5405 }
5406 return false;
5407 }
5408
setup_error_log()5409 static void setup_error_log() {
5410 /* Setup logs */
5411
5412 /*
5413 Enable old-fashioned error log, except when the user has requested
5414 help information. Since the implementation of plugin server
5415 variables the help output is now written much later.
5416
5417 log_error_dest can be:
5418 disabled_my_option --log-error was not used or --log-error=
5419 "" --log-error without arguments (no '=')
5420 filename --log-error=filename
5421 */
5422 #ifdef _WIN32
5423 /*
5424 Enable the error log file only if console option is not specified
5425 and --help is not used.
5426 */
5427 bool log_errors_to_file = !is_help_or_validate_option() && !opt_console;
5428 #else
5429 /*
5430 Enable the error log file only if --log-error=filename or --log-error
5431 was used. Logging to file is disabled by default unlike on Windows.
5432 */
5433 bool log_errors_to_file =
5434 !is_help_or_validate_option() && (log_error_dest != disabled_my_option);
5435 #endif
5436
5437 enum log_error_stage les = LOG_ERROR_STAGE_BUFFERING_UNIPLEX;
5438
5439 if (log_errors_to_file) {
5440 // Construct filename if no filename was given by the user.
5441 if (!log_error_dest[0] || log_error_dest == disabled_my_option) {
5442 #ifdef _WIN32
5443 const char *filename = pidfile_name;
5444 #else
5445 const char *filename = default_logfile_name;
5446 #endif
5447 fn_format(errorlog_filename_buff, filename, mysql_real_data_home, ".err",
5448 MY_REPLACE_EXT | /* replace '.<domain>' by '.err', bug#4997 */
5449 MY_REPLACE_DIR);
5450 } else
5451 fn_format(errorlog_filename_buff, log_error_dest, mysql_data_home, ".err",
5452 MY_UNPACK_FILENAME);
5453 /*
5454 log_error_dest may have been set to disabled_my_option or "" if no
5455 argument was passed, but we need to show the real name in SHOW VARIABLES.
5456 */
5457 log_error_dest = errorlog_filename_buff;
5458
5459 #ifndef _WIN32
5460 // Create backup stream to stdout if deamonizing and connected to tty
5461 if (opt_daemonize && isatty(STDOUT_FILENO)) {
5462 nstdout = fdopen(dup(STDOUT_FILENO), "a");
5463 if (nstdout == nullptr) {
5464 LogErr(ERROR_LEVEL, ER_DUP_FD_OPEN_FAILED, "stdout", strerror(errno));
5465 unireg_abort(MYSQLD_ABORT_EXIT);
5466 }
5467 // Display location of error log file on stdout if connected to tty
5468 fprintf(nstdout, "mysqld will log errors to %s\n",
5469 errorlog_filename_buff);
5470 }
5471 #endif /* ndef _WIN32 */
5472
5473 if (open_error_log(errorlog_filename_buff, false))
5474 unireg_abort(MYSQLD_ABORT_EXIT);
5475
5476 #ifdef _WIN32
5477 // FreeConsole(); // Remove window
5478 #endif /* _WIN32 */
5479 } else {
5480 // We are logging to stderr and SHOW VARIABLES should reflect that.
5481 log_error_dest = "stderr";
5482
5483 /*
5484 We have no known file-name, and a non-standard logging pipeline,
5485 so output of multiple log-writers may be multi-plexed to stderr.
5486 This can result in false positives, but since we're only using
5487 this to turn off some optimizations, this seems acceptable for now.
5488 With regard to the pipeline, what matters is that a non-standard
5489 set-up was requested, not that it is actually active at this point
5490 (which it wouldn't be, we do not try to apply a user-supplied
5491 configuration until external components are available).
5492 */
5493 if ((opt_log_error_services == nullptr) ||
5494 (0 != strcmp(LOG_ERROR_SERVICES_DEFAULT, opt_log_error_services)))
5495 les = LOG_ERROR_STAGE_BUFFERING_MULTIPLEX;
5496 }
5497
5498 log_error_stage_set(les);
5499 }
5500
init_server_components()5501 static int init_server_components() {
5502 DBUG_TRACE;
5503 /*
5504 We need to call each of these following functions to ensure that
5505 all things are initialized so that unireg_abort() doesn't fail
5506 */
5507 mdl_init();
5508 partitioning_init();
5509 if (table_def_init() | hostname_cache_init(host_cache_size))
5510 unireg_abort(MYSQLD_ABORT_EXIT);
5511
5512 /*
5513 Timers not needed if only starting with --help.
5514 */
5515 if (!is_help_or_validate_option()) {
5516 if (my_timer_initialize())
5517 LogErr(ERROR_LEVEL, ER_CANT_INIT_TIMER, errno);
5518 else
5519 have_statement_timeout = SHOW_OPTION_YES;
5520 }
5521
5522 randominit(&sql_rand, (ulong)server_start_time, (ulong)server_start_time / 2);
5523 setup_fpu();
5524 init_slave_list();
5525
5526 setup_error_log(); // opens the log if needed
5527
5528 enter_cond_hook = thd_enter_cond;
5529 exit_cond_hook = thd_exit_cond;
5530 enter_stage_hook = thd_enter_stage;
5531 set_waiting_for_disk_space_hook = thd_set_waiting_for_disk_space;
5532 is_killed_hook = thd_killed;
5533
5534 if (transaction_cache_init()) {
5535 LogErr(ERROR_LEVEL, ER_OOM);
5536 unireg_abort(MYSQLD_ABORT_EXIT);
5537 }
5538
5539 if (MDL_context_backup_manager::init()) {
5540 LogErr(ERROR_LEVEL, ER_OOM);
5541 unireg_abort(MYSQLD_ABORT_EXIT);
5542 }
5543
5544 /*
5545 initialize delegates for extension observers, errors have already
5546 been reported in the function
5547 */
5548 if (delegates_init()) unireg_abort(MYSQLD_ABORT_EXIT);
5549
5550 /* need to configure logging before initializing storage engines */
5551 if (opt_log_slave_updates && !opt_bin_log) {
5552 LogErr(WARNING_LEVEL, ER_NEED_LOG_BIN, "--log-slave-updates");
5553 }
5554 if (binlog_format_used && !opt_bin_log)
5555 LogErr(WARNING_LEVEL, ER_NEED_LOG_BIN, "--binlog-format");
5556
5557 /* Check that we have not let the format to unspecified at this point */
5558 DBUG_ASSERT((uint)global_system_variables.binlog_format <=
5559 array_elements(binlog_format_names) - 1);
5560
5561 opt_server_id_mask = ~ulong(0);
5562 opt_server_id_mask =
5563 (opt_server_id_bits == 32) ? ~ulong(0) : (1 << opt_server_id_bits) - 1;
5564 if (server_id != (server_id & opt_server_id_mask)) {
5565 LogErr(ERROR_LEVEL, ER_SERVERID_TOO_LARGE);
5566 unireg_abort(MYSQLD_ABORT_EXIT);
5567 }
5568
5569 if (opt_bin_log) {
5570 /* Reports an error and aborts, if the --log-bin's path
5571 is a directory.*/
5572 if (opt_bin_logname &&
5573 opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR) {
5574 LogErr(ERROR_LEVEL, ER_NEED_FILE_INSTEAD_OF_DIR, "--log-bin",
5575 opt_bin_logname);
5576 unireg_abort(MYSQLD_ABORT_EXIT);
5577 }
5578
5579 /* Reports an error and aborts, if the --log-bin-index's path
5580 is a directory.*/
5581 if (opt_binlog_index_name &&
5582 opt_binlog_index_name[strlen(opt_binlog_index_name) - 1] ==
5583 FN_LIBCHAR) {
5584 LogErr(ERROR_LEVEL, ER_NEED_FILE_INSTEAD_OF_DIR, "--log-bin-index",
5585 opt_binlog_index_name);
5586 unireg_abort(MYSQLD_ABORT_EXIT);
5587 }
5588
5589 char buf[FN_REFLEN];
5590 const char *ln;
5591 if (log_bin_supplied) {
5592 /*
5593 Binary log basename defaults to "`hostname`-bin" name prefix
5594 if --log-bin is used without argument.
5595 */
5596 ln = mysql_bin_log.generate_name(opt_bin_logname, "-bin", buf);
5597 } else {
5598 /*
5599 Binary log basename defaults to "binlog" name prefix
5600 if --log-bin is not used.
5601 */
5602 ln = mysql_bin_log.generate_name(opt_bin_logname, "", buf);
5603 }
5604
5605 if (!opt_bin_logname && !opt_binlog_index_name && log_bin_supplied) {
5606 /*
5607 User didn't give us info to name the binlog index file.
5608 Picking `hostname`-bin.index like did in 4.x, causes replication to
5609 fail if the hostname is changed later. So, we would like to instead
5610 require a name. But as we don't want to break many existing setups, we
5611 only give warning, not error.
5612 */
5613 LogErr(INFORMATION_LEVEL, ER_LOG_BIN_BETTER_WITH_NAME, ln);
5614 }
5615 if (ln == buf) {
5616 my_free(opt_bin_logname);
5617 opt_bin_logname = my_strdup(key_memory_opt_bin_logname, buf, MYF(0));
5618 }
5619
5620 /*
5621 Skip opening the index file if we start with --help. This is necessary
5622 to avoid creating the file in an otherwise empty datadir, which will
5623 cause a succeeding 'mysqld --initialize' to fail.
5624 */
5625 if (!is_help_or_validate_option() &&
5626 mysql_bin_log.open_index_file(opt_binlog_index_name, ln, true)) {
5627 unireg_abort(MYSQLD_ABORT_EXIT);
5628 }
5629 }
5630
5631 if (opt_bin_log) {
5632 /*
5633 opt_bin_logname[0] needs to be checked to make sure opt binlog name is
5634 not an empty string, incase it is an empty string default file
5635 extension will be passed
5636 */
5637 if (log_bin_supplied) {
5638 log_bin_basename = rpl_make_log_name(
5639 key_memory_MYSQL_BIN_LOG_basename, opt_bin_logname,
5640 default_logfile_name,
5641 (opt_bin_logname && opt_bin_logname[0]) ? "" : "-bin");
5642 } else {
5643 log_bin_basename =
5644 rpl_make_log_name(key_memory_MYSQL_BIN_LOG_basename, opt_bin_logname,
5645 default_binlogfile_name, "");
5646 }
5647
5648 log_bin_index =
5649 rpl_make_log_name(key_memory_MYSQL_BIN_LOG_index, opt_binlog_index_name,
5650 log_bin_basename, ".index");
5651
5652 if ((!opt_binlog_index_name || !opt_binlog_index_name[0]) &&
5653 log_bin_index) {
5654 strmake(default_binlog_index_name,
5655 log_bin_index + dirname_length(log_bin_index),
5656 FN_REFLEN + index_ext_length - 1);
5657 opt_binlog_index_name = default_binlog_index_name;
5658 }
5659
5660 if (log_bin_basename == nullptr || log_bin_index == nullptr) {
5661 LogErr(ERROR_LEVEL, ER_RPL_CANT_MAKE_PATHS, (int)FN_REFLEN, (int)FN_LEN);
5662 unireg_abort(MYSQLD_ABORT_EXIT);
5663 }
5664 }
5665
5666 DBUG_PRINT("debug",
5667 ("opt_bin_logname: %s, opt_relay_logname: %s, pidfile_name: %s",
5668 opt_bin_logname, opt_relay_logname, pidfile_name));
5669
5670 /*
5671 opt_relay_logname[0] needs to be checked to make sure opt relaylog name is
5672 not an empty string, incase it is an empty string default file
5673 extension will be passed
5674 */
5675 relay_log_basename = rpl_make_log_name(
5676 key_memory_MYSQL_RELAY_LOG_basename, opt_relay_logname,
5677 default_logfile_name,
5678 (opt_relay_logname && opt_relay_logname[0]) ? "" : relay_ext);
5679
5680 if (!opt_relay_logname || !opt_relay_logname[0]) {
5681 if (relay_log_basename) {
5682 strmake(default_relaylogfile_name,
5683 relay_log_basename + dirname_length(relay_log_basename),
5684 FN_REFLEN + relay_ext_length - 1);
5685 opt_relay_logname = default_relaylogfile_name;
5686 }
5687 } else
5688 opt_relay_logname_supplied = true;
5689
5690 if (relay_log_basename != nullptr)
5691 relay_log_index = rpl_make_log_name(key_memory_MYSQL_RELAY_LOG_index,
5692 opt_relaylog_index_name,
5693 relay_log_basename, ".index");
5694
5695 if (!opt_relaylog_index_name || !opt_relaylog_index_name[0]) {
5696 if (relay_log_index) {
5697 strmake(default_relaylog_index_name,
5698 relay_log_index + dirname_length(relay_log_index),
5699 FN_REFLEN + relay_ext_length + index_ext_length - 1);
5700 opt_relaylog_index_name = default_relaylog_index_name;
5701 }
5702 } else
5703 opt_relaylog_index_name_supplied = true;
5704
5705 if (relay_log_basename == nullptr || relay_log_index == nullptr) {
5706 LogErr(ERROR_LEVEL, ER_RPL_CANT_MAKE_PATHS, (int)FN_REFLEN, (int)FN_LEN);
5707 unireg_abort(MYSQLD_ABORT_EXIT);
5708 }
5709
5710 if (log_bin_basename != nullptr &&
5711 !strcmp(log_bin_basename, relay_log_basename)) {
5712 const int bin_ext_length = 4;
5713 char default_binlogfile_name_from_hostname[FN_REFLEN + bin_ext_length];
5714 /* Generate default bin log file name. */
5715 strmake(default_binlogfile_name_from_hostname, default_logfile_name,
5716 FN_REFLEN - 1);
5717 strcat(default_binlogfile_name_from_hostname, "-bin");
5718
5719 if (!default_relaylogfile_name[0]) {
5720 /* Generate default relay log file name. */
5721 strmake(default_relaylogfile_name, default_logfile_name, FN_REFLEN - 1);
5722 strcat(default_relaylogfile_name, relay_ext);
5723 }
5724 /*
5725 Reports an error and aborts, if the same base name is specified
5726 for both binary and relay logs.
5727 */
5728 LogErr(ERROR_LEVEL, ER_RPL_CANT_HAVE_SAME_BASENAME, log_bin_basename,
5729 "--log-bin", default_binlogfile_name,
5730 default_binlogfile_name_from_hostname, "--relay-log",
5731 default_relaylogfile_name);
5732 unireg_abort(MYSQLD_ABORT_EXIT);
5733 }
5734
5735 if (global_system_variables.binlog_row_value_options != 0) {
5736 const char *msg = nullptr;
5737 longlong err = ER_BINLOG_ROW_VALUE_OPTION_IGNORED;
5738 if (!opt_bin_log)
5739 msg = "the binary log is disabled";
5740 else if (global_system_variables.binlog_format == BINLOG_FORMAT_STMT)
5741 msg = "binlog_format=STATEMENT";
5742 else if (log_bin_use_v1_row_events) {
5743 msg = "binlog_row_value_options=PARTIAL_JSON";
5744 err = ER_BINLOG_USE_V1_ROW_EVENTS_IGNORED;
5745 } else if (global_system_variables.binlog_row_image ==
5746 BINLOG_ROW_IMAGE_FULL) {
5747 msg = "binlog_row_image=FULL";
5748 err = ER_BINLOG_ROW_VALUE_OPTION_USED_ONLY_FOR_AFTER_IMAGES;
5749 }
5750 if (msg) {
5751 switch (err) {
5752 case ER_BINLOG_ROW_VALUE_OPTION_IGNORED:
5753 case ER_BINLOG_ROW_VALUE_OPTION_USED_ONLY_FOR_AFTER_IMAGES:
5754 LogErr(WARNING_LEVEL, err, msg, "PARTIAL_JSON");
5755 break;
5756 case ER_BINLOG_USE_V1_ROW_EVENTS_IGNORED:
5757 LogErr(WARNING_LEVEL, err, msg);
5758 break;
5759 default:
5760 DBUG_ASSERT(0); /* purecov: deadcode */
5761 }
5762 }
5763 }
5764
5765 /* call ha_init_key_cache() on all key caches to init them */
5766 process_key_caches(&ha_init_key_cache);
5767
5768 /* Allow storage engine to give real error messages */
5769 if (ha_init_errors()) return 1;
5770
5771 if (gtid_server_init()) {
5772 LogErr(ERROR_LEVEL, ER_CANT_INITIALIZE_GTID);
5773 unireg_abort(MYSQLD_ABORT_EXIT);
5774 }
5775
5776 if (opt_log_slave_updates && replicate_same_server_id) {
5777 if (opt_bin_log && global_gtid_mode.get() != Gtid_mode::ON) {
5778 LogErr(ERROR_LEVEL, ER_RPL_INFINITY_DENIED);
5779 unireg_abort(MYSQLD_ABORT_EXIT);
5780 } else
5781 LogErr(WARNING_LEVEL, ER_RPL_INFINITY_IGNORED);
5782 }
5783
5784 {
5785 /*
5786 We have to call a function in log_resource.cc, or its references
5787 won't be visible to plugins.
5788 */
5789 #ifndef DBUG_OFF
5790 int dummy =
5791 #endif
5792 Log_resource::dummy_function_to_ensure_we_are_linked_into_the_server();
5793 DBUG_ASSERT(dummy == 1);
5794 }
5795
5796 /*
5797 We need to initialize the UDF globals early before reading the proc table
5798 and before the server component initialization to allow other components
5799 to register their UDFs at init time and de-register them at deinit time.
5800 */
5801 udf_init_globals();
5802
5803 /*
5804 Set tc_log to point to TC_LOG_DUMMY early in order to allow plugin_init()
5805 to commit attachable transaction after reading from mysql.plugin table.
5806 If necessary tc_log will be adjusted to point to correct TC_LOG instance
5807 later.
5808 */
5809 tc_log = &tc_log_dummy;
5810
5811 /* This limits ability to configure SSL library through config options */
5812 init_ssl();
5813
5814 /*Load early plugins */
5815 if (plugin_register_early_plugins(&remaining_argc, remaining_argv,
5816 (is_help_or_validate_option())
5817 ? PLUGIN_INIT_SKIP_INITIALIZATION
5818 : 0)) {
5819 LogErr(ERROR_LEVEL, ER_CANT_INITIALIZE_EARLY_PLUGINS);
5820 unireg_abort(1);
5821 }
5822
5823 /* Load builtin plugins, initialize MyISAM, CSV and InnoDB */
5824 if (plugin_register_builtin_and_init_core_se(&remaining_argc,
5825 remaining_argv)) {
5826 if (!opt_validate_config)
5827 LogErr(ERROR_LEVEL, ER_CANT_INITIALIZE_BUILTIN_PLUGINS);
5828 unireg_abort(1);
5829 }
5830
5831 /*
5832 Needs to be done before dd::init() which runs DDL commands (for real)
5833 during instance initialization.
5834 */
5835 init_sql_command_flags();
5836
5837 /*
5838 plugin_register_dynamic_and_init_all() needs DD initialized.
5839 Initialize DD to create data directory using current server.
5840 */
5841 if (opt_initialize) {
5842 if (!is_help_or_validate_option()) {
5843 if (dd::init(dd::enum_dd_init_type::DD_INITIALIZE)) {
5844 LogErr(ERROR_LEVEL, ER_DD_INIT_FAILED);
5845 unireg_abort(1);
5846 }
5847
5848 if (dd::init(dd::enum_dd_init_type::DD_INITIALIZE_SYSTEM_VIEWS)) {
5849 LogErr(ERROR_LEVEL, ER_SYSTEM_VIEW_INIT_FAILED);
5850 unireg_abort(1);
5851 }
5852 }
5853 } else {
5854 /*
5855 Initialize DD in case of upgrade and normal normal server restart.
5856 It is detected if we are starting on old data directory or current
5857 data directory. If it is old data directory, DD tables are created.
5858 If server is starting on data directory with DD tables, DD is initialized.
5859 */
5860 if (!is_help_or_validate_option() &&
5861 dd::init(dd::enum_dd_init_type::DD_RESTART_OR_UPGRADE)) {
5862 LogErr(ERROR_LEVEL, ER_DD_INIT_FAILED);
5863
5864 /* If clone recovery fails, we rollback the files to previous
5865 dataset and attempt to restart server. */
5866 int exit_code =
5867 clone_recovery_error ? MYSQLD_RESTART_EXIT : MYSQLD_ABORT_EXIT;
5868 unireg_abort(exit_code);
5869 }
5870 }
5871
5872 /*
5873 During plugin initialization, a plugin may expect (depending on what the
5874 plugin actually does) to find a functional server, including:
5875 - mysql system tables
5876 - information schema tables
5877 - performance schema tables
5878 - data dictionary
5879 - components / services, including the registry service
5880 During the server installation, all these parts are not available yet, as
5881 they are created during the installation process with mysqld --initialize.
5882
5883 As a result, plugins are not loaded during mysqld --initialize, so that
5884 the server install can proceed and complete before any plugin is loaded
5885 through any config file or pre-programmed command line.
5886 */
5887 int flags = 0;
5888
5889 if (opt_noacl) flags |= PLUGIN_INIT_SKIP_PLUGIN_TABLE;
5890 if (is_help_or_validate_option())
5891 flags |= PLUGIN_INIT_SKIP_INITIALIZATION | PLUGIN_INIT_SKIP_PLUGIN_TABLE;
5892 if (opt_initialize) flags |= PLUGIN_INIT_SKIP_DYNAMIC_LOADING;
5893
5894 /*
5895 In the case of upgrade, we need to delay initialization of plugins that
5896 depend on e.g. mysql tables that will be changed during upgrade.
5897 */
5898 if (!is_help_or_validate_option() && !opt_initialize &&
5899 !dd::upgrade::no_server_upgrade_required() &&
5900 opt_upgrade_mode != UPGRADE_MINIMAL)
5901 flags |= PLUGIN_INIT_DELAY_UNTIL_AFTER_UPGRADE;
5902
5903 if (plugin_register_dynamic_and_init_all(&remaining_argc, remaining_argv,
5904 flags)) {
5905 // Delete all DD tables in case of error in initializing plugins.
5906 if (dd::upgrade_57::in_progress())
5907 (void)dd::init(dd::enum_dd_init_type::DD_DELETE);
5908
5909 if (!opt_validate_config)
5910 LogErr(ERROR_LEVEL, ER_CANT_INITIALIZE_DYNAMIC_PLUGINS);
5911 unireg_abort(MYSQLD_ABORT_EXIT);
5912 }
5913 dynamic_plugins_are_initialized =
5914 true; /* Don't separate from init function */
5915
5916 LEX_CSTRING plugin_name = {STRING_WITH_LEN("thread_pool")};
5917 if (Connection_handler_manager::thread_handling !=
5918 Connection_handler_manager::SCHEDULER_ONE_THREAD_PER_CONNECTION ||
5919 plugin_is_ready(plugin_name, MYSQL_DAEMON_PLUGIN)) {
5920 auto res_grp_mgr = resourcegroups::Resource_group_mgr::instance();
5921 res_grp_mgr->disable_resource_group();
5922 res_grp_mgr->set_unsupport_reason("Thread pool plugin enabled");
5923 }
5924
5925 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5926 /*
5927 A value of the variable dd_upgrade_flag is reset after
5928 dd::init(dd::enum_dd_init_type::DD_POPULATE_UPGRADE) returned.
5929 So make its copy to call init_pfs_tables() with right argument value later.
5930 */
5931 bool dd_upgrade_was_initiated = dd::upgrade_57::in_progress();
5932 #endif
5933
5934 if (!is_help_or_validate_option() && dd::upgrade_57::in_progress()) {
5935 // Populate DD tables with meta data from 5.7
5936 if (dd::init(dd::enum_dd_init_type::DD_POPULATE_UPGRADE)) {
5937 LogErr(ERROR_LEVEL, ER_DD_POPULATING_TABLES_FAILED);
5938 unireg_abort(1);
5939 }
5940 // Run after_dd_upgrade hook
5941 if (RUN_HOOK(server_state, after_dd_upgrade_from_57, (nullptr)))
5942 unireg_abort(MYSQLD_ABORT_EXIT);
5943 }
5944
5945 /*
5946 Store server and plugin IS tables metadata into new DD.
5947 This is done after all the plugins are registered.
5948 */
5949 if (!is_help_or_validate_option() && !opt_initialize &&
5950 !dd::upgrade_57::in_progress() &&
5951 dd::init(dd::enum_dd_init_type::DD_UPDATE_I_S_METADATA)) {
5952 LogErr(ERROR_LEVEL, ER_DD_UPDATING_PLUGIN_MD_FAILED);
5953 unireg_abort(MYSQLD_ABORT_EXIT);
5954 }
5955
5956 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5957 if (!is_help_or_validate_option()) {
5958 /*
5959 Initialize the cost model, but delete it after the pfs is initialized.
5960 Cost model is needed while dropping and creating pfs tables to
5961 update metadata of referencing views (if there are any).
5962 */
5963 init_optimizer_cost_module(true);
5964
5965 bool st;
5966 if (opt_initialize || dd_upgrade_was_initiated)
5967 st = dd::performance_schema::init_pfs_tables(
5968 dd::enum_dd_init_type::DD_INITIALIZE);
5969 else
5970 st = dd::performance_schema::init_pfs_tables(
5971 dd::enum_dd_init_type::DD_RESTART_OR_UPGRADE);
5972
5973 /* Now that the pfs is initialized, delete the cost model. */
5974 delete_optimizer_cost_module();
5975
5976 if (st) {
5977 LogErr(ERROR_LEVEL, ER_PERFSCHEMA_TABLES_INIT_FAILED);
5978 unireg_abort(1);
5979 }
5980 }
5981 #endif
5982
5983 bool recreate_non_dd_based_system_view = dd::upgrade::I_S_upgrade_required();
5984 if (!is_help_or_validate_option() && !opt_initialize &&
5985 !dd::upgrade::no_server_upgrade_required()) {
5986 if (opt_upgrade_mode == UPGRADE_MINIMAL)
5987 LogErr(WARNING_LEVEL, ER_SERVER_UPGRADE_SKIP);
5988 else {
5989 init_optimizer_cost_module(true);
5990 if (bootstrap::run_bootstrap_thread(nullptr, nullptr,
5991 &dd::upgrade::upgrade_system_schemas,
5992 SYSTEM_THREAD_SERVER_UPGRADE)) {
5993 LogErr(ERROR_LEVEL, ER_SERVER_UPGRADE_FAILED);
5994 unireg_abort(MYSQLD_ABORT_EXIT);
5995 }
5996 delete_optimizer_cost_module();
5997 recreate_non_dd_based_system_view = true;
5998
5999 /*
6000 When upgrade is finished, we need to initialize the plugins that
6001 had their initialization delayed due to dependencies on the
6002 environment.
6003
6004 TODO: Provide a better long term solution by re-ordering startup
6005 sequence and rewriting the way we create and upgrade server
6006 resources needed by plugins.
6007 */
6008 if (dd::upgrade::plugin_initialize_delayed_after_upgrade()) {
6009 unireg_abort(MYSQLD_ABORT_EXIT);
6010 }
6011 }
6012 }
6013
6014 /*
6015 Re-create non DD based system views after a) if we upgraded system
6016 schemas b) I_S system view version is changed and server system views
6017 were recreated. c) If the database was upgraded. We do not update this
6018 in upgrade-minimal mode.
6019 */
6020 if (!is_help_or_validate_option() && !opt_initialize &&
6021 opt_upgrade_mode != UPGRADE_MINIMAL &&
6022 recreate_non_dd_based_system_view) {
6023 if (dd::init(
6024 dd::enum_dd_init_type::DD_INITIALIZE_NON_DD_BASED_SYSTEM_VIEWS)) {
6025 LogErr(ERROR_LEVEL, ER_SYSTEM_VIEW_INIT_FAILED);
6026 unireg_abort(MYSQLD_ABORT_EXIT);
6027 }
6028 }
6029
6030 auto res_grp_mgr = resourcegroups::Resource_group_mgr::instance();
6031 // Initialize the Resource group subsystem.
6032 if (!is_help_or_validate_option() && !opt_initialize) {
6033 if (res_grp_mgr->post_init()) {
6034 LogErr(ERROR_LEVEL, ER_RESOURCE_GROUP_POST_INIT_FAILED);
6035 unireg_abort(MYSQLD_ABORT_EXIT);
6036 }
6037 }
6038
6039 Session_tracker session_track_system_variables_check;
6040 LEX_STRING var_list;
6041 char *tmp_str;
6042 size_t len = strlen(global_system_variables.track_sysvars_ptr);
6043 tmp_str = (char *)my_malloc(PSI_NOT_INSTRUMENTED, len * sizeof(char) + 2,
6044 MYF(MY_WME));
6045 strcpy(tmp_str, global_system_variables.track_sysvars_ptr);
6046 var_list.length = len;
6047 var_list.str = tmp_str;
6048 if (session_track_system_variables_check.server_boot_verify(
6049 system_charset_info, var_list)) {
6050 LogErr(ERROR_LEVEL, ER_TRACK_VARIABLES_BOGUS);
6051 if (tmp_str) my_free(tmp_str);
6052 unireg_abort(MYSQLD_ABORT_EXIT);
6053 }
6054 if (tmp_str) my_free(tmp_str);
6055
6056 // Validate the configuration if --validate-config was specified.
6057 if (opt_validate_config && (remaining_argc > 1)) {
6058 bool saved_getopt_skip_unknown = my_getopt_skip_unknown;
6059 struct my_option no_opts[] = {{nullptr, 0, nullptr, nullptr, nullptr,
6060 nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0,
6061 nullptr, 0, nullptr}};
6062
6063 my_getopt_skip_unknown = false;
6064
6065 if (handle_options(&remaining_argc, &remaining_argv, no_opts,
6066 mysqld_get_one_option))
6067 unireg_abort(MYSQLD_ABORT_EXIT);
6068 my_getopt_skip_unknown = saved_getopt_skip_unknown;
6069 }
6070
6071 if (is_help_or_validate_option()) unireg_abort(MYSQLD_SUCCESS_EXIT);
6072
6073 /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
6074 if (!my_default_lc_messages->errmsgs->is_loaded()) {
6075 LogErr(ERROR_LEVEL, ER_CANT_READ_ERRMSGS);
6076 unireg_abort(MYSQLD_ABORT_EXIT);
6077 }
6078
6079 /* We have to initialize the storage engines before CSV logging */
6080 if (ha_init()) {
6081 LogErr(ERROR_LEVEL, ER_CANT_INIT_DBS);
6082 unireg_abort(MYSQLD_ABORT_EXIT);
6083 }
6084
6085 /* Initialize ndbinfo tables in DD */
6086 if (dd::ndbinfo::init_schema_and_tables(opt_upgrade_mode)) {
6087 LogErr(ERROR_LEVEL, ER_NDBINFO_UPGRADING_SCHEMA_FAIL);
6088 unireg_abort(1);
6089 }
6090
6091 if (opt_initialize) log_output_options = LOG_FILE;
6092
6093 /*
6094 Issue a warning if there were specified additional options to the
6095 log-output along with NONE. Probably this wasn't what user wanted.
6096 */
6097 if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
6098 LogErr(WARNING_LEVEL, ER_LOG_OUTPUT_CONTRADICTORY);
6099
6100 if (log_output_options & LOG_TABLE) {
6101 /* Fall back to log files if the csv engine is not loaded. */
6102 LEX_CSTRING csv_name = {STRING_WITH_LEN("csv")};
6103 if (!plugin_is_ready(csv_name, MYSQL_STORAGE_ENGINE_PLUGIN)) {
6104 LogErr(ERROR_LEVEL, ER_NO_CSV_NO_LOG_TABLES);
6105 log_output_options = (log_output_options & ~LOG_TABLE) | LOG_FILE;
6106 }
6107 }
6108
6109 query_logger.set_handlers(log_output_options);
6110
6111 // Open slow log file if enabled.
6112 query_logger.set_log_file(QUERY_LOG_SLOW);
6113 if (opt_slow_log && query_logger.reopen_log_file(QUERY_LOG_SLOW))
6114 opt_slow_log = false;
6115
6116 // Open general log file if enabled.
6117 query_logger.set_log_file(QUERY_LOG_GENERAL);
6118 if (opt_general_log && query_logger.reopen_log_file(QUERY_LOG_GENERAL))
6119 opt_general_log = false;
6120
6121 /*
6122 Set the default storage engines
6123 */
6124 if (initialize_storage_engine(default_storage_engine, "",
6125 &global_system_variables.table_plugin))
6126 unireg_abort(MYSQLD_ABORT_EXIT);
6127 if (initialize_storage_engine(default_tmp_storage_engine, " temp",
6128 &global_system_variables.temp_table_plugin))
6129 unireg_abort(MYSQLD_ABORT_EXIT);
6130
6131 if (!opt_initialize && !opt_noacl) {
6132 set_externally_disabled_storage_engine_names(opt_disabled_storage_engines);
6133
6134 // Log warning if default_storage_engine is a disabled storage engine.
6135 handlerton *default_se_handle =
6136 plugin_data<handlerton *>(global_system_variables.table_plugin);
6137 if (ha_is_storage_engine_disabled(default_se_handle))
6138 LogErr(WARNING_LEVEL, ER_DISABLED_STORAGE_ENGINE_AS_DEFAULT,
6139 "default_storage_engine", default_storage_engine);
6140
6141 // Log warning if default_tmp_storage_engine is a disabled storage engine.
6142 handlerton *default_tmp_se_handle =
6143 plugin_data<handlerton *>(global_system_variables.temp_table_plugin);
6144 if (ha_is_storage_engine_disabled(default_tmp_se_handle))
6145 LogErr(WARNING_LEVEL, ER_DISABLED_STORAGE_ENGINE_AS_DEFAULT,
6146 "default_tmp_storage_engine", default_tmp_storage_engine);
6147 }
6148
6149 if (total_ha_2pc > 1 || (1 == total_ha_2pc && opt_bin_log)) {
6150 if (opt_bin_log)
6151 tc_log = &mysql_bin_log;
6152 else
6153 tc_log = &tc_log_mmap;
6154 }
6155
6156 if (Recovered_xa_transactions::init()) {
6157 LogErr(ERROR_LEVEL, ER_OOM);
6158 unireg_abort(MYSQLD_ABORT_EXIT);
6159 }
6160
6161 if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file)) {
6162 LogErr(ERROR_LEVEL, ER_CANT_INIT_TC_LOG);
6163 unireg_abort(MYSQLD_ABORT_EXIT);
6164 }
6165 (void)RUN_HOOK(server_state, before_recovery, (nullptr));
6166 if (ha_recover(nullptr)) {
6167 unireg_abort(MYSQLD_ABORT_EXIT);
6168 }
6169
6170 if (dd::reset_tables_and_tablespaces()) {
6171 unireg_abort(MYSQLD_ABORT_EXIT);
6172 }
6173 ha_post_recover();
6174
6175 /*
6176 Add prepared XA transactions into the cache of XA transactions and acquire
6177 mdl lock for every table involved in any of these prepared XA transactions.
6178 This step moved away from the function ha_recover() in order to avoid
6179 possible suspending on acquiring EXLUSIVE mdl lock on tables inside the
6180 function dd::reset_tables_and_tablespaces() when table cache being reset.
6181 */
6182 if (Recovered_xa_transactions::instance()
6183 .recover_prepared_xa_transactions()) {
6184 unireg_abort(MYSQLD_ABORT_EXIT);
6185 }
6186
6187 if (global_gtid_mode.get() == Gtid_mode::ON &&
6188 _gtid_consistency_mode != GTID_CONSISTENCY_MODE_ON) {
6189 LogErr(ERROR_LEVEL, ER_RPL_GTID_MODE_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON);
6190 unireg_abort(MYSQLD_ABORT_EXIT);
6191 }
6192
6193 /*
6194 Each server should have one UUID. We will create it automatically, if it
6195 does not exist. It should be initialized before opening binlog file. Because
6196 server's uuid will be stored into the new binlog file.
6197 */
6198 if (init_server_auto_options()) {
6199 LogErr(ERROR_LEVEL, ER_CANT_CREATE_UUID);
6200 unireg_abort(MYSQLD_ABORT_EXIT);
6201 }
6202
6203 if (rpl_encryption.initialize()) {
6204 LogErr(ERROR_LEVEL, ER_SERVER_RPL_ENCRYPTION_UNABLE_TO_INITIALIZE);
6205 unireg_abort(MYSQLD_ABORT_EXIT);
6206 }
6207
6208 if (opt_bin_log) {
6209 /*
6210 Configures what object is used by the current log to store processed
6211 gtid(s). This is necessary in the MYSQL_BIN_LOG::MYSQL_BIN_LOG to
6212 corretly compute the set of previous gtids.
6213 */
6214 DBUG_ASSERT(!mysql_bin_log.is_relay_log);
6215 mysql_mutex_t *log_lock = mysql_bin_log.get_log_lock();
6216 mysql_mutex_lock(log_lock);
6217
6218 if (mysql_bin_log.open_binlog(opt_bin_logname, nullptr, max_binlog_size,
6219 false, true /*need_lock_index=true*/,
6220 true /*need_sid_lock=true*/, nullptr)) {
6221 mysql_mutex_unlock(log_lock);
6222 unireg_abort(MYSQLD_ABORT_EXIT);
6223 }
6224 mysql_mutex_unlock(log_lock);
6225 }
6226
6227 /*
6228 When we pass non-zero values for both expire_logs_days and
6229 binlog_expire_logs_seconds at the server start-up, the value of
6230 expire_logs_days will be ignored and only binlog_expire_logs_seconds
6231 will be used.
6232 */
6233 if (binlog_expire_logs_seconds_supplied && expire_logs_days_supplied) {
6234 if (binlog_expire_logs_seconds != 0 && expire_logs_days != 0) {
6235 LogErr(WARNING_LEVEL, ER_EXPIRE_LOGS_DAYS_IGNORED);
6236 expire_logs_days = 0;
6237 }
6238 } else if (expire_logs_days_supplied)
6239 binlog_expire_logs_seconds = 0;
6240 DBUG_ASSERT(expire_logs_days == 0 || binlog_expire_logs_seconds == 0);
6241
6242 if (opt_bin_log) {
6243 if (expire_logs_days > 0 || binlog_expire_logs_seconds > 0) {
6244 time_t purge_time = my_time(0) - binlog_expire_logs_seconds -
6245 expire_logs_days * 24 * 60 * 60;
6246 DBUG_EXECUTE_IF("expire_logs_always_at_start",
6247 { purge_time = my_time(0); });
6248 mysql_bin_log.purge_logs_before_date(purge_time, true);
6249 }
6250 } else {
6251 if (binlog_expire_logs_seconds_supplied)
6252 LogErr(WARNING_LEVEL, ER_NEED_LOG_BIN, "--binlog-expire-logs-seconds");
6253 if (expire_logs_days_supplied)
6254 LogErr(WARNING_LEVEL, ER_NEED_LOG_BIN, "--expire_logs_days");
6255 }
6256
6257 if (opt_myisam_log) (void)mi_log(1);
6258
6259 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
6260 if (locked_in_memory && !getuid()) {
6261 if (setreuid((uid_t)-1, 0) == -1) { // this should never happen
6262 LogErr(ERROR_LEVEL, ER_FAIL_SETREUID, strerror(errno));
6263 unireg_abort(MYSQLD_ABORT_EXIT);
6264 }
6265 if (mlockall(MCL_CURRENT)) {
6266 LogErr(WARNING_LEVEL, ER_FAILED_TO_LOCK_MEM,
6267 errno); /* purecov: inspected */
6268 locked_in_memory = false;
6269 }
6270 #ifndef _WIN32
6271 if (!user_info.IsVoid()) set_user(mysqld_user, user_info);
6272 #endif
6273 } else
6274 #endif
6275 locked_in_memory = false;
6276
6277 /* Initialize the optimizer cost module */
6278 init_optimizer_cost_module(true);
6279 ft_init_stopwords();
6280
6281 init_max_user_conn();
6282
6283 return 0;
6284 }
6285
6286 #ifdef _WIN32
6287
handle_shutdown_and_restart(void * arg)6288 extern "C" void *handle_shutdown_and_restart(void *arg) {
6289 MSG msg;
6290 HANDLE event_handles[2];
6291 event_handles[0] = hEventShutdown;
6292 event_handles[1] = hEventRestart;
6293
6294 my_thread_init();
6295 /* This call should create the message queue for this thread. */
6296 PeekMessage(&msg, NULL, 1, 65534, PM_NOREMOVE);
6297 DWORD ret_code = WaitForMultipleObjects(
6298 2, static_cast<HANDLE *>(event_handles), FALSE, INFINITE);
6299
6300 if (ret_code == WAIT_OBJECT_0 || ret_code == WAIT_OBJECT_0 + 1) {
6301 if (ret_code == WAIT_OBJECT_0)
6302 LogErr(SYSTEM_LEVEL, ER_NORMAL_SERVER_SHUTDOWN, my_progname);
6303 else
6304 signal_hand_thr_exit_code = MYSQLD_RESTART_EXIT;
6305
6306 set_connection_events_loop_aborted(true);
6307 close_connections();
6308 my_thread_end();
6309 my_thread_exit(0);
6310 }
6311 return 0;
6312 }
6313
create_shutdown_and_restart_thread()6314 static void create_shutdown_and_restart_thread() {
6315 DBUG_TRACE;
6316
6317 const char *errmsg;
6318 my_thread_attr_t thr_attr;
6319 SECURITY_ATTRIBUTES *shutdown_sec_attr;
6320
6321 my_security_attr_create(&shutdown_sec_attr, &errmsg, GENERIC_ALL,
6322 SYNCHRONIZE | EVENT_MODIFY_STATE);
6323
6324 if (!opt_no_monitor) {
6325 snprintf(shutdown_event_name, sizeof(shutdown_event_name),
6326 "mysqld%s_shutdown", get_monitor_pid());
6327 }
6328
6329 hEventShutdown =
6330 CreateEvent(shutdown_sec_attr, FALSE, FALSE, shutdown_event_name);
6331 hEventRestart = CreateEvent(0, FALSE, FALSE, restart_event_name);
6332
6333 my_thread_attr_init(&thr_attr);
6334
6335 if (my_thread_create(&shutdown_restart_thr_handle, &thr_attr,
6336 handle_shutdown_and_restart, 0))
6337 LogErr(WARNING_LEVEL, ER_CANT_CREATE_SHUTDOWN_THREAD, errno);
6338
6339 my_security_attr_free(shutdown_sec_attr);
6340 my_thread_attr_destroy(&thr_attr);
6341 }
6342 #endif /* _WIN32 */
6343
6344 #ifndef DBUG_OFF
6345 /*
6346 Debugging helper function to keep the locale database
6347 (see sql_locale.cc) and max_month_name_length and
6348 max_day_name_length variable values in consistent state.
6349 */
test_lc_time_sz()6350 static void test_lc_time_sz() {
6351 DBUG_TRACE;
6352 for (MY_LOCALE **loc = my_locales; *loc; loc++) {
6353 size_t max_month_len = 0;
6354 size_t max_day_len = 0;
6355 for (const char **month = (*loc)->month_names->type_names; *month;
6356 month++) {
6357 max_month_len = std::max(
6358 max_month_len, my_numchars_mb(&my_charset_utf8_general_ci, *month,
6359 *month + strlen(*month)));
6360 }
6361 for (const char **day = (*loc)->day_names->type_names; *day; day++) {
6362 max_day_len =
6363 std::max(max_day_len, my_numchars_mb(&my_charset_utf8_general_ci,
6364 *day, *day + strlen(*day)));
6365 }
6366 if ((*loc)->max_month_name_length != max_month_len ||
6367 (*loc)->max_day_name_length != max_day_len) {
6368 DBUG_PRINT("Wrong max day name(or month name) length for locale:",
6369 ("%s", (*loc)->name));
6370 DBUG_ASSERT(0);
6371 }
6372 }
6373 }
6374 #endif // DBUG_OFF
6375
6376 /*
6377 @brief : Set opt_super_readonly to user supplied value before
6378 enabling communication channels to accept user connections
6379 */
6380
set_super_read_only_post_init()6381 static void set_super_read_only_post_init() {
6382 opt_super_readonly = super_read_only;
6383 }
6384
calculate_mysql_home_from_my_progname()6385 static void calculate_mysql_home_from_my_progname() {
6386 const std::string runtime_output_directory_addon{
6387 "/runtime_output_directory/"};
6388 #if defined(_WIN32) || defined(APPLE_XCODE)
6389 /* Allow Win32 users to move MySQL anywhere */
6390 char prg_dev[LIBLEN];
6391 my_path(prg_dev, my_progname, nullptr);
6392
6393 // On windows or Xcode the basedir will always be one level up from where
6394 // the executable is located. E.g. <basedir>/bin/mysqld.exe in a
6395 // package, or <basedir>/runtime_output_directory/<buildconfig>/mysqld.exe
6396 // for a sandbox build.
6397 strcat(prg_dev, "/../"); // Remove containing directory to get base dir
6398 cleanup_dirname(mysql_home, prg_dev);
6399
6400 // New layout: <cmake_binary_dir>/runtime_output_directory/<buildconfig>/
6401 char cmake_binary_dir[FN_REFLEN];
6402 size_t dlen = 0;
6403 dirname_part(cmake_binary_dir, mysql_home, &dlen);
6404 if (dlen > runtime_output_directory_addon.length() &&
6405 (!strcmp(
6406 cmake_binary_dir + (dlen - runtime_output_directory_addon.length()),
6407 runtime_output_directory_addon.c_str()) ||
6408 !strcmp(
6409 cmake_binary_dir + (dlen - runtime_output_directory_addon.length()),
6410 "\\runtime_output_directory\\"))) {
6411 mysql_home[strlen(mysql_home) - 1] = '\0'; // remove trailing
6412 dirname_part(cmake_binary_dir, mysql_home, &dlen);
6413 strmake(mysql_home, cmake_binary_dir, sizeof(mysql_home) - 1);
6414 }
6415 // The sql_print_information below outputs nothing ??
6416 // fprintf(stderr, "mysql_home %s\n", mysql_home);
6417 // fflush(stderr);
6418 #else
6419 const char *tmpenv = getenv("MY_BASEDIR_VERSION");
6420 if (tmpenv != nullptr) {
6421 strmake(mysql_home, tmpenv, sizeof(mysql_home) - 1);
6422 } else {
6423 char progdir[FN_REFLEN];
6424 size_t dlen = 0;
6425 dirname_part(progdir, my_progname, &dlen);
6426 if (dlen > runtime_output_directory_addon.length() &&
6427 !strcmp(progdir + (dlen - runtime_output_directory_addon.length()),
6428 runtime_output_directory_addon.c_str())) {
6429 char cmake_binary_dir[FN_REFLEN];
6430 progdir[strlen(progdir) - 1] = '\0'; // remove trailing "/"
6431 dirname_part(cmake_binary_dir, progdir, &dlen);
6432 strmake(mysql_home, cmake_binary_dir, sizeof(mysql_home) - 1);
6433 } else {
6434 strcat(progdir, "/../");
6435 cleanup_dirname(mysql_home, progdir);
6436 }
6437 }
6438 #endif
6439 mysql_home_ptr = mysql_home;
6440 }
6441
6442 #ifdef _WIN32
win_main(int argc,char ** argv)6443 int win_main(int argc, char **argv)
6444 #else
6445 int mysqld_main(int argc, char **argv)
6446 #endif
6447 {
6448 // Substitute the full path to the executable in argv[0]
6449 substitute_progpath(argv);
6450 sysd::notify_connect();
6451 sysd::notify("STATUS=Server startup in progress\n");
6452
6453 /*
6454 Perform basic thread library and malloc initialization,
6455 to be able to read defaults files and parse options.
6456 */
6457 my_progname = argv[0];
6458 calculate_mysql_home_from_my_progname();
6459
6460 #ifndef _WIN32
6461 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
6462 pre_initialize_performance_schema();
6463 #endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */
6464 // For windows, my_init() is called from the win specific mysqld_main
6465 if (my_init()) // init my_sys library & pthreads
6466 {
6467 LogErr(ERROR_LEVEL, ER_MYINIT_FAILED);
6468 flush_error_log_messages();
6469 return 1;
6470 }
6471 #endif /* _WIN32 */
6472
6473 orig_argc = argc;
6474 orig_argv = argv;
6475 my_getopt_use_args_separator = true;
6476 my_defaults_read_login_file = false;
6477 if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv,
6478 &argv_alloc)) {
6479 flush_error_log_messages();
6480 return 1;
6481 }
6482
6483 /* Set data dir directory paths */
6484 strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR),
6485 sizeof(mysql_real_data_home) - 1);
6486
6487 /*
6488 Initialize variables cache for persisted variables, load persisted
6489 config file and append read only persisted variables to command line
6490 options if present.
6491 */
6492 if (persisted_variables_cache.init(&argc, &argv) ||
6493 persisted_variables_cache.load_persist_file() ||
6494 persisted_variables_cache.append_read_only_variables(&argc, &argv)) {
6495 flush_error_log_messages();
6496 return 1;
6497 }
6498 my_getopt_use_args_separator = false;
6499 remaining_argc = argc;
6500 remaining_argv = argv;
6501
6502 init_variable_default_paths();
6503
6504 /* Must be initialized early for comparison of options name */
6505 system_charset_info = &my_charset_utf8_general_ci;
6506
6507 /* Write mysys error messages to the error log. */
6508 local_message_hook = error_log_print;
6509
6510 int heo_error;
6511
6512 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
6513 /*
6514 Initialize the array of performance schema instrument configurations.
6515 */
6516 init_pfs_instrument_array();
6517 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
6518
6519 heo_error = handle_early_options();
6520
6521 init_sql_statement_names();
6522 sys_var_init();
6523 ulong requested_open_files = 0;
6524
6525 // Init error log subsystem. This does not actually open the log yet.
6526 if (init_error_log()) unireg_abort(MYSQLD_ABORT_EXIT);
6527 if (!opt_validate_config) adjust_related_options(&requested_open_files);
6528
6529 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
6530 if (heo_error == 0) {
6531 if (!is_help_or_validate_option() && !opt_initialize) {
6532 int pfs_rc;
6533 /* Add sizing hints from the server sizing parameters. */
6534 pfs_param.m_hints.m_table_definition_cache = table_def_size;
6535 pfs_param.m_hints.m_table_open_cache = table_cache_size;
6536 pfs_param.m_hints.m_max_connections = max_connections;
6537 pfs_param.m_hints.m_open_files_limit = requested_open_files;
6538 pfs_param.m_hints.m_max_prepared_stmt_count = max_prepared_stmt_count;
6539
6540 pfs_rc = initialize_performance_schema(
6541 &pfs_param, &psi_thread_hook, &psi_mutex_hook, &psi_rwlock_hook,
6542 &psi_cond_hook, &psi_file_hook, &psi_socket_hook, &psi_table_hook,
6543 &psi_mdl_hook, &psi_idle_hook, &psi_stage_hook, &psi_statement_hook,
6544 &psi_transaction_hook, &psi_memory_hook, &psi_error_hook,
6545 &psi_data_lock_hook, &psi_system_hook, &psi_tls_channel_hook);
6546 if ((pfs_rc != 0) && pfs_param.m_enabled) {
6547 pfs_param.m_enabled = false;
6548 LogErr(WARNING_LEVEL, ER_PERFSCHEMA_INIT_FAILED);
6549 }
6550 }
6551 }
6552 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
6553
6554 #ifdef WITH_LOCK_ORDER
6555 if (heo_error == 0) {
6556 if (lo_param.m_enabled && !opt_help && !opt_initialize) {
6557 int lo_rc;
6558 lo_rc = LO_init(&lo_param, &psi_thread_hook, &psi_mutex_hook,
6559 &psi_rwlock_hook, &psi_cond_hook, &psi_file_hook,
6560 &psi_socket_hook, &psi_table_hook, &psi_mdl_hook,
6561 &psi_idle_hook, &psi_stage_hook, &psi_statement_hook,
6562 &psi_transaction_hook, &psi_memory_hook);
6563 if (lo_rc != 0) {
6564 LogErr(WARNING_LEVEL, ER_LOCK_ORDER_INIT_FAILED);
6565 }
6566 }
6567 }
6568 #endif /* WITH_LOCK_ORDER */
6569
6570 /*
6571 Other provider of the instrumentation interface should
6572 initialize PSI_hook here:
6573 - HAVE_PSI_INTERFACE is for the instrumentation interface
6574 - WITH_PERFSCHEMA_STORAGE_ENGINE is for one implementation
6575 of the interface,
6576 but there could be alternate implementations, which is why
6577 these two defines are kept separate.
6578 */
6579
6580 #ifdef HAVE_PSI_INTERFACE
6581 /*
6582 Obtain the current performance schema instrumentation interface,
6583 if available.
6584 */
6585
6586 void *service;
6587
6588 if (psi_thread_hook != nullptr) {
6589 service = psi_thread_hook->get_interface(PSI_CURRENT_THREAD_VERSION);
6590 if (service != nullptr) {
6591 set_psi_thread_service(service);
6592 }
6593 }
6594
6595 if (psi_mutex_hook != nullptr) {
6596 service = psi_mutex_hook->get_interface(PSI_CURRENT_MUTEX_VERSION);
6597 if (service != nullptr) {
6598 set_psi_mutex_service(service);
6599 }
6600 }
6601
6602 if (psi_rwlock_hook != nullptr) {
6603 service = psi_rwlock_hook->get_interface(PSI_CURRENT_RWLOCK_VERSION);
6604 if (service != nullptr) {
6605 set_psi_rwlock_service(service);
6606 }
6607 }
6608
6609 if (psi_cond_hook != nullptr) {
6610 service = psi_cond_hook->get_interface(PSI_CURRENT_COND_VERSION);
6611 if (service != nullptr) {
6612 set_psi_cond_service(service);
6613 }
6614 }
6615
6616 if (psi_file_hook != nullptr) {
6617 service = psi_file_hook->get_interface(PSI_CURRENT_FILE_VERSION);
6618 if (service != nullptr) {
6619 set_psi_file_service(service);
6620 }
6621 }
6622
6623 if (psi_socket_hook != nullptr) {
6624 service = psi_socket_hook->get_interface(PSI_CURRENT_SOCKET_VERSION);
6625 if (service != nullptr) {
6626 set_psi_socket_service(service);
6627 }
6628 }
6629
6630 if (psi_table_hook != nullptr) {
6631 service = psi_table_hook->get_interface(PSI_CURRENT_TABLE_VERSION);
6632 if (service != nullptr) {
6633 set_psi_table_service(service);
6634 }
6635 }
6636
6637 if (psi_mdl_hook != nullptr) {
6638 service = psi_mdl_hook->get_interface(PSI_CURRENT_MDL_VERSION);
6639 if (service != nullptr) {
6640 set_psi_mdl_service(service);
6641 }
6642 }
6643
6644 if (psi_idle_hook != nullptr) {
6645 service = psi_idle_hook->get_interface(PSI_CURRENT_IDLE_VERSION);
6646 if (service != nullptr) {
6647 set_psi_idle_service(service);
6648 }
6649 }
6650
6651 if (psi_stage_hook != nullptr) {
6652 service = psi_stage_hook->get_interface(PSI_CURRENT_STAGE_VERSION);
6653 if (service != nullptr) {
6654 set_psi_stage_service(service);
6655 }
6656 }
6657
6658 if (psi_statement_hook != nullptr) {
6659 service = psi_statement_hook->get_interface(PSI_CURRENT_STATEMENT_VERSION);
6660 if (service != nullptr) {
6661 set_psi_statement_service(service);
6662 }
6663 }
6664
6665 if (psi_transaction_hook != nullptr) {
6666 service =
6667 psi_transaction_hook->get_interface(PSI_CURRENT_TRANSACTION_VERSION);
6668 if (service != nullptr) {
6669 set_psi_transaction_service(service);
6670 }
6671 }
6672
6673 if (psi_memory_hook != nullptr) {
6674 service = psi_memory_hook->get_interface(PSI_CURRENT_MEMORY_VERSION);
6675 if (service != nullptr) {
6676 set_psi_memory_service(service);
6677 }
6678 }
6679
6680 if (psi_error_hook != nullptr) {
6681 service = psi_error_hook->get_interface(PSI_CURRENT_ERROR_VERSION);
6682 if (service != nullptr) {
6683 set_psi_error_service(service);
6684 }
6685 }
6686
6687 if (psi_data_lock_hook != nullptr) {
6688 service = psi_data_lock_hook->get_interface(PSI_CURRENT_DATA_LOCK_VERSION);
6689 if (service != nullptr) {
6690 set_psi_data_lock_service(service);
6691 }
6692 }
6693
6694 if (psi_system_hook != nullptr) {
6695 service = psi_system_hook->get_interface(PSI_CURRENT_SYSTEM_VERSION);
6696 if (service != nullptr) {
6697 set_psi_system_service(service);
6698 }
6699 }
6700
6701 if (psi_tls_channel_hook != nullptr) {
6702 service =
6703 psi_tls_channel_hook->get_interface(PSI_CURRENT_TLS_CHANNEL_VERSION);
6704 if (service != nullptr) {
6705 set_psi_tls_channel_service(service);
6706 }
6707 }
6708
6709 /*
6710 Now that we have parsed the command line arguments, and have initialized
6711 the performance schema itself, the next step is to register all the
6712 server instruments.
6713 */
6714 init_server_psi_keys();
6715
6716 /*
6717 Now that some instrumentation is in place,
6718 recreate objects which were initialised early,
6719 so that they are instrumented as well.
6720 */
6721 my_thread_global_reinit();
6722 #endif /* HAVE_PSI_INTERFACE */
6723
6724 /*
6725 Initialize Components core subsystem early on, once we have PSI, which it
6726 uses. This part doesn't use any more MySQL-specific functionalities but
6727 error logging and PFS.
6728 */
6729 if (component_infrastructure_init()) unireg_abort(MYSQLD_ABORT_EXIT);
6730
6731 /*
6732 Initialize Performance Schema component services.
6733 */
6734 #ifdef HAVE_PSI_THREAD_INTERFACE
6735 if (!is_help_or_validate_option() && !opt_initialize) {
6736 register_pfs_notification_service();
6737 register_pfs_resource_group_service();
6738 }
6739 #endif
6740
6741 // Initialize the resource group subsystem.
6742 auto res_grp_mgr = resourcegroups::Resource_group_mgr::instance();
6743 if (!is_help_or_validate_option() && !opt_initialize) {
6744 if (res_grp_mgr->init()) {
6745 LogErr(ERROR_LEVEL, ER_RESOURCE_GROUP_SUBSYSTEM_INIT_FAILED);
6746 unireg_abort(MYSQLD_ABORT_EXIT);
6747 }
6748 }
6749
6750 #ifdef HAVE_PSI_THREAD_INTERFACE
6751 /* Instrument the main thread */
6752 PSI_thread *psi = PSI_THREAD_CALL(new_thread)(key_thread_main, nullptr, 0);
6753 PSI_THREAD_CALL(set_thread_os_id)(psi);
6754 PSI_THREAD_CALL(set_thread)(psi);
6755 #endif /* HAVE_PSI_THREAD_INTERFACE */
6756
6757 /* Initialize audit interface globals. Audit plugins are inited later. */
6758 mysql_audit_initialize();
6759
6760 Srv_session::module_init();
6761
6762 /*
6763 Perform basic query log initialization. Should be called after
6764 MY_INIT, as it initializes mutexes.
6765 */
6766 query_logger.init();
6767
6768 if (heo_error) {
6769 /*
6770 Parsing command line option failed,
6771 Since we don't have a workable remaining_argc/remaining_argv
6772 to continue the server initialization, this is as far as this
6773 code can go.
6774 This is the best effort to log meaningful messages:
6775 - messages will be printed to stderr, which is not redirected yet,
6776 - messages will be printed in the NT event log, for windows.
6777 */
6778 flush_error_log_messages();
6779 /*
6780 Not enough initializations for unireg_abort()
6781 Using exit() for windows.
6782 */
6783 exit(MYSQLD_ABORT_EXIT);
6784 }
6785
6786 if (init_common_variables()) {
6787 setup_error_log();
6788 unireg_abort(MYSQLD_ABORT_EXIT); // Will do exit
6789 }
6790
6791 my_init_signals();
6792
6793 size_t guardize = 0;
6794 #ifndef _WIN32
6795 int retval = pthread_attr_getguardsize(&connection_attrib, &guardize);
6796 DBUG_ASSERT(retval == 0);
6797 if (retval != 0) guardize = my_thread_stack_size;
6798 #endif
6799
6800 #if defined(__ia64__) || defined(__ia64)
6801 /*
6802 Peculiar things with ia64 platforms - it seems we only have half the
6803 stack size in reality, so we have to double it here
6804 */
6805 guardize = my_thread_stack_size;
6806 #endif
6807
6808 if (0 != my_thread_attr_setstacksize(&connection_attrib,
6809 my_thread_stack_size + guardize)) {
6810 DBUG_ASSERT(false);
6811 }
6812
6813 {
6814 /* Retrieve used stack size; Needed for checking stack overflows */
6815 size_t stack_size = 0;
6816 my_thread_attr_getstacksize(&connection_attrib, &stack_size);
6817
6818 /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
6819 if (stack_size && stack_size < (my_thread_stack_size + guardize)) {
6820 LogErr(WARNING_LEVEL, ER_STACKSIZE_UNEXPECTED,
6821 my_thread_stack_size + guardize, (long)stack_size);
6822 #if defined(__ia64__) || defined(__ia64)
6823 my_thread_stack_size = stack_size / 2;
6824 #else
6825 my_thread_stack_size = static_cast<ulong>(stack_size - guardize);
6826 #endif
6827 }
6828 }
6829
6830 #ifndef DBUG_OFF
6831 test_lc_time_sz();
6832 srand(static_cast<uint>(time(nullptr)));
6833 #endif
6834
6835 #if !defined(_WIN32)
6836
6837 if (opt_initialize && opt_daemonize) {
6838 fprintf(stderr, "Initialize and daemon options are incompatible.\n");
6839 unireg_abort(MYSQLD_ABORT_EXIT);
6840 }
6841
6842 if (opt_daemonize && log_error_dest == disabled_my_option &&
6843 (isatty(STDOUT_FILENO) || isatty(STDERR_FILENO))) {
6844 // Just use the default in this case.
6845 log_error_dest = "";
6846 }
6847
6848 if (opt_daemonize && !opt_validate_config) {
6849 if (chdir("/") < 0) {
6850 LogErr(ERROR_LEVEL, ER_CANNOT_CHANGE_TO_ROOT_DIR, strerror(errno));
6851 unireg_abort(MYSQLD_ABORT_EXIT);
6852 }
6853
6854 if ((pipe_write_fd = mysqld::runtime::mysqld_daemonize()) < -1) {
6855 LogErr(ERROR_LEVEL, ER_FAILED_START_MYSQLD_DAEMON);
6856 unireg_abort(MYSQLD_ABORT_EXIT);
6857 }
6858
6859 if (pipe_write_fd < 0) {
6860 // This is the launching process and the daemon appears to have
6861 // started ok (Need to call unireg_abort with success here to
6862 // clean up resources in the lauching process.
6863 unireg_abort(MYSQLD_SUCCESS_EXIT);
6864 }
6865
6866 // Need to update the value of current_pid so that it reflects the
6867 // pid of the daemon (the previous value was set by unireg_init()
6868 // while still in the launcher process.
6869 current_pid = static_cast<ulong>(getpid());
6870 }
6871 #endif
6872
6873 #ifndef _WIN32
6874 user_info = check_user(mysqld_user);
6875 if (!user_info.IsVoid()) {
6876 #if HAVE_CHOWN
6877 if (unlikely(opt_initialize)) {
6878 /* need to change the owner of the freshly created data directory */
6879 MY_STAT stat;
6880 char errbuf[MYSYS_STRERROR_SIZE];
6881 bool must_chown = true;
6882
6883 /* fetch the directory's owner */
6884 if (!my_stat(mysql_real_data_home, &stat, MYF(0))) {
6885 LogErr(INFORMATION_LEVEL, ER_CANT_STAT_DATADIR, my_errno(),
6886 my_strerror(errbuf, sizeof(errbuf), my_errno()));
6887 }
6888 /* Don't change it if it's already the same as SElinux stops this */
6889 else if (stat.st_uid == user_info.pw_uid &&
6890 stat.st_gid == user_info.pw_gid)
6891 must_chown = false;
6892
6893 if (must_chown &&
6894 chown(mysql_real_data_home, user_info.pw_uid, user_info.pw_gid)) {
6895 LogErr(ERROR_LEVEL, ER_CANT_CHOWN_DATADIR, mysqld_user);
6896 unireg_abort(1);
6897 }
6898 }
6899 #endif
6900
6901 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
6902 if (locked_in_memory) // getuid() == 0 here
6903 set_effective_user(user_info);
6904 else
6905 #endif
6906 set_user(mysqld_user, user_info);
6907 }
6908 #endif // !_WIN32
6909
6910 /*
6911 initiate key migration if any one of the migration specific
6912 options are provided.
6913 */
6914 if (opt_keyring_migration_source || opt_keyring_migration_destination ||
6915 migrate_connect_options) {
6916 Migrate_keyring mk;
6917 my_getopt_skip_unknown = true;
6918 if (mk.init(remaining_argc, remaining_argv, opt_keyring_migration_source,
6919 opt_keyring_migration_destination, opt_keyring_migration_user,
6920 opt_keyring_migration_host, opt_keyring_migration_password,
6921 opt_keyring_migration_socket, opt_keyring_migration_port)) {
6922 LogErr(ERROR_LEVEL, ER_KEYRING_MIGRATION_FAILED);
6923 log_error_dest = "stderr";
6924 flush_error_log_messages();
6925 unireg_abort(MYSQLD_ABORT_EXIT);
6926 }
6927
6928 if (mk.execute()) {
6929 LogErr(ERROR_LEVEL, ER_KEYRING_MIGRATION_FAILED);
6930 log_error_dest = "stderr";
6931 flush_error_log_messages();
6932 unireg_abort(MYSQLD_ABORT_EXIT);
6933 }
6934
6935 my_getopt_skip_unknown = false;
6936 LogErr(INFORMATION_LEVEL, ER_KEYRING_MIGRATION_SUCCESSFUL);
6937 log_error_dest = "stderr";
6938 flush_error_log_messages();
6939 unireg_abort(MYSQLD_SUCCESS_EXIT);
6940 }
6941
6942 /*
6943 We have enough space for fiddling with the argv, continue
6944 */
6945 if (!(is_help_or_validate_option()) &&
6946 my_setwd(mysql_real_data_home, MYF(0))) {
6947 char errbuf[MYSYS_STRERROR_SIZE];
6948
6949 LogErr(ERROR_LEVEL, ER_CANT_SET_DATA_DIR, mysql_real_data_home, errno,
6950 my_strerror(errbuf, sizeof(errbuf), errno));
6951 unireg_abort(MYSQLD_ABORT_EXIT); /* purecov: inspected */
6952 }
6953
6954 /*
6955 The subsequent calls may take a long time : e.g. innodb log read.
6956 Thus set the long running service control manager timeout
6957 */
6958 #if defined(_WIN32)
6959 if (windows_service) {
6960 if (setup_service_status_cmd_processed_handle())
6961 unireg_abort(MYSQLD_ABORT_EXIT);
6962
6963 char buf[32];
6964 snprintf(buf, sizeof(buf), "T %lu", slow_start_timeout);
6965 Service_status_msg msg(buf);
6966 send_service_status(msg);
6967 }
6968 #endif
6969
6970 /* Determine default TCP port and unix socket name */
6971 set_ports();
6972
6973 if (init_server_components()) unireg_abort(MYSQLD_ABORT_EXIT);
6974
6975 if (!server_id_supplied)
6976 LogErr(INFORMATION_LEVEL, ER_WARN_NO_SERVERID_SPECIFIED);
6977
6978 /*
6979 Add server_uuid to the sid_map. This must be done after
6980 server_uuid has been initialized in init_server_auto_options and
6981 after the binary log (and sid_map file) has been initialized in
6982 init_server_components().
6983
6984 No error message is needed: init_sid_map() prints a message.
6985
6986 Strictly speaking, this is not currently needed when
6987 opt_bin_log==0, since the variables that gtid_state->init
6988 initializes are not currently used in that case. But we call it
6989 regardless to avoid possible future bugs if gtid_state ever
6990 needs to do anything else.
6991 */
6992 global_sid_lock->wrlock();
6993 int gtid_ret = gtid_state->init();
6994 global_sid_lock->unlock();
6995
6996 if (gtid_ret) unireg_abort(MYSQLD_ABORT_EXIT);
6997
6998 if (!opt_initialize && !opt_initialize_insecure) {
6999 // Initialize executed_gtids from mysql.gtid_executed table.
7000 if (gtid_state->read_gtid_executed_from_table() == -1) unireg_abort(1);
7001 }
7002
7003 if (opt_bin_log) {
7004 /*
7005 Initialize GLOBAL.GTID_EXECUTED and GLOBAL.GTID_PURGED from
7006 gtid_executed table and binlog files during server startup.
7007 */
7008 Gtid_set *executed_gtids =
7009 const_cast<Gtid_set *>(gtid_state->get_executed_gtids());
7010 Gtid_set *lost_gtids = const_cast<Gtid_set *>(gtid_state->get_lost_gtids());
7011 Gtid_set *gtids_only_in_table =
7012 const_cast<Gtid_set *>(gtid_state->get_gtids_only_in_table());
7013 Gtid_set *previous_gtids_logged =
7014 const_cast<Gtid_set *>(gtid_state->get_previous_gtids_logged());
7015
7016 Gtid_set purged_gtids_from_binlog(global_sid_map, global_sid_lock);
7017 Gtid_set gtids_in_binlog(global_sid_map, global_sid_lock);
7018 Gtid_set gtids_in_binlog_not_in_table(global_sid_map, global_sid_lock);
7019
7020 if (mysql_bin_log.init_gtid_sets(
7021 >ids_in_binlog, &purged_gtids_from_binlog,
7022 opt_master_verify_checksum, true /*true=need lock*/,
7023 nullptr /*trx_parser*/, nullptr /*partial_trx*/,
7024 true /*is_server_starting*/))
7025 unireg_abort(MYSQLD_ABORT_EXIT);
7026
7027 global_sid_lock->wrlock();
7028
7029 purged_gtids_from_binlog.dbug_print("purged_gtids_from_binlog");
7030 gtids_in_binlog.dbug_print("gtids_in_binlog");
7031
7032 if (!gtids_in_binlog.is_empty() &&
7033 !gtids_in_binlog.is_subset(executed_gtids)) {
7034 gtids_in_binlog_not_in_table.add_gtid_set(>ids_in_binlog);
7035 if (!executed_gtids->is_empty())
7036 gtids_in_binlog_not_in_table.remove_gtid_set(executed_gtids);
7037 /*
7038 Save unsaved GTIDs into gtid_executed table, in the following
7039 four cases:
7040 1. the upgrade case.
7041 2. the case that a slave is provisioned from a backup of
7042 the master and the slave is cleaned by RESET MASTER
7043 and RESET SLAVE before this.
7044 3. the case that no binlog rotation happened from the
7045 last RESET MASTER on the server before it crashes.
7046 4. The set of GTIDs of the last binlog is not saved into the
7047 gtid_executed table if server crashes, so we save it into
7048 gtid_executed table and executed_gtids during recovery
7049 from the crash.
7050 */
7051 if (gtid_state->save(>ids_in_binlog_not_in_table) == -1) {
7052 global_sid_lock->unlock();
7053 unireg_abort(MYSQLD_ABORT_EXIT);
7054 }
7055 executed_gtids->add_gtid_set(>ids_in_binlog_not_in_table);
7056 }
7057
7058 /* gtids_only_in_table= executed_gtids - gtids_in_binlog */
7059 if (gtids_only_in_table->add_gtid_set(executed_gtids) != RETURN_STATUS_OK) {
7060 global_sid_lock->unlock();
7061 unireg_abort(MYSQLD_ABORT_EXIT);
7062 }
7063 gtids_only_in_table->remove_gtid_set(>ids_in_binlog);
7064 /*
7065 lost_gtids = executed_gtids -
7066 (gtids_in_binlog - purged_gtids_from_binlog)
7067 = gtids_only_in_table + purged_gtids_from_binlog;
7068 */
7069 DBUG_ASSERT(lost_gtids->is_empty());
7070 if (lost_gtids->add_gtid_set(gtids_only_in_table) != RETURN_STATUS_OK ||
7071 lost_gtids->add_gtid_set(&purged_gtids_from_binlog) !=
7072 RETURN_STATUS_OK) {
7073 global_sid_lock->unlock();
7074 unireg_abort(MYSQLD_ABORT_EXIT);
7075 }
7076
7077 /* Prepare previous_gtids_logged for next binlog */
7078 if (previous_gtids_logged->add_gtid_set(>ids_in_binlog) !=
7079 RETURN_STATUS_OK) {
7080 global_sid_lock->unlock();
7081 unireg_abort(MYSQLD_ABORT_EXIT);
7082 }
7083
7084 /*
7085 Write the previous set of gtids at this point because during
7086 the creation of the binary log this is not done as we cannot
7087 move the init_gtid_sets() to a place before openning the binary
7088 log. This requires some investigation.
7089
7090 /Alfranio
7091 */
7092 Previous_gtids_log_event prev_gtids_ev(>ids_in_binlog);
7093
7094 global_sid_lock->unlock();
7095
7096 (prev_gtids_ev.common_footer)->checksum_alg =
7097 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options);
7098
7099 if (mysql_bin_log.write_event_to_binlog_and_sync(&prev_gtids_ev))
7100 unireg_abort(MYSQLD_ABORT_EXIT);
7101
7102 (void)RUN_HOOK(server_state, after_engine_recovery, (nullptr));
7103 }
7104
7105 if (init_ssl_communication()) unireg_abort(MYSQLD_ABORT_EXIT);
7106 if (network_init()) unireg_abort(MYSQLD_ABORT_EXIT);
7107
7108 #ifdef _WIN32
7109 if (opt_require_secure_transport && !opt_enable_shared_memory &&
7110 !have_ssl() && !opt_initialize) {
7111 LogErr(ERROR_LEVEL, ER_TRANSPORTS_WHAT_TRANSPORTS);
7112 unireg_abort(MYSQLD_ABORT_EXIT);
7113 }
7114 #endif
7115
7116 /*
7117 Initialize my_str_malloc(), my_str_realloc() and my_str_free()
7118 */
7119 my_str_malloc = &my_str_malloc_mysqld;
7120 my_str_free = &my_str_free_mysqld;
7121 my_str_realloc = &my_str_realloc_mysqld;
7122
7123 error_handler_hook = my_message_sql;
7124
7125 bool abort = false;
7126
7127 /* Save pid of this process in a file */
7128 if (!opt_initialize) {
7129 if (create_pid_file()) abort = true;
7130 }
7131
7132 /* Read the optimizer cost model configuration tables */
7133 if (!opt_initialize) reload_optimizer_cost_constants();
7134
7135 if (
7136 /*
7137 Read components table to restore previously installed components. This
7138 requires read access to mysql.component table.
7139 */
7140 (!opt_initialize && mysql_component_infrastructure_init()) ||
7141 mysql_rm_tmp_tables()) {
7142 abort = true;
7143 }
7144
7145 /* we do want to exit if there are any other unknown options */
7146 if (remaining_argc > 1) {
7147 int ho_error;
7148 struct my_option no_opts[] = {{nullptr, 0, nullptr, nullptr, nullptr,
7149 nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0,
7150 nullptr, 0, nullptr}};
7151 /*
7152 We need to eat any 'loose' arguments first before we conclude
7153 that there are unprocessed options.
7154 */
7155 my_getopt_skip_unknown = false;
7156
7157 if ((ho_error = handle_options(&remaining_argc, &remaining_argv, no_opts,
7158 mysqld_get_one_option)))
7159 abort = true;
7160 else {
7161 /* Add back the program name handle_options removes */
7162 remaining_argc++;
7163 remaining_argv--;
7164 my_getopt_skip_unknown = true;
7165
7166 if (remaining_argc > 1) {
7167 LogErr(ERROR_LEVEL, ER_EXCESS_ARGUMENTS, remaining_argv[1]);
7168 LogErr(INFORMATION_LEVEL, ER_VERBOSE_HINT);
7169 abort = true;
7170 }
7171 }
7172 }
7173
7174 if (abort || acl_init(opt_noacl)) {
7175 if (!abort) LogErr(ERROR_LEVEL, ER_PRIVILEGE_SYSTEM_INIT_FAILED);
7176 abort = true;
7177 opt_noacl = true;
7178 }
7179
7180 /*
7181 if running with --initialize, explicitly allocate the memory
7182 to be used by ACL objects.
7183 */
7184 if (opt_initialize) init_acl_memory();
7185
7186 /*
7187 Turn ON the system variable '@@partial_revokes' during server
7188 start in case there exist at least one restrictions instance.
7189 */
7190 if (mysqld_partial_revokes() == false && is_partial_revoke_exists(nullptr)) {
7191 set_mysqld_partial_revokes(true);
7192 LogErr(WARNING_LEVEL, ER_TURNING_ON_PARTIAL_REVOKES);
7193 }
7194
7195 if (abort || my_tz_init((THD *)nullptr, default_tz_name, opt_initialize) ||
7196 grant_init(opt_noacl)) {
7197 set_connection_events_loop_aborted(true);
7198
7199 delete_pid_file(MYF(MY_WME));
7200
7201 unireg_abort(MYSQLD_ABORT_EXIT);
7202 }
7203
7204 /*
7205 Bootstrap the dynamic privilege service implementation
7206 */
7207 if (dynamic_privilege_init()) {
7208 LogErr(WARNING_LEVEL, ER_PERSISTENT_PRIVILEGES_BOOTSTRAP);
7209 }
7210
7211 if (!opt_initialize) servers_init(false);
7212
7213 if (!opt_noacl) {
7214 udf_read_functions_table();
7215 }
7216
7217 init_status_vars();
7218 /* If running with --initialize, do not start replication. */
7219 if (opt_initialize) opt_skip_slave_start = true;
7220
7221 check_binlog_cache_size(nullptr);
7222 check_binlog_stmt_cache_size(nullptr);
7223
7224 binlog_unsafe_map_init();
7225
7226 /* If running with --initialize, do not start replication. */
7227 if (!opt_initialize) {
7228 // Make @@slave_skip_errors show the nice human-readable value.
7229 set_slave_skip_errors(&opt_slave_skip_errors);
7230 /*
7231 Group replication filters should be discarded before init_slave(),
7232 otherwise the pre-configured filters will be referenced by group
7233 replication channels.
7234 */
7235 rpl_channel_filters.discard_group_replication_filters();
7236
7237 /*
7238 init_slave() must be called after the thread keys are created.
7239 */
7240 if (server_id != 0)
7241 init_slave(); /* Ignoring errors while configuring replication. */
7242
7243 /*
7244 If the user specifies a per-channel replication filter through a
7245 command-line option (or in a configuration file) for a slave
7246 replication channel which does not exist as of now (i.e not
7247 present in slave info tables yet), then the per-channel
7248 replication filter is discarded with a warning.
7249 If the user specifies a per-channel replication filter through
7250 a command-line option (or in a configuration file) for group
7251 replication channels 'group_replication_recovery' and
7252 'group_replication_applier' which is disallowed, then the
7253 per-channel replication filter is discarded with a warning.
7254 */
7255 rpl_channel_filters.discard_all_unattached_filters();
7256 }
7257
7258 #ifdef WITH_LOCK_ORDER
7259 if (!opt_initialize) {
7260 LO_activate();
7261 }
7262 #endif /* WITH_LOCK_ORDER */
7263
7264 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
7265 initialize_performance_schema_acl(opt_initialize);
7266 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
7267
7268 initialize_information_schema_acl();
7269
7270 (void)RUN_HOOK(server_state, after_recovery, (nullptr));
7271
7272 if (Events::init(opt_noacl || opt_initialize))
7273 unireg_abort(MYSQLD_ABORT_EXIT);
7274
7275 #ifndef _WIN32
7276 // Start signal handler thread.
7277 start_signal_handler();
7278 #endif
7279
7280 /* set all persistent options */
7281 if (persisted_variables_cache.set_persist_options()) {
7282 LogErr(ERROR_LEVEL, ER_CANT_SET_UP_PERSISTED_VALUES);
7283 flush_error_log_messages();
7284 return 1;
7285 }
7286
7287 /*
7288 Activate loadable error logging components, if any.
7289 First, check configuration value -- is it well-formed, and do
7290 the requested services exist?
7291 */
7292 if (log_builtins_error_stack(opt_log_error_services, true, nullptr) == 0) {
7293 // Syntax is OK and services exist; let's try to initialize them:
7294 size_t pos;
7295
7296 if (log_builtins_error_stack(opt_log_error_services, false, &pos) < 0) {
7297 char *problem = opt_log_error_services; /* purecov: begin inspected */
7298 const char *var_name = "log_error_services";
7299
7300 /*
7301 We failed to set the requested configuration. This can happen
7302 e.g. when a given log-writer does not have sufficient permissions
7303 to open its log files. pos should mark the position in the
7304 configuration string where we ran into trouble. Make a char-pointer
7305 from it so we can inform the user what log-service we could not
7306 initialize.
7307 */
7308 if (pos < strlen(opt_log_error_services))
7309 problem = &((char *)opt_log_error_services)[pos];
7310
7311 flush_error_log_messages();
7312
7313 /*
7314 We could not set the requested pipeline.
7315 Try to fall back to default error logging stack
7316 (by looking up the system variable for this configuration
7317 item and extracting the default value from it).
7318 If that's impossible, print diagnostics, then exit.
7319 */
7320 sys_var *var = intern_find_sys_var(var_name, strlen(var_name));
7321
7322 if (var != nullptr) {
7323 // We found the system variable, now extract the default value:
7324 opt_log_error_services = (char *)var->get_default();
7325 if (log_builtins_error_stack(opt_log_error_services, false, nullptr) >=
7326 0) {
7327 /*
7328 We managed to set the default pipeline. Now log what was wrong
7329 about the user-supplied value, then shut down.
7330 */
7331 LogErr(ERROR_LEVEL, ER_CANT_START_ERROR_LOG_SERVICE, var_name,
7332 problem);
7333 unireg_abort(MYSQLD_ABORT_EXIT);
7334 }
7335 /*
7336 If we arrive here, the user-supplied value was valid, but could
7337 not be set. The default value was found, but also could not be
7338 set. Something is very wrong. Fall-through to below where we
7339 low-level write diagnostics, then abort.
7340 */
7341 }
7342
7343 /*
7344 We failed to set the default error logging stack (or failed to look
7345 up the default setting). At this point, we don't know whether ANY of
7346 the requested sinks work, so our best bet is to write directly to the
7347 error stream. Then, we abort.
7348 */
7349 {
7350 char buff[512];
7351 size_t len;
7352
7353 len = snprintf(buff, sizeof(buff),
7354 ER_DEFAULT(ER_CANT_START_ERROR_LOG_SERVICE), var_name,
7355 problem);
7356 len = std::min(len, sizeof(buff) - 1);
7357
7358 // Trust nothing. Write directly. Quit.
7359 log_write_errstream(buff, len);
7360
7361 unireg_abort(MYSQLD_ABORT_EXIT);
7362 } /* purecov: end */
7363 } // value was OK, but could not be set
7364 // If we arrive here, the value was OK, and was set successfully.
7365 } else {
7366 /*
7367 We were given an illegal value at start-up, so the default was
7368 used instead. Let's now point our variable back at the default
7369 (i.e. the value actually used) so SELECT @@GLOBAL.log_error_services
7370 will render correct results.
7371 */
7372 sys_var *var = intern_find_sys_var(STRING_WITH_LEN("log_error_services"));
7373 char *default_services = nullptr;
7374
7375 if ((var != nullptr) &&
7376 ((default_services = (char *)var->get_default()) != nullptr))
7377 log_builtins_error_stack(default_services, false, nullptr);
7378
7379 // Report that we're falling back to the default value.
7380 LogErr(WARNING_LEVEL, ER_CANNOT_SET_LOG_ERROR_SERVICES,
7381 opt_log_error_services);
7382
7383 if (default_services != nullptr) opt_log_error_services = default_services;
7384 }
7385
7386 /*
7387 Now that the error-logging stack is fully set up, loadable components
7388 and all, flush buffered log-events to the log-services the user actually
7389 wants!
7390 */
7391 log_error_stage_set(LOG_ERROR_STAGE_EXTERNAL_SERVICES_AVAILABLE);
7392 flush_error_log_messages();
7393
7394 /*
7395 Invoke the bootstrap thread, if required.
7396 */
7397 process_bootstrap();
7398
7399 /*
7400 Event must be invoked after error_handler_hook is assigned to
7401 my_message_sql, otherwise my_message will not cause the event to abort.
7402 */
7403 void *argv_p = argv;
7404 if (mysql_audit_notify(AUDIT_EVENT(MYSQL_AUDIT_SERVER_STARTUP_STARTUP),
7405 static_cast<const char **>(argv_p), argc))
7406 unireg_abort(MYSQLD_ABORT_EXIT);
7407
7408 #ifdef _WIN32
7409 create_shutdown_and_restart_thread();
7410 #endif
7411 if (mysqld_process_must_end_at_startup) {
7412 #if !defined(_WIN32)
7413 if (opt_daemonize) mysqld::runtime::signal_parent(pipe_write_fd, 1);
7414 #endif
7415 unireg_abort(MYSQLD_SUCCESS_EXIT);
7416 }
7417
7418 start_handle_manager();
7419
7420 create_compress_gtid_table_thread();
7421
7422 LogEvent()
7423 .type(LOG_TYPE_ERROR)
7424 .subsys(LOG_SUBSYSTEM_TAG)
7425 .prio(SYSTEM_LEVEL)
7426 .lookup(ER_SERVER_STARTUP_MSG, my_progname, server_version,
7427 #ifdef HAVE_SYS_UN_H
7428 (opt_initialize ? "" : mysqld_unix_port),
7429 #else
7430 "",
7431 #endif
7432 mysqld_port, MYSQL_COMPILATION_COMMENT_SERVER);
7433
7434 if (!opt_disable_networking && my_admin_bind_addr_str)
7435 LogEvent()
7436 .type(LOG_TYPE_ERROR)
7437 .subsys(LOG_SUBSYSTEM_TAG)
7438 .prio(SYSTEM_LEVEL)
7439 .lookup(ER_SERVER_STARTUP_ADMIN_INTERFACE, my_admin_bind_addr_str,
7440 mysqld_admin_port, MYSQL_COMPILATION_COMMENT);
7441
7442 #if defined(_WIN32)
7443 if (windows_service) {
7444 Service_status_msg s("R");
7445 send_service_status(s);
7446 }
7447 #endif
7448
7449 server_components_initialized();
7450
7451 /*
7452 Set opt_super_readonly here because if opt_super_readonly is set
7453 in get_option, it will create problem while setting up event scheduler.
7454 */
7455 set_super_read_only_post_init();
7456
7457 DBUG_PRINT("info", ("Block, listening for incoming connections"));
7458
7459 (void)MYSQL_SET_STAGE(0, __FILE__, __LINE__);
7460
7461 server_operational_state = SERVER_OPERATING;
7462 sysd::notify("READY=1\nSTATUS=Server is operational\nMAIN_PID=", getpid(),
7463 "\n");
7464
7465 (void)RUN_HOOK(server_state, before_handle_connection, (nullptr));
7466
7467 #if defined(_WIN32)
7468 setup_conn_event_handler_threads();
7469 #else
7470 mysql_mutex_lock(&LOCK_socket_listener_active);
7471 // Make it possible for the signal handler to kill the listener.
7472 socket_listener_active = true;
7473 mysql_mutex_unlock(&LOCK_socket_listener_active);
7474
7475 if (opt_daemonize) {
7476 if (nstdout != nullptr) {
7477 // Show the pid on stdout if deamonizing and connected to tty
7478 fprintf(nstdout, "mysqld is running as pid %lu\n", current_pid);
7479 fclose(nstdout);
7480 nstdout = nullptr;
7481 }
7482
7483 mysqld::runtime::signal_parent(pipe_write_fd, 1);
7484 }
7485
7486 mysqld_socket_acceptor->connection_event_loop();
7487 #endif /* _WIN32 */
7488 server_operational_state = SERVER_SHUTTING_DOWN;
7489 sysd::notify("STOPPING=1\nSTATUS=Server shutdown in progress\n");
7490
7491 DBUG_PRINT("info", ("No longer listening for incoming connections"));
7492
7493 mysql_audit_notify(MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN,
7494 MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_SHUTDOWN,
7495 MYSQLD_SUCCESS_EXIT);
7496
7497 terminate_compress_gtid_table_thread();
7498 /*
7499 Save set of GTIDs of the last binlog into gtid_executed table
7500 on server shutdown.
7501 */
7502 if (opt_bin_log)
7503 if (gtid_state->save_gtids_of_last_binlog_into_table())
7504 LogErr(WARNING_LEVEL, ER_CANT_SAVE_GTIDS);
7505
7506 #ifndef _WIN32
7507 mysql_mutex_lock(&LOCK_socket_listener_active);
7508 // Notify the signal handler that we have stopped listening for connections.
7509 socket_listener_active = false;
7510 mysql_cond_broadcast(&COND_socket_listener_active);
7511 mysql_mutex_unlock(&LOCK_socket_listener_active);
7512 #endif // !_WIN32
7513
7514 #ifdef HAVE_PSI_THREAD_INTERFACE
7515 /*
7516 Disable the main thread instrumentation,
7517 to avoid recording events during the shutdown.
7518 */
7519 PSI_THREAD_CALL(delete_current_thread)();
7520 #endif /* HAVE_PSI_THREAD_INTERFACE */
7521
7522 DBUG_PRINT("info", ("Waiting for shutdown proceed"));
7523 int ret = 0;
7524 #ifdef _WIN32
7525 if (shutdown_restart_thr_handle.handle)
7526 ret = my_thread_join(&shutdown_restart_thr_handle, NULL);
7527 shutdown_restart_thr_handle.handle = NULL;
7528 if (0 != ret)
7529 LogErr(WARNING_LEVEL, ER_CANT_JOIN_SHUTDOWN_THREAD, "shutdown ", ret);
7530 #else
7531 if (signal_thread_id.thread != 0)
7532 ret = my_thread_join(&signal_thread_id, nullptr);
7533 signal_thread_id.thread = 0;
7534 if (0 != ret)
7535 LogErr(WARNING_LEVEL, ER_CANT_JOIN_SHUTDOWN_THREAD, "signal_", ret);
7536 #endif // _WIN32
7537
7538 clean_up(true);
7539 sysd::notify("STATUS=Server shutdown complete");
7540 mysqld_exit(signal_hand_thr_exit_code);
7541 }
7542
7543 /****************************************************************************
7544 Main and thread entry function for Win32
7545 (all this is needed only to run mysqld as a service on WinNT)
7546 ****************************************************************************/
7547
7548 #if defined(_WIN32)
7549
is_windows_service()7550 bool is_windows_service() { return windows_service; }
7551
get_win_service_ptr()7552 NTService *get_win_service_ptr() { return &Service; }
7553
mysql_service(void * p)7554 int mysql_service(void *p) {
7555 int my_argc;
7556 char **my_argv;
7557
7558 if (use_opt_args) {
7559 my_argc = opt_argc;
7560 my_argv = opt_argv;
7561 } else if (is_mysqld_monitor()) {
7562 my_argc = Service.my_argc;
7563 my_argv = Service.my_argv;
7564 } else {
7565 my_argc = my_global_argc;
7566 my_argv = my_global_argv;
7567 }
7568
7569 if (!mysqld_early_option) {
7570 int res = start_monitor();
7571 if (res != -1) {
7572 deinitialize_mysqld_monitor();
7573 return res;
7574 }
7575 }
7576
7577 if (my_thread_init()) {
7578 flush_error_log_messages();
7579 return 1;
7580 }
7581
7582 win_main(my_argc, my_argv);
7583
7584 my_thread_end();
7585 return 0;
7586 }
7587
7588 /* Quote string if it contains space, else copy */
7589
add_quoted_string(char * to,const char * from,char * to_end)7590 static char *add_quoted_string(char *to, const char *from, char *to_end) {
7591 uint length = (uint)(to_end - to);
7592
7593 if (!strchr(from, ' ')) return strmake(to, from, length - 1);
7594 return strxnmov(to, length - 1, "\"", from, "\"", NullS);
7595 }
7596
7597 /**
7598 Handle basic handling of services, like installation and removal.
7599
7600 @param argv Pointer to argument list
7601 @param servicename Internal name of service
7602 @param displayname Display name of service (in taskbar ?)
7603 @param file_path Path to this program
7604 @param startup_option Startup option to mysqld
7605
7606 @retval
7607 0 option handled
7608 @retval
7609 1 Could not handle option
7610 */
7611
default_service_handling(char ** argv,const char * servicename,const char * displayname,const char * file_path,const char * extra_opt,const char * account_name)7612 static bool default_service_handling(char **argv, const char *servicename,
7613 const char *displayname,
7614 const char *file_path,
7615 const char *extra_opt,
7616 const char *account_name) {
7617 char path_and_service[FN_REFLEN + FN_REFLEN + 32], *pos, *end;
7618 const char *opt_delim;
7619 end = path_and_service + sizeof(path_and_service) - 3;
7620
7621 /* We have to quote filename if it contains spaces */
7622 pos = add_quoted_string(path_and_service, file_path, end);
7623 if (extra_opt && *extra_opt) {
7624 /*
7625 Add option after file_path. There will be zero or one extra option. It's
7626 assumed to be --defaults-file=file but isn't checked. The variable (not
7627 the option name) should be quoted if it contains a string.
7628 */
7629 *pos++ = ' ';
7630 if (opt_delim = strchr(extra_opt, '=')) {
7631 size_t length = ++opt_delim - extra_opt;
7632 pos = my_stpnmov(pos, extra_opt, length);
7633 } else
7634 opt_delim = extra_opt;
7635
7636 pos = add_quoted_string(pos, opt_delim, end);
7637 }
7638 /* We must have servicename last */
7639 *pos++ = ' ';
7640 (void)add_quoted_string(pos, servicename, end);
7641
7642 if (Service.got_service_option(argv, "install")) {
7643 Service.Install(1, servicename, displayname, path_and_service,
7644 account_name);
7645 return 0;
7646 }
7647 if (Service.got_service_option(argv, "install-manual")) {
7648 Service.Install(0, servicename, displayname, path_and_service,
7649 account_name);
7650 return 0;
7651 }
7652 if (Service.got_service_option(argv, "remove")) {
7653 Service.Remove(servicename);
7654 return 0;
7655 }
7656 return 1;
7657 }
7658
mysqld_main(int argc,char ** argv)7659 int mysqld_main(int argc, char **argv) {
7660 bool mysqld_monitor = false;
7661 mysqld_early_option = is_early_option(argc, argv);
7662
7663 if (!mysqld_early_option) {
7664 initialize_mysqld_monitor();
7665 mysqld_monitor = is_mysqld_monitor();
7666 }
7667
7668 if (mysqld_early_option || !mysqld_monitor) {
7669 /*
7670 When several instances are running on the same machine, we
7671 need to have an unique named hEventShudown through the
7672 application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
7673 */
7674
7675 longlong10_to_str(GetCurrentProcessId(),
7676 my_stpcpy(shutdown_event_name, "MYSQLShutdown"), 10);
7677 longlong10_to_str(GetCurrentProcessId(),
7678 my_stpcpy(restart_event_name, "MYSQLRestart"), 10);
7679 }
7680
7681 /* Must be initialized early for comparison of service name */
7682 system_charset_info = &my_charset_utf8_general_ci;
7683
7684 if (mysqld_early_option || !mysqld_monitor) {
7685 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
7686 pre_initialize_performance_schema();
7687 #endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */
7688
7689 if (my_init()) {
7690 LogErr(ERROR_LEVEL, ER_MYINIT_FAILED);
7691 flush_error_log_messages();
7692 return 1;
7693 }
7694 }
7695
7696 if (Service.GetOS() && mysqld_monitor) /* true NT family */
7697 {
7698 char file_path[FN_REFLEN];
7699 my_path(file_path, argv[0], ""); /* Find name in path */
7700 fn_format(file_path, argv[0], file_path, "",
7701 MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
7702
7703 if (argc == 2) {
7704 if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
7705 file_path, "", NULL))
7706 return 0;
7707 if (Service.IsService(argv[1])) /* Start an optional service */
7708 {
7709 /*
7710 Only add the service name to the groups read from the config file
7711 if it's not "MySQL". (The default service name should be 'mysqld'
7712 but we started a bad tradition by calling it MySQL from the start
7713 and we are now stuck with it.
7714 */
7715 if (my_strcasecmp(system_charset_info, argv[1], "mysql"))
7716 load_default_groups[load_default_groups_sz - 2] = argv[1];
7717 windows_service = true;
7718
7719 Service.Init(argv[1], mysql_service);
7720 return 0;
7721 }
7722 } else if (argc == 3) /* install or remove any optional service */
7723 {
7724 if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
7725 NULL))
7726 return 0;
7727 if (Service.IsService(argv[2])) {
7728 /*
7729 mysqld was started as
7730 mysqld --defaults-file=my_path\my.ini service-name
7731 */
7732 use_opt_args = 1;
7733 opt_argc = 2; // Skip service-name
7734 opt_argv = argv;
7735 windows_service = true;
7736 if (my_strcasecmp(system_charset_info, argv[2], "mysql"))
7737 load_default_groups[load_default_groups_sz - 2] = argv[2];
7738 Service.Init(argv[2], mysql_service);
7739 return 0;
7740 }
7741 } else if (argc == 4 || argc == 5) {
7742 /*
7743 This may seem strange, because we handle --local-service while
7744 preserving 4.1's behavior of allowing any one other argument that is
7745 passed to the service on startup. (The assumption is that this is
7746 --defaults-file=file, but that was not enforced in 4.1, so we don't
7747 enforce it here.)
7748 */
7749 const char *extra_opt = NullS;
7750 const char *account_name = NullS;
7751 int index;
7752 for (index = 3; index < argc; index++) {
7753 if (!strcmp(argv[index], "--local-service"))
7754 account_name = "NT AUTHORITY\\LocalService";
7755 else
7756 extra_opt = argv[index];
7757 }
7758
7759 if (argc == 4 || account_name)
7760 if (!default_service_handling(argv, argv[2], argv[2], file_path,
7761 extra_opt, account_name))
7762 return 0;
7763 } else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME)) {
7764 /* start the default service */
7765 windows_service = true;
7766 Service.Init(MYSQL_SERVICENAME, mysql_service);
7767 return 0;
7768 }
7769 }
7770
7771 // Set windows_service value in mysqld
7772 if (!mysqld_monitor) {
7773 windows_service = is_monitor_win_service();
7774
7775 if (windows_service) {
7776 if (argc == 2 && Service.IsService(argv[1])) {
7777 if (my_strcasecmp(system_charset_info, argv[1], "mysql"))
7778 load_default_groups[load_default_groups_sz - 2] = argv[1];
7779 argc--;
7780
7781 } else if (argc == 3 && Service.IsService(argv[2])) {
7782 /*
7783 mysqld was started as
7784 mysqld --defaults-file=my_path\my.ini service-name
7785 */
7786 if (my_strcasecmp(system_charset_info, argv[2], "mysql"))
7787 load_default_groups[load_default_groups_sz - 2] = argv[2];
7788 argc--;
7789 }
7790 }
7791
7792 my_global_argc = argc;
7793 my_global_argv = argv;
7794 } else {
7795 Service.my_argc = argc;
7796 Service.my_argv = argv;
7797 }
7798
7799 return mysql_service(NULL);
7800 }
7801 #endif // _WIN32
7802
7803 /**
7804 Execute the bootstrap thread, if required.
7805
7806 When mysqld is started with --initialize only,
7807 the bootstrap thread executes
7808 - compiled in statements.
7809 - create the non-DD based INFORMATION_SCHEMA.
7810 and the server exits.
7811
7812 When mysqld is started with --init-file only,
7813 the bootstrap thread executes SQL statements provided
7814 in the input text file,
7815 and the server continues and serves requests.
7816
7817 When mysqld is started with both --initialize and --init-file,
7818 the bootstrap thread:
7819 - executes compiled in statements,
7820 - executes SQL statements in the --init-file.
7821 - creates the non-DD based INFORMATION_SCHEMA.
7822 The server then exits.
7823
7824 Compiled in statements are executed in a privileged mode,
7825 with SYSTEM_THREAD_SERVER_INITIALIZE.
7826
7827 @see handle_bootstrap_impl
7828 */
process_bootstrap()7829 static void process_bootstrap() {
7830 MYSQL_FILE *init_file = nullptr;
7831 const char *init_file_name = nullptr;
7832 enum_thread_type system_thread;
7833 bool need_bootstrap = false;
7834
7835 if (opt_initialize) {
7836 // Make sure we can process SIGHUP during bootstrap.
7837 server_components_initialized();
7838 need_bootstrap = true;
7839 system_thread = SYSTEM_THREAD_SERVER_INITIALIZE;
7840 } else {
7841 system_thread = SYSTEM_THREAD_INIT_FILE;
7842 }
7843
7844 if (opt_init_file != nullptr) {
7845 if (*opt_init_file != '\0') {
7846 init_file_name = opt_init_file;
7847 LogErr(INFORMATION_LEVEL, ER_BEG_INITFILE, init_file_name);
7848
7849 init_file = mysql_file_fopen(key_file_init, init_file_name, O_RDONLY,
7850 MYF(MY_WME));
7851 need_bootstrap = true;
7852 }
7853
7854 if (init_file == nullptr) {
7855 LogErr(ERROR_LEVEL, ER_INIT_CANT_OPEN_BOOTSTRAP_FILE, init_file_name);
7856 unireg_abort(MYSQLD_ABORT_EXIT);
7857 }
7858 }
7859
7860 if (need_bootstrap) {
7861 bool error = bootstrap::run_bootstrap_thread(init_file_name, init_file,
7862 nullptr, system_thread);
7863
7864 if (init_file != nullptr) {
7865 mysql_file_fclose(init_file, MYF(MY_WME));
7866 LogErr(INFORMATION_LEVEL, ER_END_INITFILE, init_file_name);
7867 }
7868
7869 if (error) {
7870 /* Abort during system initialization, but not init-file execution */
7871 if (system_thread == SYSTEM_THREAD_SERVER_INITIALIZE) {
7872 unireg_abort(MYSQLD_ABORT_EXIT);
7873 }
7874 }
7875
7876 if (opt_initialize) {
7877 // Create non DD based system views during --initialize.
7878 error = dd::init(
7879 dd::enum_dd_init_type::DD_INITIALIZE_NON_DD_BASED_SYSTEM_VIEWS);
7880 if (error != 0) {
7881 LogErr(ERROR_LEVEL, ER_SYSTEM_VIEW_INIT_FAILED);
7882 unireg_abort(MYSQLD_ABORT_EXIT);
7883 }
7884
7885 unireg_abort(MYSQLD_SUCCESS_EXIT);
7886 }
7887 }
7888
7889 return;
7890 }
7891
7892 /****************************************************************************
7893 Handle start options
7894 ******************************************************************************/
7895
7896 /**
7897 Process command line options flagged as 'early'.
7898 Some components needs to be initialized as early as possible,
7899 because the rest of the server initialization depends on them.
7900 Options that needs to be parsed early includes:
7901 - the performance schema, when compiled in,
7902 - options related to the help,
7903 - options related to the bootstrap
7904 The performance schema needs to be initialized as early as possible,
7905 before to-be-instrumented objects of the server are initialized.
7906 */
handle_early_options()7907 static int handle_early_options() {
7908 int ho_error;
7909 vector<my_option> all_early_options;
7910 all_early_options.reserve(100);
7911
7912 my_getopt_register_get_addr(nullptr);
7913 /* Skip unknown options so that they may be processed later */
7914 my_getopt_skip_unknown = true;
7915
7916 /* Add the system variables parsed early */
7917 sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
7918
7919 /* Add the command line options parsed early */
7920 for (my_option *opt = my_long_early_options; opt->name != nullptr; opt++)
7921 all_early_options.push_back(*opt);
7922
7923 add_terminator(&all_early_options);
7924
7925 my_getopt_error_reporter = option_error_reporter;
7926 my_charset_error_reporter = charset_error_reporter;
7927
7928 ho_error = handle_options(&remaining_argc, &remaining_argv,
7929 &all_early_options[0], mysqld_get_one_option);
7930 if (ho_error == 0) {
7931 /* Add back the program name handle_options removes */
7932 remaining_argc++;
7933 remaining_argv--;
7934
7935 if (opt_initialize_insecure) opt_initialize = true;
7936 }
7937
7938 // Swap with an empty vector, i.e. delete elements and free allocated space.
7939 vector<my_option>().swap(all_early_options);
7940
7941 return ho_error;
7942 }
7943
7944 /**
7945 Adjust @c open_files_limit.
7946 Computation is based on:
7947 - @c max_connections,
7948 - @c table_cache_size,
7949 - the platform max open file limit.
7950 */
adjust_open_files_limit(ulong * requested_open_files)7951 static void adjust_open_files_limit(ulong *requested_open_files) {
7952 ulong limit_1;
7953 ulong limit_2;
7954 ulong limit_3;
7955 ulong request_open_files;
7956 ulong effective_open_files;
7957
7958 /* MyISAM requires two file handles per table. */
7959 limit_1 = 10 + max_connections + table_cache_size * 2;
7960
7961 /*
7962 We are trying to allocate no less than max_connections*5 file
7963 handles (i.e. we are trying to set the limit so that they will
7964 be available).
7965 */
7966 limit_2 = max_connections * 5;
7967
7968 /* Try to allocate no less than 5000 by default. */
7969 limit_3 = open_files_limit ? open_files_limit : 5000;
7970
7971 request_open_files = max<ulong>(max<ulong>(limit_1, limit_2), limit_3);
7972
7973 /* Notice: my_set_max_open_files() may return more than requested. */
7974 effective_open_files = my_set_max_open_files(request_open_files);
7975
7976 if (effective_open_files < request_open_files) {
7977 if (open_files_limit == 0) {
7978 LogErr(WARNING_LEVEL, ER_CHANGED_MAX_OPEN_FILES, effective_open_files,
7979 request_open_files);
7980 } else {
7981 LogErr(WARNING_LEVEL, ER_CANT_INCREASE_MAX_OPEN_FILES,
7982 effective_open_files, request_open_files);
7983 }
7984 }
7985
7986 open_files_limit = effective_open_files;
7987 if (requested_open_files)
7988 *requested_open_files =
7989 min<ulong>(effective_open_files, request_open_files);
7990 }
7991
adjust_max_connections(ulong requested_open_files)7992 static void adjust_max_connections(ulong requested_open_files) {
7993 ulong limit;
7994
7995 limit = requested_open_files - 10 - TABLE_OPEN_CACHE_MIN * 2;
7996
7997 if (limit < max_connections) {
7998 LogErr(WARNING_LEVEL, ER_CHANGED_MAX_CONNECTIONS, limit, max_connections);
7999
8000 // This can be done unprotected since it is only called on startup.
8001 max_connections = limit;
8002 }
8003 }
8004
adjust_table_cache_size(ulong requested_open_files)8005 static void adjust_table_cache_size(ulong requested_open_files) {
8006 ulong limit;
8007
8008 limit = max<ulong>((requested_open_files - 10 - max_connections) / 2,
8009 TABLE_OPEN_CACHE_MIN);
8010
8011 if (limit < table_cache_size) {
8012 LogErr(WARNING_LEVEL, ER_CHANGED_TABLE_OPEN_CACHE, limit, table_cache_size);
8013
8014 table_cache_size = limit;
8015 }
8016
8017 table_cache_size_per_instance = table_cache_size / table_cache_instances;
8018 }
8019
adjust_table_def_size()8020 static void adjust_table_def_size() {
8021 ulong default_value;
8022 sys_var *var;
8023
8024 default_value = min<ulong>(400 + table_cache_size / 2, 2000);
8025 var = intern_find_sys_var(STRING_WITH_LEN("table_definition_cache"));
8026 DBUG_ASSERT(var != nullptr);
8027 var->update_default(default_value);
8028
8029 if (!table_definition_cache_specified) table_def_size = default_value;
8030 }
8031
adjust_related_options(ulong * requested_open_files)8032 static void adjust_related_options(ulong *requested_open_files) {
8033 /*
8034 In bootstrap, disable grant tables (about to be created)
8035 */
8036 if (opt_initialize) opt_noacl = true;
8037
8038 /* The order is critical here, because of dependencies. */
8039 adjust_open_files_limit(requested_open_files);
8040 adjust_max_connections(*requested_open_files);
8041 adjust_table_cache_size(*requested_open_files);
8042 adjust_table_def_size();
8043 }
8044
8045 vector<my_option> all_options;
8046
8047 struct my_option my_long_early_options[] = {
8048 #if !defined(_WIN32)
8049 {"daemonize", 'D', "Run mysqld as sysv daemon", &opt_daemonize,
8050 &opt_daemonize, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8051 #endif
8052 {"skip-grant-tables", 0,
8053 "Start without grant tables. This gives all users FULL ACCESS to all "
8054 "tables.",
8055 &opt_noacl, &opt_noacl, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
8056 nullptr},
8057 {"help", '?', "Display this help and exit.", &opt_help, &opt_help, nullptr,
8058 GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8059 {"verbose", 'v', "Used with --help option for detailed help.", &opt_verbose,
8060 &opt_verbose, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8061 {"version", 'V', "Output version information and exit.", nullptr, nullptr,
8062 nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8063 {"initialize", 'I',
8064 "Create the default database and exit."
8065 " Create a super user with a random expired password and store it into "
8066 "the log.",
8067 &opt_initialize, &opt_initialize, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
8068 nullptr, 0, nullptr},
8069 {"initialize-insecure", 0,
8070 "Create the default database and exit."
8071 " Create a super user with empty password.",
8072 &opt_initialize_insecure, &opt_initialize_insecure, nullptr, GET_BOOL,
8073 NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8074 {"keyring-migration-source", OPT_KEYRING_MIGRATION_SOURCE,
8075 "Keyring plugin from where the keys needs to "
8076 "be migrated to. This option must be specified along with "
8077 "--keyring-migration-destination.",
8078 &opt_keyring_migration_source, &opt_keyring_migration_source, nullptr,
8079 GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8080 {"keyring-migration-destination", OPT_KEYRING_MIGRATION_DESTINATION,
8081 "Keyring plugin to which the keys are "
8082 "migrated to. This option must be specified along with "
8083 "--keyring-migration-source.",
8084 &opt_keyring_migration_destination, &opt_keyring_migration_destination,
8085 nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8086 {"keyring-migration-user", OPT_KEYRING_MIGRATION_USER,
8087 "User to login to server.", &opt_keyring_migration_user,
8088 &opt_keyring_migration_user, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
8089 nullptr, 0, nullptr},
8090 {"keyring-migration-host", OPT_KEYRING_MIGRATION_HOST, "Connect to host.",
8091 &opt_keyring_migration_host, &opt_keyring_migration_host, nullptr, GET_STR,
8092 REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8093 {"keyring-migration-password", 'p',
8094 "Password to use when connecting to server during keyring migration. "
8095 "If password value is not specified then it will be asked from the tty.",
8096 nullptr, nullptr, nullptr, GET_PASSWORD, OPT_ARG, 0, 0, 0, nullptr, 0,
8097 nullptr},
8098 {"keyring-migration-socket", OPT_KEYRING_MIGRATION_SOCKET,
8099 "The socket file to use for connection.", &opt_keyring_migration_socket,
8100 &opt_keyring_migration_socket, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
8101 nullptr, 0, nullptr},
8102 {"keyring-migration-port", OPT_KEYRING_MIGRATION_PORT,
8103 "Port number to use for connection.", &opt_keyring_migration_port,
8104 &opt_keyring_migration_port, nullptr, GET_ULONG, REQUIRED_ARG, 0, 0, 0,
8105 nullptr, 0, nullptr},
8106 {"no-dd-upgrade", 0,
8107 "Abort restart if automatic upgrade or downgrade of the data dictionary "
8108 "is needed. Deprecated option. Use --upgrade=NONE instead.",
8109 &opt_no_dd_upgrade, &opt_no_dd_upgrade, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
8110 nullptr, 0, nullptr},
8111 {"validate-config", 0,
8112 "Validate the server configuration specified by the user.",
8113 &opt_validate_config, &opt_validate_config, nullptr, GET_BOOL, NO_ARG, 0,
8114 0, 0, nullptr, 0, nullptr},
8115 {nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
8116 0, nullptr, 0, nullptr}};
8117
8118 /**
8119 System variables are automatically command-line options (few
8120 exceptions are documented in sys_var.h), so don't need
8121 to be listed here.
8122 */
8123
8124 struct my_option my_long_options[] = {
8125 {"abort-slave-event-count", 0,
8126 "Option used by mysql-test for debugging and testing of replication.",
8127 &abort_slave_event_count, &abort_slave_event_count, nullptr, GET_INT,
8128 REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8129 {"allow-suspicious-udfs", 0,
8130 "Allows use of UDFs consisting of only one symbol xxx() "
8131 "without corresponding xxx_init() or xxx_deinit(). That also means "
8132 "that one can load any function from any library, for example exit() "
8133 "from libc.so",
8134 &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs, nullptr, GET_BOOL,
8135 NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8136 {"ansi", 'a',
8137 "Use ANSI SQL syntax instead of MySQL syntax. This mode "
8138 "will also set transaction isolation level 'serializable'.",
8139 nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
8140 nullptr},
8141 /*
8142 Because Sys_var_bit does not support command-line options, we need to
8143 explicitly add one for --autocommit
8144 */
8145 {"autocommit", 0, "Set default value for autocommit (0 or 1)",
8146 &opt_autocommit, &opt_autocommit, nullptr, GET_BOOL, OPT_ARG, 1, 0, 0,
8147 &source_autocommit, /* arg_source, to be copied to Sys_var */
8148 0, nullptr},
8149 {"binlog-do-db", OPT_BINLOG_DO_DB,
8150 "Tells the master it should log updates for the specified database, "
8151 "and exclude all others not explicitly mentioned.",
8152 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8153 nullptr},
8154 {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
8155 "Tells the master that updates to the given database should not be logged "
8156 "to the binary log.",
8157 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8158 nullptr},
8159 {"character-set-client-handshake", 0,
8160 "Don't ignore client side character set value sent during handshake.",
8161 &opt_character_set_client_handshake, &opt_character_set_client_handshake,
8162 nullptr, GET_BOOL, NO_ARG, 1, 0, 0, nullptr, 0, nullptr},
8163 {"character-set-filesystem", 0, "Set the filesystem character set.",
8164 &character_set_filesystem_name, &character_set_filesystem_name, nullptr,
8165 GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8166 {"character-set-server", 'C', "Set the default character set.",
8167 &default_character_set_name, &default_character_set_name, nullptr, GET_STR,
8168 REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8169 {"chroot", 'r', "Chroot mysqld daemon during startup.", &mysqld_chroot,
8170 &mysqld_chroot, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8171 nullptr},
8172 {"collation-server", 0, "Set the default collation.",
8173 &default_collation_name, &default_collation_name, nullptr, GET_STR,
8174 REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8175 {"console", OPT_CONSOLE,
8176 "Write error output on screen; don't remove the console window on "
8177 "windows.",
8178 &opt_console, &opt_console, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
8179 nullptr},
8180 {"core-file", OPT_WANT_CORE, "Write core on errors.", nullptr, nullptr,
8181 nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8182 /* default-storage-engine should have "MyISAM" as def_value. Instead
8183 of initializing it here it is done in init_common_variables() due
8184 to a compiler bug in Sun Studio compiler. */
8185 {"default-storage-engine", 0, "The default storage engine for new tables",
8186 &default_storage_engine, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
8187 nullptr, 0, nullptr},
8188 {"default-tmp-storage-engine", 0,
8189 "The default storage engine for new explicit temporary tables",
8190 &default_tmp_storage_engine, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
8191 0, nullptr, 0, nullptr},
8192 {"default-time-zone", 0, "Set the default time zone.", &default_tz_name,
8193 &default_tz_name, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8194 nullptr},
8195 {"disconnect-slave-event-count", 0,
8196 "Option used by mysql-test for debugging and testing of replication.",
8197 &disconnect_slave_event_count, &disconnect_slave_event_count, nullptr,
8198 GET_INT, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8199 {"exit-info", 'T', "Used for debugging. Use at your own risk.", nullptr,
8200 nullptr, nullptr, GET_LONG, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
8201
8202 {"external-locking", 0,
8203 "Use system (external) locking (disabled by "
8204 "default). With this option enabled you can run myisamchk to test "
8205 "(not repair) tables while the MySQL server is running. Disable with "
8206 "--skip-external-locking.",
8207 &opt_external_locking, &opt_external_locking, nullptr, GET_BOOL, NO_ARG, 0,
8208 0, 0, nullptr, 0, nullptr},
8209 /* We must always support the next option to make scripts like mysqltest
8210 easier to do */
8211 {"gdb", 0, "Set up signals usable for debugging.", &opt_debugging,
8212 &opt_debugging, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8213 #if defined(HAVE_LINUX_LARGE_PAGES) || defined(HAVE_SOLARIS_LARGE_PAGES)
8214 {"super-large-pages", 0, "Enable support for super large pages.",
8215 &opt_super_large_pages, &opt_super_large_pages, nullptr, GET_BOOL, OPT_ARG,
8216 0, 0, 1, nullptr, 1, nullptr},
8217 #endif
8218 {"language", 'L',
8219 "Client error messages in given language. May be given as a full path. "
8220 "Deprecated. Use --lc-messages-dir instead.",
8221 &lc_messages_dir_ptr, &lc_messages_dir_ptr, nullptr, GET_STR, REQUIRED_ARG,
8222 0, 0, 0, nullptr, 0, nullptr},
8223 {"lc-messages", 0, "Set the language used for the error messages.",
8224 &lc_messages, &lc_messages, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
8225 nullptr, 0, nullptr},
8226 {"lc-time-names", 0,
8227 "Set the language used for the month names and the days of the week.",
8228 &lc_time_names_name, &lc_time_names_name, nullptr, GET_STR, REQUIRED_ARG,
8229 0, 0, 0, nullptr, 0, nullptr},
8230 {"log-bin", OPT_BIN_LOG,
8231 "Configures the name prefix to use for binary log files. If the --log-bin "
8232 "option is not supplied, the name prefix defaults to \"binlog\". If the "
8233 "--log-bin option is supplied without argument, the name prefix defaults "
8234 "to \"HOSTNAME-bin\", where HOSTNAME is the machine's hostname. To set a "
8235 "different name prefix for binary log files, use --log-bin=name. To "
8236 "disable "
8237 "binary logging, use the --skip-log-bin or --disable-log-bin option.",
8238 &opt_bin_logname, &opt_bin_logname, nullptr, GET_STR_ALLOC, OPT_ARG, 0, 0,
8239 0, nullptr, 0, nullptr},
8240 {"log-bin-index", 0, "File that holds the names for binary log files.",
8241 &opt_binlog_index_name, &opt_binlog_index_name, nullptr, GET_STR,
8242 REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8243 {"relay-log-index", 0, "File that holds the names for relay log files.",
8244 &opt_relaylog_index_name, &opt_relaylog_index_name, nullptr, GET_STR,
8245 REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8246 {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
8247 &myisam_log_filename, &myisam_log_filename, nullptr, GET_STR, OPT_ARG, 0,
8248 0, 0, nullptr, 0, nullptr},
8249 {"log-short-format", 0,
8250 "Don't log extra information to update and slow-query logs.",
8251 &opt_short_log_format, &opt_short_log_format, nullptr, GET_BOOL, NO_ARG, 0,
8252 0, 0, nullptr, 0, nullptr},
8253 {"log-tc", 0,
8254 "Path to transaction coordinator log (used for transactions that affect "
8255 "more than one storage engine, when binary log is disabled).",
8256 &opt_tc_log_file, &opt_tc_log_file, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
8257 0, nullptr, 0, nullptr},
8258 {"log-tc-size", 0, "Size of transaction coordinator log.", &opt_tc_log_size,
8259 &opt_tc_log_size, nullptr, GET_ULONG, REQUIRED_ARG,
8260 TC_LOG_MIN_PAGES *my_getpagesize(), TC_LOG_MIN_PAGES *my_getpagesize(),
8261 ULONG_MAX, nullptr, my_getpagesize(), nullptr},
8262 {"master-info-file", OPT_MASTER_INFO_FILE,
8263 "The location and name of the file that remembers the master and where "
8264 "the I/O replication thread is in the master's binlogs. "
8265 "Deprecated option that shall be removed eventually without a "
8266 "replacement.",
8267 &master_info_file, &master_info_file, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
8268 0, nullptr, 0, nullptr},
8269 {"master-retry-count", OPT_MASTER_RETRY_COUNT,
8270 "The number of tries the slave will make to connect to the master before "
8271 "giving up. "
8272 "Deprecated option, use 'CHANGE MASTER TO master_retry_count = <num>' "
8273 "instead.",
8274 &master_retry_count, &master_retry_count, nullptr, GET_ULONG, REQUIRED_ARG,
8275 3600 * 24, 0, 0, nullptr, 0, nullptr},
8276 {"max-binlog-dump-events", 0,
8277 "Option used by mysql-test for debugging and testing of replication.",
8278 &max_binlog_dump_events, &max_binlog_dump_events, nullptr, GET_INT,
8279 REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8280 {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory,
8281 &locked_in_memory, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
8282 nullptr},
8283 {"old-style-user-limits", 0,
8284 "Enable old-style user limits (before 5.0.3, user resources were counted "
8285 "per each user+host vs. per account).",
8286 &opt_old_style_user_limits, &opt_old_style_user_limits, nullptr, GET_BOOL,
8287 NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8288 {"port-open-timeout", 0,
8289 "Maximum time in seconds to wait for the port to become free. "
8290 "(Default: No wait).",
8291 &mysqld_port_timeout, &mysqld_port_timeout, nullptr, GET_UINT,
8292 REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8293 {"replicate-do-db", OPT_REPLICATE_DO_DB,
8294 "Tells the slave thread to restrict replication to the specified "
8295 "database. "
8296 "To specify more than one database, use the directive multiple times, "
8297 "once for each database. Note that this will only work if you do not use "
8298 "cross-database queries such as UPDATE some_db.some_table SET foo='bar' "
8299 "while having selected a different or no database. If you need cross "
8300 "database updates to work, make sure you have 3.23.28 or later, and use "
8301 "replicate-wild-do-table=db_name.%.",
8302 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8303 nullptr},
8304 {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
8305 "Tells the slave thread to restrict replication to the specified table. "
8306 "To specify more than one table, use the directive multiple times, once "
8307 "for each table. This will work for cross-database updates, in contrast "
8308 "to replicate-do-db.",
8309 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8310 nullptr},
8311 {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
8312 "Tells the slave thread to not replicate to the specified database. To "
8313 "specify more than one database to ignore, use the directive multiple "
8314 "times, once for each database. This option will not work if you use "
8315 "cross database updates. If you need cross database updates to work, "
8316 "make sure you have 3.23.28 or later, and use replicate-wild-ignore-"
8317 "table=db_name.%. ",
8318 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8319 nullptr},
8320 {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
8321 "Tells the slave thread to not replicate to the specified table. To "
8322 "specify "
8323 "more than one table to ignore, use the directive multiple times, once "
8324 "for "
8325 "each table. This will work for cross-database updates, in contrast to "
8326 "replicate-ignore-db.",
8327 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8328 nullptr},
8329 {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
8330 "Updates to a database with a different name than the original. Example: "
8331 "replicate-rewrite-db=master_db_name->slave_db_name.",
8332 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8333 nullptr},
8334 {"replicate-same-server-id", 0,
8335 "In replication, if set to 1, do not skip events having our server id. "
8336 "Default value is 0 (to break infinite loops in circular replication). "
8337 "Can't be set to 1 if --log-slave-updates is used.",
8338 &replicate_same_server_id, &replicate_same_server_id, nullptr, GET_BOOL,
8339 NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8340 {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
8341 "Tells the slave thread to restrict replication to the tables that match "
8342 "the specified wildcard pattern. To specify more than one table, use the "
8343 "directive multiple times, once for each table. This will work for cross-"
8344 "database updates. Example: replicate-wild-do-table=foo%.bar% will "
8345 "replicate only updates to tables in all databases that start with foo "
8346 "and whose table names start with bar.",
8347 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8348 nullptr},
8349 {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
8350 "Tells the slave thread to not replicate to the tables that match the "
8351 "given wildcard pattern. To specify more than one table to ignore, use "
8352 "the directive multiple times, once for each table. This will work for "
8353 "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% "
8354 "will not do updates to tables in databases that start with foo and whose "
8355 "table names start with bar.",
8356 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8357 nullptr},
8358 {"safe-user-create", 0,
8359 "Don't allow new user creation by the user who has no write privileges to "
8360 "the mysql.user table.",
8361 &opt_safe_user_create, &opt_safe_user_create, nullptr, GET_BOOL, NO_ARG, 0,
8362 0, 0, nullptr, 0, nullptr},
8363 {"show-slave-auth-info", 0,
8364 "Show user and password in SHOW SLAVE HOSTS on this master.",
8365 &opt_show_slave_auth_info, &opt_show_slave_auth_info, nullptr, GET_BOOL,
8366 NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8367 {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", nullptr,
8368 nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8369 {"skip-new", OPT_SKIP_NEW, "Don't use new, possibly wrong routines.",
8370 nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
8371 nullptr},
8372 {"skip-slave-start", 0, "If set, slave is not autostarted.",
8373 &opt_skip_slave_start, &opt_skip_slave_start, nullptr, GET_BOOL, NO_ARG, 0,
8374 0, 0, nullptr, 0, nullptr},
8375 {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
8376 "Don't print a stack trace on failure.", nullptr, nullptr, nullptr,
8377 GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8378 #if defined(_WIN32)
8379 {"slow-start-timeout", 0,
8380 "Maximum number of milliseconds that the service control manager should "
8381 "wait "
8382 "before trying to kill the windows service during startup"
8383 "(Default: 15000).",
8384 &slow_start_timeout, &slow_start_timeout, 0, GET_ULONG, REQUIRED_ARG,
8385 15000, 0, 0, 0, 0, 0},
8386 #endif
8387 {"sporadic-binlog-dump-fail", 0,
8388 "Option used by mysql-test for debugging and testing of replication.",
8389 &opt_sporadic_binlog_dump_fail, &opt_sporadic_binlog_dump_fail, 0,
8390 GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8391 #ifndef XTRABACKUP
8392 {"ssl", 0,
8393 "Enable SSL for connection (automatically enabled with other flags).",
8394 &opt_use_ssl, &opt_use_ssl, nullptr, GET_BOOL, OPT_ARG, 1, 0, 0, nullptr,
8395 0, nullptr},
8396 {"admin-ssl", 0,
8397 "Enable SSL for admin interface (automatically enabled with other flags).",
8398 &opt_use_admin_ssl, &opt_use_admin_ssl, nullptr, GET_BOOL, OPT_ARG, 1, 0,
8399 0, nullptr, 0, nullptr},
8400 #endif /* XTRABACKUP */
8401 #ifdef _WIN32
8402 {"standalone", 0, "Dummy option to start as a standalone program (NT).", 0,
8403 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
8404 {"no-monitor", 0, "Disable monitor process.", &opt_no_monitor,
8405 &opt_no_monitor, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
8406 #endif
8407 {"symbolic-links", 's',
8408 "Enable symbolic link support (deprecated and will be removed in a future"
8409 " release).",
8410 &my_enable_symlinks, &my_enable_symlinks, nullptr, GET_BOOL, NO_ARG, 0, 0,
8411 0, nullptr, 0, nullptr},
8412 {"sysdate-is-now", 0,
8413 "Non-default option to alias SYSDATE() to NOW() to make it "
8414 "safe-replicable. "
8415 "Since 5.0, SYSDATE() returns a `dynamic' value different for different "
8416 "invocations, even within the same statement.",
8417 &global_system_variables.sysdate_is_now, nullptr, nullptr, GET_BOOL,
8418 NO_ARG, 0, 0, 1, nullptr, 1, nullptr},
8419 {"tc-heuristic-recover", 0,
8420 "Decision to use in heuristic recover process. Possible values are OFF, "
8421 "COMMIT or ROLLBACK.",
8422 &tc_heuristic_recover, &tc_heuristic_recover,
8423 &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG,
8424 TC_HEURISTIC_NOT_USED, 0, 0, nullptr, 0, nullptr},
8425 #if defined(ENABLED_DEBUG_SYNC)
8426 {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT,
8427 "Enable the debug sync facility "
8428 "and optionally specify a default wait timeout in seconds. "
8429 "A zero value keeps the facility disabled.",
8430 &opt_debug_sync_timeout, nullptr, nullptr, GET_UINT, OPT_ARG, 0, 0,
8431 UINT_MAX, nullptr, 0, nullptr},
8432 #endif /* defined(ENABLED_DEBUG_SYNC) */
8433 {"transaction-isolation", 0, "Default transaction isolation level.",
8434 &global_system_variables.transaction_isolation,
8435 &global_system_variables.transaction_isolation, &tx_isolation_typelib,
8436 GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, nullptr, 0, nullptr},
8437 {"transaction-read-only", 0,
8438 "Default transaction access mode. "
8439 "True if transactions are read-only.",
8440 &global_system_variables.transaction_read_only,
8441 &global_system_variables.transaction_read_only, nullptr, GET_BOOL, OPT_ARG,
8442 0, 0, 0, nullptr, 0, nullptr},
8443 {"user", 'u', "Run mysqld daemon as user.", nullptr, nullptr, nullptr,
8444 GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8445 {"early-plugin-load", OPT_EARLY_PLUGIN_LOAD,
8446 "Optional semicolon-separated list of plugins to load before storage "
8447 "engine "
8448 "initialization, where each plugin is identified as name=library, where "
8449 "name is the plugin name and library is the plugin library in plugin_dir.",
8450 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8451 nullptr},
8452 {"plugin-load", OPT_PLUGIN_LOAD,
8453 "Optional semicolon-separated list of plugins to load, where each plugin "
8454 "is "
8455 "identified as name=library, where name is the plugin name and library "
8456 "is the plugin library in plugin_dir.",
8457 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8458 nullptr},
8459 {"plugin-load-add", OPT_PLUGIN_LOAD_ADD,
8460 "Optional semicolon-separated list of plugins to load, where each plugin "
8461 "is "
8462 "identified as name=library, where name is the plugin name and library "
8463 "is the plugin library in plugin_dir. This option adds to the list "
8464 "specified by --plugin-load in an incremental way. "
8465 "Multiple --plugin-load-add are supported.",
8466 nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8467 nullptr},
8468
8469 {"innodb", OPT_SKIP_INNODB,
8470 "Deprecated option. Provided for backward compatibility only. "
8471 "The option has no effect on the server behaviour. InnoDB is always "
8472 "enabled. "
8473 "The option will be removed in a future release.",
8474 nullptr, nullptr, nullptr, GET_BOOL, OPT_ARG, 0, 0, 0, nullptr, 0,
8475 nullptr},
8476
8477 {"upgrade", 0,
8478 "Set server upgrade mode. NONE to abort server if automatic upgrade of "
8479 "the server is needed; MINIMAL to start the server, but skip upgrade "
8480 "steps that are not absolutely necessary; AUTO (default) to upgrade the "
8481 "server if required; FORCE to force upgrade server.",
8482 &opt_upgrade_mode, &opt_upgrade_mode, &upgrade_mode_typelib, GET_ENUM,
8483 REQUIRED_ARG, UPGRADE_AUTO, 0, 0, nullptr, 0, nullptr},
8484
8485 {nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
8486 0, nullptr, 0, nullptr}};
8487
show_queries(THD * thd,SHOW_VAR * var,char *)8488 static int show_queries(THD *thd, SHOW_VAR *var, char *) {
8489 var->type = SHOW_LONGLONG;
8490 var->value = (char *)&thd->query_id;
8491 return 0;
8492 }
8493
show_net_compression(THD * thd,SHOW_VAR * var,char * buff)8494 static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff) {
8495 var->type = SHOW_MY_BOOL;
8496 var->value = buff;
8497 *((bool *)buff) = thd->get_protocol()->get_compression();
8498 return 0;
8499 }
8500
show_net_compression_algorithm(THD * thd,SHOW_VAR * var,char * buff)8501 static int show_net_compression_algorithm(THD *thd, SHOW_VAR *var, char *buff) {
8502 const char *s = thd->get_protocol()->get_compression_algorithm();
8503 var->type = SHOW_CHAR;
8504 var->value = buff;
8505 sprintf(buff, "%s", (s ? s : ""));
8506 return 0;
8507 }
8508
show_net_compression_level(THD * thd,SHOW_VAR * var,char * buff)8509 static int show_net_compression_level(THD *thd, SHOW_VAR *var, char *buff) {
8510 var->type = SHOW_INT;
8511 var->value = buff;
8512 unsigned int *value = reinterpret_cast<unsigned int *>(buff);
8513 *value = thd->get_protocol()->get_compression_level();
8514 return 0;
8515 }
8516
show_starttime(THD * thd,SHOW_VAR * var,char * buff)8517 static int show_starttime(THD *thd, SHOW_VAR *var, char *buff) {
8518 var->type = SHOW_LONGLONG;
8519 var->value = buff;
8520 *((longlong *)buff) =
8521 (longlong)(thd->query_start_in_secs() - server_start_time);
8522 return 0;
8523 }
8524
show_max_used_connections_time(THD * thd,SHOW_VAR * var,char * buff)8525 static int show_max_used_connections_time(THD *thd, SHOW_VAR *var, char *buff) {
8526 MYSQL_TIME max_used_connections_time;
8527 var->type = SHOW_CHAR;
8528 var->value = buff;
8529 thd->variables.time_zone->gmt_sec_to_TIME(
8530 &max_used_connections_time,
8531 Connection_handler_manager::max_used_connections_time);
8532 my_datetime_to_str(max_used_connections_time, buff, 0);
8533 return 0;
8534 }
8535
show_num_thread_running(THD *,SHOW_VAR * var,char * buff)8536 static int show_num_thread_running(THD *, SHOW_VAR *var, char *buff) {
8537 var->type = SHOW_LONGLONG;
8538 var->value = buff;
8539 long long *value = reinterpret_cast<long long *>(buff);
8540 *value = static_cast<long long>(
8541 Global_THD_manager::get_instance()->get_num_thread_running());
8542 return 0;
8543 }
8544
show_num_thread_created(THD *,SHOW_VAR * var,char * buff)8545 static int show_num_thread_created(THD *, SHOW_VAR *var, char *buff) {
8546 var->type = SHOW_LONG;
8547 var->value = buff;
8548 long *value = reinterpret_cast<long *>(buff);
8549 *value = static_cast<long>(
8550 Global_THD_manager::get_instance()->get_num_thread_created());
8551 return 0;
8552 }
8553
show_thread_id_count(THD *,SHOW_VAR * var,char * buff)8554 static int show_thread_id_count(THD *, SHOW_VAR *var, char *buff) {
8555 var->type = SHOW_LONG;
8556 var->value = buff;
8557 long *value = reinterpret_cast<long *>(buff);
8558 *value = static_cast<long>(
8559 Global_THD_manager::get_instance()->get_thread_id() - 1);
8560 return 0;
8561 }
8562
show_aborted_connects(THD *,SHOW_VAR * var,char * buff)8563 static int show_aborted_connects(THD *, SHOW_VAR *var, char *buff) {
8564 var->type = SHOW_LONG;
8565 var->value = buff;
8566 long *value = reinterpret_cast<long *>(buff);
8567 *value = static_cast<long>(
8568 Connection_handler_manager::get_instance()->aborted_connects());
8569 return 0;
8570 }
8571
show_acl_cache_items_count(THD *,SHOW_VAR * var,char * buff)8572 static int show_acl_cache_items_count(THD *, SHOW_VAR *var, char *buff) {
8573 var->type = SHOW_LONG;
8574 var->value = buff;
8575 long *value = reinterpret_cast<long *>(buff);
8576 *value = static_cast<long>(get_global_acl_cache_size());
8577 return 0;
8578 }
8579
show_connection_errors_max_connection(THD *,SHOW_VAR * var,char * buff)8580 static int show_connection_errors_max_connection(THD *, SHOW_VAR *var,
8581 char *buff) {
8582 var->type = SHOW_LONG;
8583 var->value = buff;
8584 long *value = reinterpret_cast<long *>(buff);
8585 *value = static_cast<long>(Connection_handler_manager::get_instance()
8586 ->connection_errors_max_connection());
8587 return 0;
8588 }
8589
show_connection_errors_select(THD *,SHOW_VAR * var,char * buff)8590 static int show_connection_errors_select(THD *, SHOW_VAR *var, char *buff) {
8591 var->type = SHOW_LONG;
8592 var->value = buff;
8593 long *value = reinterpret_cast<long *>(buff);
8594 *value = static_cast<long>(get_connection_errors_select());
8595 return 0;
8596 }
8597
show_connection_errors_accept(THD *,SHOW_VAR * var,char * buff)8598 static int show_connection_errors_accept(THD *, SHOW_VAR *var, char *buff) {
8599 var->type = SHOW_LONG;
8600 var->value = buff;
8601 long *value = reinterpret_cast<long *>(buff);
8602 *value = static_cast<long>(get_connection_errors_accept());
8603 return 0;
8604 }
8605
show_connection_errors_tcpwrap(THD *,SHOW_VAR * var,char * buff)8606 static int show_connection_errors_tcpwrap(THD *, SHOW_VAR *var, char *buff) {
8607 var->type = SHOW_LONG;
8608 var->value = buff;
8609 long *value = reinterpret_cast<long *>(buff);
8610 *value = static_cast<long>(get_connection_errors_tcpwrap());
8611 return 0;
8612 }
8613
8614 #ifdef ENABLED_PROFILING
show_flushstatustime(THD * thd,SHOW_VAR * var,char * buff)8615 static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff) {
8616 var->type = SHOW_LONGLONG;
8617 var->value = buff;
8618 *((longlong *)buff) =
8619 (longlong)(thd->query_start_in_secs() - flush_status_time);
8620 return 0;
8621 }
8622 #endif
8623
8624 /**
8625 After Multisource replication, this function only shows the value
8626 of default channel.
8627
8628 To know the status of other channels, performance schema replication
8629 tables comes to the rescue.
8630
8631 @todo Any warning needed if multiple channels exist to request
8632 the users to start using replication performance schema
8633 tables.
8634 */
show_slave_running(THD *,SHOW_VAR * var,char * buff)8635 static int show_slave_running(THD *, SHOW_VAR *var, char *buff) {
8636 channel_map.rdlock();
8637 Master_info *mi = channel_map.get_default_channel_mi();
8638
8639 if (mi) {
8640 var->type = SHOW_MY_BOOL;
8641 var->value = buff;
8642 *((bool *)buff) =
8643 (bool)(mi && mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
8644 mi->rli->slave_running);
8645 } else
8646 var->type = SHOW_UNDEF;
8647
8648 channel_map.unlock();
8649 return 0;
8650 }
8651
8652 /**
8653 This status variable is also exclusively (look comments on
8654 show_slave_running()) for default channel.
8655 */
show_slave_retried_trans(THD *,SHOW_VAR * var,char * buff)8656 static int show_slave_retried_trans(THD *, SHOW_VAR *var, char *buff) {
8657 channel_map.rdlock();
8658 Master_info *mi = channel_map.get_default_channel_mi();
8659
8660 if (mi) {
8661 var->type = SHOW_LONG;
8662 var->value = buff;
8663 *((long *)buff) = (long)mi->rli->retried_trans;
8664 } else
8665 var->type = SHOW_UNDEF;
8666
8667 channel_map.unlock();
8668 return 0;
8669 }
8670
8671 /**
8672 Only for default channel. Refer to comments on show_slave_running()
8673 */
show_slave_received_heartbeats(THD *,SHOW_VAR * var,char * buff)8674 static int show_slave_received_heartbeats(THD *, SHOW_VAR *var, char *buff) {
8675 channel_map.rdlock();
8676 Master_info *mi = channel_map.get_default_channel_mi();
8677
8678 if (mi) {
8679 var->type = SHOW_LONGLONG;
8680 var->value = buff;
8681 *((longlong *)buff) = mi->received_heartbeats;
8682 } else
8683 var->type = SHOW_UNDEF;
8684
8685 channel_map.unlock();
8686 return 0;
8687 }
8688
8689 /**
8690 Only for default channel. Refer to comments on show_slave_running()
8691 */
show_slave_last_heartbeat(THD * thd,SHOW_VAR * var,char * buff)8692 static int show_slave_last_heartbeat(THD *thd, SHOW_VAR *var, char *buff) {
8693 MYSQL_TIME received_heartbeat_time;
8694
8695 channel_map.rdlock();
8696 Master_info *mi = channel_map.get_default_channel_mi();
8697
8698 if (mi) {
8699 var->type = SHOW_CHAR;
8700 var->value = buff;
8701 if (mi->last_heartbeat == 0)
8702 buff[0] = '\0';
8703 else {
8704 thd->variables.time_zone->gmt_sec_to_TIME(
8705 &received_heartbeat_time,
8706 static_cast<my_time_t>(mi->last_heartbeat / 1000000));
8707 my_datetime_to_str(received_heartbeat_time, buff, 0);
8708 }
8709 } else
8710 var->type = SHOW_UNDEF;
8711
8712 channel_map.unlock();
8713 return 0;
8714 }
8715
8716 /**
8717 Only for default channel. For details, refer to show_slave_running()
8718 */
show_heartbeat_period(THD *,SHOW_VAR * var,char * buff)8719 static int show_heartbeat_period(THD *, SHOW_VAR *var, char *buff) {
8720 channel_map.rdlock();
8721 Master_info *mi = channel_map.get_default_channel_mi();
8722
8723 if (mi) {
8724 var->type = SHOW_CHAR;
8725 var->value = buff;
8726 sprintf(buff, "%.3f", mi->heartbeat_period);
8727 } else
8728 var->type = SHOW_UNDEF;
8729
8730 channel_map.unlock();
8731 return 0;
8732 }
8733
8734 #ifndef DBUG_OFF
show_slave_rows_last_search_algorithm_used(THD *,SHOW_VAR * var,char * buff)8735 static int show_slave_rows_last_search_algorithm_used(THD *, SHOW_VAR *var,
8736 char *buff) {
8737 uint res = slave_rows_last_search_algorithm_used;
8738 const char *s =
8739 ((res == Rows_log_event::ROW_LOOKUP_TABLE_SCAN)
8740 ? "TABLE_SCAN"
8741 : ((res == Rows_log_event::ROW_LOOKUP_HASH_SCAN) ? "HASH_SCAN"
8742 : "INDEX_SCAN"));
8743
8744 var->type = SHOW_CHAR;
8745 var->value = buff;
8746 sprintf(buff, "%s", s);
8747
8748 return 0;
8749 }
8750
show_ongoing_automatic_gtid_violating_transaction_count(THD *,SHOW_VAR * var,char * buf)8751 static int show_ongoing_automatic_gtid_violating_transaction_count(
8752 THD *, SHOW_VAR *var, char *buf) {
8753 var->type = SHOW_CHAR;
8754 var->value = buf;
8755 sprintf(buf, "%d",
8756 gtid_state->get_automatic_gtid_violating_transaction_count());
8757 return 0;
8758 }
8759
show_ongoing_anonymous_gtid_violating_transaction_count(THD *,SHOW_VAR * var,char * buf)8760 static int show_ongoing_anonymous_gtid_violating_transaction_count(
8761 THD *, SHOW_VAR *var, char *buf) {
8762 var->type = SHOW_CHAR;
8763 var->value = buf;
8764 sprintf(buf, "%d",
8765 gtid_state->get_anonymous_gtid_violating_transaction_count());
8766 return 0;
8767 }
8768
8769 #endif
8770
show_ongoing_anonymous_transaction_count(THD *,SHOW_VAR * var,char * buf)8771 static int show_ongoing_anonymous_transaction_count(THD *, SHOW_VAR *var,
8772 char *buf) {
8773 var->type = SHOW_CHAR;
8774 var->value = buf;
8775 sprintf(buf, "%d", gtid_state->get_anonymous_ownership_count());
8776 return 0;
8777 }
8778
show_open_tables(THD *,SHOW_VAR * var,char * buff)8779 static int show_open_tables(THD *, SHOW_VAR *var, char *buff) {
8780 var->type = SHOW_LONG;
8781 var->value = buff;
8782 *((long *)buff) = (long)table_cache_manager.cached_tables();
8783 return 0;
8784 }
8785
show_prepared_stmt_count(THD *,SHOW_VAR * var,char * buff)8786 static int show_prepared_stmt_count(THD *, SHOW_VAR *var, char *buff) {
8787 var->type = SHOW_LONG;
8788 var->value = buff;
8789 mysql_mutex_lock(&LOCK_prepared_stmt_count);
8790 *((long *)buff) = (long)prepared_stmt_count;
8791 mysql_mutex_unlock(&LOCK_prepared_stmt_count);
8792 return 0;
8793 }
8794
show_table_definitions(THD *,SHOW_VAR * var,char * buff)8795 static int show_table_definitions(THD *, SHOW_VAR *var, char *buff) {
8796 var->type = SHOW_LONG;
8797 var->value = buff;
8798 *((long *)buff) = (long)cached_table_definitions();
8799 return 0;
8800 }
8801
8802 /*
8803 Functions relying on SSL
8804 Note: In the show_ssl_* functions, we need to check if we have a
8805 valid vio-object since this isn't always true, specifically
8806 when session_status or global_status is requested from
8807 inside an Event.
8808 */
show_ssl_get_version(THD * thd,SHOW_VAR * var,char *)8809 static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *) {
8810 SSL_handle ssl = thd->get_ssl();
8811 var->type = SHOW_CHAR;
8812 if (ssl)
8813 var->value = const_cast<char *>(SSL_get_version(ssl));
8814 else
8815 var->value = const_cast<char *>("");
8816 return 0;
8817 }
8818
show_ssl_session_reused(THD * thd,SHOW_VAR * var,char * buff)8819 static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff) {
8820 SSL_handle ssl = thd->get_ssl();
8821 var->type = SHOW_LONG;
8822 var->value = buff;
8823 if (ssl)
8824 *((long *)buff) = (long)SSL_session_reused(ssl);
8825 else
8826 *((long *)buff) = 0;
8827 return 0;
8828 }
8829
show_ssl_get_default_timeout(THD * thd,SHOW_VAR * var,char * buff)8830 static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff) {
8831 SSL_handle ssl = thd->get_ssl();
8832 var->type = SHOW_LONG;
8833 var->value = buff;
8834 if (ssl)
8835 *((long *)buff) = (long)SSL_get_default_timeout(ssl);
8836 else
8837 *((long *)buff) = 0;
8838 return 0;
8839 }
8840
show_ssl_get_verify_mode(THD * thd,SHOW_VAR * var,char * buff)8841 static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff) {
8842 SSL_handle ssl = thd->get_ssl();
8843 var->type = SHOW_LONG;
8844 var->value = buff;
8845 if (ssl)
8846 *((long *)buff) = (long)SSL_get_verify_mode(ssl);
8847 else
8848 *((long *)buff) = 0;
8849 return 0;
8850 }
8851
show_ssl_get_verify_depth(THD * thd,SHOW_VAR * var,char * buff)8852 static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff) {
8853 SSL_handle ssl = thd->get_ssl();
8854 var->type = SHOW_LONG;
8855 var->value = buff;
8856 if (ssl)
8857 *((long *)buff) = (long)SSL_get_verify_depth(ssl);
8858 else
8859 *((long *)buff) = 0;
8860 return 0;
8861 }
8862
show_ssl_get_cipher(THD * thd,SHOW_VAR * var,char *)8863 static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *) {
8864 SSL_handle ssl = thd->get_ssl();
8865 var->type = SHOW_CHAR;
8866 if (ssl)
8867 var->value = const_cast<char *>(SSL_get_cipher(ssl));
8868 else
8869 var->value = const_cast<char *>("");
8870 return 0;
8871 }
8872
show_ssl_get_cipher_list(THD * thd,SHOW_VAR * var,char * buff)8873 static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff) {
8874 SSL_handle ssl = thd->get_ssl();
8875 var->type = SHOW_CHAR;
8876 var->value = buff;
8877 if (ssl) {
8878 int i;
8879 const char *p;
8880 char *end = buff + SHOW_VAR_FUNC_BUFF_SIZE;
8881 for (i = 0; (p = SSL_get_cipher_list(ssl, i)) && buff < end; i++) {
8882 buff = my_stpnmov(buff, p, end - buff - 1);
8883 *buff++ = ':';
8884 }
8885 if (i) buff--;
8886 }
8887 *buff = 0;
8888 return 0;
8889 }
8890
show_slave_open_temp_tables(THD *,SHOW_VAR * var,char * buf)8891 static int show_slave_open_temp_tables(THD *, SHOW_VAR *var, char *buf) {
8892 var->type = SHOW_INT;
8893 var->value = buf;
8894 *((int *)buf) = atomic_slave_open_temp_tables;
8895 return 0;
8896 }
8897
8898 /*
8899 Variables shown by SHOW STATUS in alphabetical order
8900 */
8901
8902 SHOW_VAR status_vars[] = {
8903 {"Aborted_clients", (char *)&aborted_threads, SHOW_LONG, SHOW_SCOPE_GLOBAL},
8904 {"Aborted_connects", (char *)&show_aborted_connects, SHOW_FUNC,
8905 SHOW_SCOPE_GLOBAL},
8906 {"Acl_cache_items_count", (char *)&show_acl_cache_items_count, SHOW_FUNC,
8907 SHOW_SCOPE_GLOBAL},
8908 #ifndef DBUG_OFF
8909 {"Ongoing_anonymous_gtid_violating_transaction_count",
8910 (char *)&show_ongoing_anonymous_gtid_violating_transaction_count,
8911 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8912 #endif //! DBUG_OFF
8913 {"Ongoing_anonymous_transaction_count",
8914 (char *)&show_ongoing_anonymous_transaction_count, SHOW_FUNC,
8915 SHOW_SCOPE_GLOBAL},
8916 #ifndef DBUG_OFF
8917 {"Ongoing_automatic_gtid_violating_transaction_count",
8918 (char *)&show_ongoing_automatic_gtid_violating_transaction_count,
8919 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8920 #endif //! DBUG_OFF
8921 {"Binlog_cache_disk_use", (char *)&binlog_cache_disk_use, SHOW_LONG,
8922 SHOW_SCOPE_GLOBAL},
8923 {"Binlog_cache_use", (char *)&binlog_cache_use, SHOW_LONG,
8924 SHOW_SCOPE_GLOBAL},
8925 {"Binlog_stmt_cache_disk_use", (char *)&binlog_stmt_cache_disk_use,
8926 SHOW_LONG, SHOW_SCOPE_GLOBAL},
8927 {"Binlog_stmt_cache_use", (char *)&binlog_stmt_cache_use, SHOW_LONG,
8928 SHOW_SCOPE_GLOBAL},
8929 {"Bytes_received", (char *)offsetof(System_status_var, bytes_received),
8930 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8931 {"Bytes_sent", (char *)offsetof(System_status_var, bytes_sent),
8932 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8933 {"Com", (char *)com_status_vars, SHOW_ARRAY, SHOW_SCOPE_ALL},
8934 {"Com_stmt_reprepare",
8935 (char *)offsetof(System_status_var, com_stmt_reprepare), SHOW_LONG_STATUS,
8936 SHOW_SCOPE_ALL},
8937 {"Compression", (char *)&show_net_compression, SHOW_FUNC,
8938 SHOW_SCOPE_SESSION},
8939 {"Compression_algorithm", (char *)&show_net_compression_algorithm,
8940 SHOW_FUNC, SHOW_SCOPE_SESSION},
8941 {"Compression_level", (char *)&show_net_compression_level, SHOW_FUNC,
8942 SHOW_SCOPE_SESSION},
8943 {"Connections", (char *)&show_thread_id_count, SHOW_FUNC,
8944 SHOW_SCOPE_GLOBAL},
8945 {"Connection_errors_accept", (char *)&show_connection_errors_accept,
8946 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8947 {"Connection_errors_internal", (char *)&connection_errors_internal,
8948 SHOW_LONG, SHOW_SCOPE_GLOBAL},
8949 {"Connection_errors_max_connections",
8950 (char *)&show_connection_errors_max_connection, SHOW_FUNC,
8951 SHOW_SCOPE_GLOBAL},
8952 {"Connection_errors_peer_address", (char *)&connection_errors_peer_addr,
8953 SHOW_LONG, SHOW_SCOPE_GLOBAL},
8954 {"Connection_errors_select", (char *)&show_connection_errors_select,
8955 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8956 {"Connection_errors_tcpwrap", (char *)&show_connection_errors_tcpwrap,
8957 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8958 {"Created_tmp_disk_tables",
8959 (char *)offsetof(System_status_var, created_tmp_disk_tables),
8960 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8961 {"Created_tmp_files", (char *)&my_tmp_file_created, SHOW_LONG,
8962 SHOW_SCOPE_GLOBAL},
8963 {"Created_tmp_tables",
8964 (char *)offsetof(System_status_var, created_tmp_tables),
8965 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8966 {"Delayed_errors", (char *)&delayed_insert_errors, SHOW_LONG,
8967 SHOW_SCOPE_GLOBAL},
8968 {"Delayed_insert_threads", (char *)&delayed_insert_threads,
8969 SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
8970 {"Delayed_writes", (char *)&delayed_insert_writes, SHOW_LONG,
8971 SHOW_SCOPE_GLOBAL},
8972 {"Flush_commands", (char *)&refresh_version, SHOW_LONG_NOFLUSH,
8973 SHOW_SCOPE_GLOBAL},
8974 {"Handler_commit", (char *)offsetof(System_status_var, ha_commit_count),
8975 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8976 {"Handler_delete", (char *)offsetof(System_status_var, ha_delete_count),
8977 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8978 {"Handler_discover", (char *)offsetof(System_status_var, ha_discover_count),
8979 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8980 {"Handler_external_lock",
8981 (char *)offsetof(System_status_var, ha_external_lock_count),
8982 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8983 {"Handler_mrr_init",
8984 (char *)offsetof(System_status_var, ha_multi_range_read_init_count),
8985 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8986 {"Handler_prepare", (char *)offsetof(System_status_var, ha_prepare_count),
8987 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8988 {"Handler_read_first",
8989 (char *)offsetof(System_status_var, ha_read_first_count),
8990 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8991 {"Handler_read_key", (char *)offsetof(System_status_var, ha_read_key_count),
8992 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8993 {"Handler_read_last",
8994 (char *)offsetof(System_status_var, ha_read_last_count),
8995 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8996 {"Handler_read_next",
8997 (char *)offsetof(System_status_var, ha_read_next_count),
8998 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8999 {"Handler_read_prev",
9000 (char *)offsetof(System_status_var, ha_read_prev_count),
9001 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9002 {"Handler_read_rnd", (char *)offsetof(System_status_var, ha_read_rnd_count),
9003 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9004 {"Handler_read_rnd_next",
9005 (char *)offsetof(System_status_var, ha_read_rnd_next_count),
9006 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9007 {"Handler_rollback", (char *)offsetof(System_status_var, ha_rollback_count),
9008 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9009 {"Handler_savepoint",
9010 (char *)offsetof(System_status_var, ha_savepoint_count),
9011 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9012 {"Handler_savepoint_rollback",
9013 (char *)offsetof(System_status_var, ha_savepoint_rollback_count),
9014 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9015 {"Handler_update", (char *)offsetof(System_status_var, ha_update_count),
9016 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9017 {"Handler_write", (char *)offsetof(System_status_var, ha_write_count),
9018 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9019 {"Key_blocks_not_flushed",
9020 (char *)offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG,
9021 SHOW_SCOPE_GLOBAL},
9022 {"Key_blocks_unused", (char *)offsetof(KEY_CACHE, blocks_unused),
9023 SHOW_KEY_CACHE_LONG, SHOW_SCOPE_GLOBAL},
9024 {"Key_blocks_used", (char *)offsetof(KEY_CACHE, blocks_used),
9025 SHOW_KEY_CACHE_LONG, SHOW_SCOPE_GLOBAL},
9026 {"Key_read_requests", (char *)offsetof(KEY_CACHE, global_cache_r_requests),
9027 SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
9028 {"Key_reads", (char *)offsetof(KEY_CACHE, global_cache_read),
9029 SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
9030 {"Key_write_requests", (char *)offsetof(KEY_CACHE, global_cache_w_requests),
9031 SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
9032 {"Key_writes", (char *)offsetof(KEY_CACHE, global_cache_write),
9033 SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
9034 {"Last_query_cost", (char *)offsetof(System_status_var, last_query_cost),
9035 SHOW_DOUBLE_STATUS, SHOW_SCOPE_SESSION},
9036 {"Last_query_partial_plans",
9037 (char *)offsetof(System_status_var, last_query_partial_plans),
9038 SHOW_LONGLONG_STATUS, SHOW_SCOPE_SESSION},
9039 {"Locked_connects", (char *)&locked_account_connection_count, SHOW_LONG,
9040 SHOW_SCOPE_GLOBAL},
9041 {"Max_execution_time_exceeded",
9042 (char *)offsetof(System_status_var, max_execution_time_exceeded),
9043 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9044 {"Max_execution_time_set",
9045 (char *)offsetof(System_status_var, max_execution_time_set),
9046 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9047 {"Max_execution_time_set_failed",
9048 (char *)offsetof(System_status_var, max_execution_time_set_failed),
9049 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9050 {"Max_used_connections",
9051 (char *)&Connection_handler_manager::max_used_connections, SHOW_LONG,
9052 SHOW_SCOPE_GLOBAL},
9053 {"Max_used_connections_time", (char *)&show_max_used_connections_time,
9054 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9055 {"Not_flushed_delayed_rows", (char *)&delayed_rows_in_use,
9056 SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
9057 {"Open_files", (char *)&my_file_opened, SHOW_LONG_NOFLUSH,
9058 SHOW_SCOPE_GLOBAL},
9059 {"Open_streams", (char *)&my_stream_opened, SHOW_LONG_NOFLUSH,
9060 SHOW_SCOPE_GLOBAL},
9061 {"Open_table_definitions", (char *)&show_table_definitions, SHOW_FUNC,
9062 SHOW_SCOPE_GLOBAL},
9063 {"Open_tables", (char *)&show_open_tables, SHOW_FUNC, SHOW_SCOPE_ALL},
9064 {"Opened_files",
9065 const_cast<char *>(reinterpret_cast<const char *>(&my_file_total_opened)),
9066 SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
9067 {"Opened_tables", (char *)offsetof(System_status_var, opened_tables),
9068 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9069 {"Opened_table_definitions",
9070 (char *)offsetof(System_status_var, opened_shares), SHOW_LONGLONG_STATUS,
9071 SHOW_SCOPE_ALL},
9072 {"Prepared_stmt_count", (char *)&show_prepared_stmt_count, SHOW_FUNC,
9073 SHOW_SCOPE_GLOBAL},
9074 {"Queries", (char *)&show_queries, SHOW_FUNC, SHOW_SCOPE_ALL},
9075 {"Questions", (char *)offsetof(System_status_var, questions),
9076 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9077 {"Secondary_engine_execution_count",
9078 (char *)offsetof(System_status_var, secondary_engine_execution_count),
9079 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9080 {"Select_full_join",
9081 (char *)offsetof(System_status_var, select_full_join_count),
9082 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9083 {"Select_full_range_join",
9084 (char *)offsetof(System_status_var, select_full_range_join_count),
9085 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9086 {"Select_range", (char *)offsetof(System_status_var, select_range_count),
9087 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9088 {"Select_range_check",
9089 (char *)offsetof(System_status_var, select_range_check_count),
9090 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9091 {"Select_scan", (char *)offsetof(System_status_var, select_scan_count),
9092 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9093 {"Slave_open_temp_tables", (char *)&show_slave_open_temp_tables, SHOW_FUNC,
9094 SHOW_SCOPE_GLOBAL},
9095 {"Slave_retried_transactions", (char *)&show_slave_retried_trans, SHOW_FUNC,
9096 SHOW_SCOPE_GLOBAL},
9097 {"Slave_heartbeat_period", (char *)&show_heartbeat_period, SHOW_FUNC,
9098 SHOW_SCOPE_GLOBAL},
9099 {"Slave_received_heartbeats", (char *)&show_slave_received_heartbeats,
9100 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9101 {"Slave_last_heartbeat", (char *)&show_slave_last_heartbeat, SHOW_FUNC,
9102 SHOW_SCOPE_GLOBAL},
9103 #ifndef DBUG_OFF
9104 {"Slave_rows_last_search_algorithm_used",
9105 (char *)&show_slave_rows_last_search_algorithm_used, SHOW_FUNC,
9106 SHOW_SCOPE_GLOBAL},
9107 #endif
9108 {"Slave_running", (char *)&show_slave_running, SHOW_FUNC,
9109 SHOW_SCOPE_GLOBAL},
9110 {"Slow_launch_threads",
9111 (char *)&Per_thread_connection_handler::slow_launch_threads, SHOW_LONG,
9112 SHOW_SCOPE_ALL},
9113 {"Slow_queries", (char *)offsetof(System_status_var, long_query_count),
9114 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9115 {"Sort_merge_passes",
9116 (char *)offsetof(System_status_var, filesort_merge_passes),
9117 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9118 {"Sort_range", (char *)offsetof(System_status_var, filesort_range_count),
9119 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9120 {"Sort_rows", (char *)offsetof(System_status_var, filesort_rows),
9121 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9122 {"Sort_scan", (char *)offsetof(System_status_var, filesort_scan_count),
9123 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9124 {"Ssl_accept_renegotiates",
9125 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_accept_renegotiate,
9126 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9127 {"Ssl_accepts", (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_accept,
9128 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9129 {"Ssl_callback_cache_hits",
9130 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_cb_hits, SHOW_FUNC,
9131 SHOW_SCOPE_GLOBAL},
9132 {"Ssl_cipher", (char *)&show_ssl_get_cipher, SHOW_FUNC, SHOW_SCOPE_ALL},
9133 {"Ssl_cipher_list", (char *)&show_ssl_get_cipher_list, SHOW_FUNC,
9134 SHOW_SCOPE_ALL},
9135 {"Ssl_client_connects",
9136 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_connect, SHOW_FUNC,
9137 SHOW_SCOPE_GLOBAL},
9138 {"Ssl_connect_renegotiates",
9139 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_connect_renegotiate,
9140 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9141 {"Ssl_ctx_verify_depth",
9142 (char *)&Ssl_mysql_main_status::show_ssl_ctx_get_verify_depth, SHOW_FUNC,
9143 SHOW_SCOPE_GLOBAL},
9144 {"Ssl_ctx_verify_mode",
9145 (char *)&Ssl_mysql_main_status::show_ssl_ctx_get_verify_mode, SHOW_FUNC,
9146 SHOW_SCOPE_GLOBAL},
9147 {"Ssl_default_timeout", (char *)&show_ssl_get_default_timeout, SHOW_FUNC,
9148 SHOW_SCOPE_ALL},
9149 {"Ssl_finished_accepts",
9150 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_accept_good, SHOW_FUNC,
9151 SHOW_SCOPE_GLOBAL},
9152 {"Ssl_finished_connects",
9153 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_connect_good, SHOW_FUNC,
9154 SHOW_SCOPE_GLOBAL},
9155 {"Ssl_session_cache_hits",
9156 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_hits, SHOW_FUNC,
9157 SHOW_SCOPE_GLOBAL},
9158 {"Ssl_session_cache_misses",
9159 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_misses, SHOW_FUNC,
9160 SHOW_SCOPE_GLOBAL},
9161 {"Ssl_session_cache_mode",
9162 (char *)&Ssl_mysql_main_status::show_ssl_ctx_get_session_cache_mode,
9163 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9164 {"Ssl_session_cache_overflows",
9165 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_cache_full, SHOW_FUNC,
9166 SHOW_SCOPE_GLOBAL},
9167 {"Ssl_session_cache_size",
9168 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_get_cache_size,
9169 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9170 {"Ssl_session_cache_timeouts",
9171 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_timeouts, SHOW_FUNC,
9172 SHOW_SCOPE_GLOBAL},
9173 {"Ssl_sessions_reused", (char *)&show_ssl_session_reused, SHOW_FUNC,
9174 SHOW_SCOPE_ALL},
9175 {"Ssl_used_session_cache_entries",
9176 (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_number, SHOW_FUNC,
9177 SHOW_SCOPE_GLOBAL},
9178 {"Ssl_verify_depth", (char *)&show_ssl_get_verify_depth, SHOW_FUNC,
9179 SHOW_SCOPE_ALL},
9180 {"Ssl_verify_mode", (char *)&show_ssl_get_verify_mode, SHOW_FUNC,
9181 SHOW_SCOPE_ALL},
9182 {"Ssl_version", (char *)&show_ssl_get_version, SHOW_FUNC, SHOW_SCOPE_ALL},
9183 {"Ssl_server_not_before",
9184 (char *)&Ssl_mysql_main_status::show_ssl_get_server_not_before, SHOW_FUNC,
9185 SHOW_SCOPE_ALL},
9186 {"Ssl_server_not_after",
9187 (char *)&Ssl_mysql_main_status::show_ssl_get_server_not_after, SHOW_FUNC,
9188 SHOW_SCOPE_ALL},
9189 {"Current_tls_ca", (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_ca,
9190 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9191 {"Current_tls_capath",
9192 (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_capath, SHOW_FUNC,
9193 SHOW_SCOPE_GLOBAL},
9194 {"Current_tls_cert", (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_cert,
9195 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9196 {"Current_tls_key", (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_key,
9197 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9198 {"Current_tls_version",
9199 (char *)&Ssl_mysql_main_status::show_ssl_get_tls_version, SHOW_FUNC,
9200 SHOW_SCOPE_GLOBAL},
9201 {"Current_tls_cipher",
9202 (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_cipher, SHOW_FUNC,
9203 SHOW_SCOPE_GLOBAL},
9204 {"Current_tls_ciphersuites",
9205 (char *)&Ssl_mysql_main_status::show_ssl_get_tls_ciphersuites, SHOW_FUNC,
9206 SHOW_SCOPE_GLOBAL},
9207 {"Current_tls_crl", (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_crl,
9208 SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9209 {"Current_tls_crlpath",
9210 (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_crlpath, SHOW_FUNC,
9211 SHOW_SCOPE_GLOBAL},
9212 {"Rsa_public_key", (char *)&show_rsa_public_key, SHOW_FUNC,
9213 SHOW_SCOPE_GLOBAL},
9214 {"Table_locks_immediate", (char *)&locks_immediate, SHOW_LONG,
9215 SHOW_SCOPE_GLOBAL},
9216 {"Table_locks_waited", (char *)&locks_waited, SHOW_LONG, SHOW_SCOPE_GLOBAL},
9217 {"Table_open_cache_hits",
9218 (char *)offsetof(System_status_var, table_open_cache_hits),
9219 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9220 {"Table_open_cache_misses",
9221 (char *)offsetof(System_status_var, table_open_cache_misses),
9222 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9223 {"Table_open_cache_overflows",
9224 (char *)offsetof(System_status_var, table_open_cache_overflows),
9225 SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9226 {"Tc_log_max_pages_used", (char *)&tc_log_max_pages_used, SHOW_LONG,
9227 SHOW_SCOPE_GLOBAL},
9228 {"Tc_log_page_size", (char *)&tc_log_page_size, SHOW_LONG_NOFLUSH,
9229 SHOW_SCOPE_GLOBAL},
9230 {"Tc_log_page_waits", (char *)&tc_log_page_waits, SHOW_LONG,
9231 SHOW_SCOPE_GLOBAL},
9232 {"Threads_cached",
9233 (char *)&Per_thread_connection_handler::blocked_pthread_count,
9234 SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
9235 {"Threads_connected", (char *)&Connection_handler_manager::connection_count,
9236 SHOW_INT, SHOW_SCOPE_GLOBAL},
9237 {"Threads_created", (char *)&show_num_thread_created, SHOW_FUNC,
9238 SHOW_SCOPE_GLOBAL},
9239 {"Threads_running", (char *)&show_num_thread_running, SHOW_FUNC,
9240 SHOW_SCOPE_GLOBAL},
9241 {"Uptime", (char *)&show_starttime, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9242 #ifdef ENABLED_PROFILING
9243 {"Uptime_since_flush_status", (char *)&show_flushstatustime, SHOW_FUNC,
9244 SHOW_SCOPE_GLOBAL},
9245 #endif
9246 {NullS, NullS, SHOW_LONG, SHOW_SCOPE_ALL}};
9247
add_terminator(vector<my_option> * options)9248 void add_terminator(vector<my_option> *options) {
9249 my_option empty_element = {nullptr, 0, nullptr, nullptr, nullptr,
9250 nullptr, GET_NO_ARG, NO_ARG, 0, 0,
9251 0, nullptr, 0, nullptr};
9252 options->push_back(empty_element);
9253 }
9254
print_server_version(void)9255 static void print_server_version(void) {
9256 set_server_version();
9257
9258 print_explicit_version(server_version);
9259 }
9260
9261 /** Compares two options' names, treats - and _ the same */
operator <(const my_option & a,const my_option & b)9262 static bool operator<(const my_option &a, const my_option &b) {
9263 const char *sa = a.name;
9264 const char *sb = b.name;
9265 for (; *sa || *sb; sa++, sb++) {
9266 if (*sa < *sb) {
9267 if (*sa == '-' && *sb == '_')
9268 continue;
9269 else
9270 return true;
9271 }
9272 if (*sa > *sb) {
9273 if (*sa == '_' && *sb == '-')
9274 continue;
9275 else
9276 return false;
9277 }
9278 }
9279 DBUG_ASSERT(a.name == b.name);
9280 return false;
9281 }
9282
print_help()9283 static void print_help() {
9284 MEM_ROOT mem_root;
9285 init_alloc_root(key_memory_help, &mem_root, 4096, 4096);
9286
9287 all_options.pop_back();
9288 sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
9289 for (my_option *opt = my_long_early_options; opt->name != nullptr; opt++) {
9290 all_options.push_back(*opt);
9291 }
9292 add_plugin_options(&all_options, &mem_root);
9293 std::sort(all_options.begin(), all_options.end(), std::less<my_option>());
9294 add_terminator(&all_options);
9295
9296 my_print_help(&all_options[0]);
9297 my_print_variables(&all_options[0]);
9298
9299 free_root(&mem_root, MYF(0));
9300 vector<my_option>().swap(all_options); // Deletes the vector contents.
9301 }
9302
usage(void)9303 static void usage(void) {
9304 DBUG_TRACE;
9305 if (!(default_charset_info = get_charset_by_csname(
9306 default_character_set_name, MY_CS_PRIMARY, MYF(MY_WME))))
9307 exit(MYSQLD_ABORT_EXIT);
9308 if (!default_collation_name)
9309 default_collation_name = default_charset_info->name;
9310 if (is_help_or_validate_option() || opt_verbose) {
9311 my_progname = my_progname + dirname_length(my_progname);
9312 }
9313 print_server_version();
9314 puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
9315 puts("Starts the MySQL database server.\n");
9316 printf("Usage: %s [OPTIONS]\n", my_progname);
9317 if (!opt_verbose)
9318 puts(
9319 "\nFor more help options (several pages), use mysqld --verbose "
9320 "--help.");
9321 else {
9322 #ifdef _WIN32
9323 puts(
9324 "NT and Win32 specific options:\n\
9325 --install Install the default service (NT).\n\
9326 --install-manual Install the default service started manually (NT).\n\
9327 --install service_name Install an optional service (NT).\n\
9328 --install-manual service_name Install an optional service started manually (NT).\n\
9329 --remove Remove the default service from the service list (NT).\n\
9330 --remove service_name Remove the service_name from the service list (NT).\n\
9331 --enable-named-pipe Only to be used for the default server (NT).\n\
9332 --standalone Dummy option to start as a standalone server (NT).\
9333 ");
9334 puts("");
9335 #endif
9336 print_defaults(MYSQL_CONFIG_NAME, load_default_groups);
9337 puts("");
9338 set_ports();
9339
9340 /* Print out all the options including plugin supplied options */
9341 print_help();
9342
9343 if (!dynamic_plugins_are_initialized) {
9344 puts(
9345 "\n\
9346 Plugins have parameters that are not reflected in this list\n\
9347 because execution stopped before plugins were initialized.");
9348 }
9349
9350 puts(
9351 "\n\
9352 To see what values a running MySQL server is using, type\n\
9353 'mysqladmin variables' instead of 'mysqld --verbose --help'.");
9354 }
9355 }
9356
9357 /**
9358 Initialize MySQL global variables to default values.
9359
9360 @note
9361 The reason to set a lot of global variables to zero is that
9362 on some exotic platforms global variables are
9363 not set to 0 when a program starts.
9364
9365 We don't need to set variables refered to in my_long_options
9366 as these are initialized by my_getopt.
9367 */
9368
mysql_init_variables()9369 static int mysql_init_variables() {
9370 /* Things reset to zero */
9371 opt_skip_slave_start = false;
9372 pidfile_name[0] = 0;
9373 myisam_test_invalid_symlink = test_if_data_home_dir;
9374 opt_general_log = opt_slow_log = false;
9375 opt_disable_networking = opt_skip_show_db = false;
9376 opt_skip_name_resolve = false;
9377 opt_general_logname = opt_binlog_index_name = opt_slow_logname = nullptr;
9378 opt_tc_log_file = "tc.log"; // no hostname in tc_log file name !
9379 opt_myisam_log = false;
9380 mqh_used = false;
9381 cleanup_done = 0;
9382 server_id_supplied = false;
9383 test_flags = select_errors = ha_open_options = 0;
9384 atomic_slave_open_temp_tables = 0;
9385 opt_endinfo = using_udf_functions = false;
9386 opt_using_transactions = false;
9387 set_connection_events_loop_aborted(false);
9388 set_mysqld_offline_mode(false);
9389 set_mysqld_partial_revokes(opt_partial_revokes);
9390 server_operational_state = SERVER_BOOTING;
9391 aborted_threads = 0;
9392 delayed_insert_threads = delayed_insert_writes = delayed_rows_in_use = 0;
9393 delayed_insert_errors = 0;
9394 specialflag = 0;
9395 binlog_cache_use = binlog_cache_disk_use = 0;
9396 mysqld_user = mysqld_chroot = opt_init_file = opt_bin_logname = nullptr;
9397 prepared_stmt_count = 0;
9398 mysqld_unix_port = opt_mysql_tmpdir = my_bind_addr_str = NullS;
9399 new (&mysql_tmpdir_list) MY_TMPDIR;
9400 memset(&global_status_var, 0, sizeof(global_status_var));
9401 opt_large_pages = false;
9402 opt_super_large_pages = false;
9403 #if defined(ENABLED_DEBUG_SYNC)
9404 opt_debug_sync_timeout = 0;
9405 #endif /* defined(ENABLED_DEBUG_SYNC) */
9406 server_uuid[0] = 0;
9407
9408 /* Character sets */
9409 system_charset_info = &my_charset_utf8_general_ci;
9410 files_charset_info = &my_charset_utf8_general_ci;
9411 national_charset_info = &my_charset_utf8_general_ci;
9412 table_alias_charset = &my_charset_bin;
9413 character_set_filesystem = &my_charset_bin;
9414
9415 opt_specialflag = 0;
9416 pidfile_name_ptr = pidfile_name;
9417 lc_messages_dir_ptr = lc_messages_dir;
9418 protocol_version = PROTOCOL_VERSION;
9419 what_to_log = ~(1L << (uint)COM_TIME);
9420 refresh_version = 1L; /* Increments on each reload */
9421 my_stpcpy(server_version, MYSQL_SERVER_VERSION);
9422 key_caches.empty();
9423 if (!(dflt_key_cache = get_or_create_key_cache(
9424 default_key_cache_base.str, default_key_cache_base.length))) {
9425 LogErr(ERROR_LEVEL, ER_KEYCACHE_OOM);
9426 return 1;
9427 }
9428 /* set key_cache_hash.default_value = dflt_key_cache */
9429 multi_keycache_init();
9430
9431 /* Replication parameters */
9432 master_info_file = "master.info";
9433 relay_log_info_file = "relay-log.info";
9434 report_user = report_password = report_host = nullptr; /* TO BE DELETED */
9435 opt_relay_logname = opt_relaylog_index_name = nullptr;
9436 opt_relaylog_index_name_supplied = false;
9437 opt_relay_logname_supplied = false;
9438 log_bin_basename = nullptr;
9439 log_bin_index = nullptr;
9440
9441 /* Handler variables */
9442 total_ha_2pc = 0;
9443 /* Variables in libraries */
9444 charsets_dir = nullptr;
9445 default_character_set_name = MYSQL_DEFAULT_CHARSET_NAME;
9446 default_collation_name = compiled_default_collation_name;
9447 character_set_filesystem_name = "binary";
9448 lc_messages = mysqld_default_locale_name;
9449 lc_time_names_name = mysqld_default_locale_name;
9450
9451 /* Variables that depends on compile options */
9452 #ifndef DBUG_OFF
9453 default_dbug_option =
9454 IF_WIN("d:t:i:O,\\mysqld.trace", "d:t:i:o,/tmp/mysqld.trace");
9455 #endif
9456 #ifdef ENABLED_PROFILING
9457 have_profiling = SHOW_OPTION_YES;
9458 #else
9459 have_profiling = SHOW_OPTION_NO;
9460 #endif
9461
9462 have_symlink = SHOW_OPTION_YES;
9463
9464 have_dlopen = SHOW_OPTION_YES;
9465
9466 have_query_cache = SHOW_OPTION_NO;
9467
9468 have_geometry = SHOW_OPTION_YES;
9469
9470 have_rtree_keys = SHOW_OPTION_YES;
9471
9472 /* Always true */
9473 have_compress = SHOW_OPTION_YES;
9474 #if defined(_WIN32)
9475 shared_memory_base_name = default_shared_memory_base_name;
9476 #endif
9477
9478 return 0;
9479 }
9480
9481 /**
9482 Check if it is a global replication filter setting.
9483
9484 @param argument The setting of startup option --replicate-*.
9485
9486 @retval
9487 0 OK
9488 @retval
9489 1 Error
9490 */
is_rpl_global_filter_setting(char * argument)9491 static bool is_rpl_global_filter_setting(char *argument) {
9492 DBUG_TRACE;
9493
9494 bool res = false;
9495 char *p = strchr(argument, ':');
9496 if (p == nullptr) res = true;
9497
9498 return res;
9499 }
9500
9501 /**
9502 Extract channel name and filter value from argument.
9503
9504 @param [out] channel_name The name of the channel.
9505 @param [out] filter_val The value of filter.
9506 @param argument The setting of startup option --replicate-*.
9507 */
parse_filter_arg(char ** channel_name,char ** filter_val,char * argument)9508 void parse_filter_arg(char **channel_name, char **filter_val, char *argument) {
9509 DBUG_TRACE;
9510
9511 char *p = strchr(argument, ':');
9512
9513 DBUG_ASSERT(p != nullptr);
9514
9515 /*
9516 If argument='channel_1:db1', then channel_name='channel_1'
9517 and filter_val='db1'; If argument=':db1', then channel_name=''
9518 and filter_val='db1'.
9519 */
9520 *channel_name = argument;
9521 *filter_val = p + 1;
9522 *p = 0;
9523 }
9524
9525 /**
9526 Extract channel name and filter value from argument.
9527
9528 @param [out] key The db is rewritten from.
9529 @param [out] val The db is rewritten to.
9530 @param argument The value of filter.
9531
9532 @retval
9533 0 OK
9534 @retval
9535 1 Error
9536 */
parse_replicate_rewrite_db(char ** key,char ** val,char * argument)9537 static int parse_replicate_rewrite_db(char **key, char **val, char *argument) {
9538 DBUG_TRACE;
9539 char *p;
9540 *key = argument;
9541
9542 if (!(p = strstr(argument, "->"))) {
9543 LogErr(ERROR_LEVEL, ER_RPL_REWRITEDB_MISSING_ARROW);
9544 return 1;
9545 }
9546 *val = p + 2;
9547
9548 while (p > argument && my_isspace(mysqld_charset, p[-1])) p--;
9549 *p = 0;
9550
9551 if (!**key) {
9552 LogErr(ERROR_LEVEL, ER_RPL_REWRITEDB_EMPTY_FROM);
9553 return 1;
9554 }
9555 while (**val && my_isspace(mysqld_charset, **val)) (*val)++;
9556 if (!**val) {
9557 LogErr(ERROR_LEVEL, ER_RPL_REWRITEDB_EMPTY_TO);
9558 return 1;
9559 }
9560
9561 return 0;
9562 }
9563
mysqld_get_one_option(int optid,const struct my_option * opt MY_ATTRIBUTE ((unused)),char * argument)9564 bool mysqld_get_one_option(int optid,
9565 const struct my_option *opt MY_ATTRIBUTE((unused)),
9566 char *argument) {
9567 Rpl_filter *rpl_filter = nullptr;
9568 char *filter_val;
9569 char *channel_name;
9570
9571 switch (optid) {
9572 case '#':
9573 #ifndef DBUG_OFF
9574 DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
9575 #endif
9576 opt_endinfo = true; /* unireg: memory allocation */
9577 break;
9578 case 'a':
9579 global_system_variables.sql_mode = MODE_ANSI;
9580 global_system_variables.transaction_isolation = ISO_SERIALIZABLE;
9581 break;
9582 case 'b':
9583 strmake(mysql_home, argument, sizeof(mysql_home) - 1);
9584 mysql_home_ptr = mysql_home;
9585 break;
9586 case 'C':
9587 if (default_collation_name == compiled_default_collation_name)
9588 default_collation_name = nullptr;
9589 break;
9590 case 'h':
9591 strmake(mysql_real_data_home, argument, sizeof(mysql_real_data_home) - 1);
9592 /* Correct pointer set by my_getopt */
9593 mysql_real_data_home_ptr = mysql_real_data_home;
9594 break;
9595 case 'u':
9596 if (!mysqld_user || !strcmp(mysqld_user, argument))
9597 mysqld_user = argument;
9598 else
9599 LogErr(WARNING_LEVEL, ER_THE_USER_ABIDES, argument, mysqld_user);
9600 break;
9601 case 's':
9602 if (argument && argument[0] == '0') {
9603 LogErr(WARNING_LEVEL, ER_DEPRECATE_MSG_NO_REPLACEMENT,
9604 "Disabling symbolic links using --skip-symbolic-links"
9605 " (or equivalent) is the default. Consider not using"
9606 " this option as it");
9607 } else {
9608 LogErr(WARNING_LEVEL, ER_DEPRECATE_MSG_NO_REPLACEMENT,
9609 "Enabling symbolic using --symbolic-links/-s (or equivalent)");
9610 }
9611 break;
9612 case 'L':
9613 push_deprecated_warn(nullptr, "--language/-l", "'--lc-messages-dir'");
9614 /* Note: fall-through */
9615 case OPT_LC_MESSAGES_DIRECTORY:
9616 strmake(lc_messages_dir, argument, sizeof(lc_messages_dir) - 1);
9617 lc_messages_dir_ptr = lc_messages_dir;
9618 break;
9619 case OPT_BINLOG_FORMAT:
9620 binlog_format_used = true;
9621 break;
9622 case OPT_BINLOG_MAX_FLUSH_QUEUE_TIME:
9623 push_deprecated_warn_no_replacement(nullptr,
9624 "--binlog_max_flush_queue_time");
9625 break;
9626 case OPT_EXPIRE_LOGS_DAYS:
9627 push_deprecated_warn(nullptr, "expire-logs-days",
9628 "binlog_expire_logs_seconds");
9629 expire_logs_days_supplied = true;
9630 break;
9631 case OPT_BINLOG_EXPIRE_LOGS_SECONDS:
9632 binlog_expire_logs_seconds_supplied = true;
9633 break;
9634 #ifndef XTRABACKUP
9635 case OPT_SSL_KEY:
9636 case OPT_SSL_CERT:
9637 case OPT_SSL_CA:
9638 case OPT_SSL_CAPATH:
9639 case OPT_SSL_CIPHER:
9640 case OPT_TLS_CIPHERSUITES:
9641 case OPT_SSL_CRL:
9642 case OPT_SSL_CRLPATH:
9643 case OPT_TLS_VERSION:
9644 /*
9645 Enable use of SSL if we are using any ssl option.
9646 One can disable SSL later by using --skip-ssl or --ssl=0.
9647 */
9648 opt_use_ssl = true;
9649 break;
9650 case OPT_ADMIN_SSL_KEY:
9651 case OPT_ADMIN_SSL_CERT:
9652 case OPT_ADMIN_SSL_CA:
9653 case OPT_ADMIN_SSL_CAPATH:
9654 case OPT_ADMIN_SSL_CIPHER:
9655 case OPT_ADMIN_TLS_CIPHERSUITES:
9656 case OPT_ADMIN_SSL_CRL:
9657 case OPT_ADMIN_SSL_CRLPATH:
9658 case OPT_ADMIN_TLS_VERSION:
9659 /*
9660 Enable use of SSL if we are using any ssl option.
9661 One can disable SSL later by using --skip-admin-ssl or --admin-ssl=0.
9662 */
9663 g_admin_ssl_configured = true;
9664 opt_use_admin_ssl = true;
9665 break;
9666 #endif /* XTRABACKUP */
9667 case 'V':
9668 print_server_version();
9669 exit(MYSQLD_SUCCESS_EXIT);
9670 case 'T':
9671 test_flags = argument ? (uint)atoi(argument) : 0;
9672 opt_endinfo = true;
9673 break;
9674 case (int)OPT_ISAM_LOG:
9675 opt_myisam_log = true;
9676 break;
9677 case (int)OPT_BIN_LOG:
9678 opt_bin_log = (argument != disabled_my_option);
9679 if (!opt_bin_log) {
9680 // Clear the binlog basename used by any previous --log-bin
9681 if (opt_bin_logname) {
9682 my_free(opt_bin_logname);
9683 opt_bin_logname = nullptr;
9684 }
9685 }
9686 log_bin_supplied = true;
9687 break;
9688 case (int)OPT_REPLICATE_IGNORE_DB: {
9689 if (is_rpl_global_filter_setting(argument)) {
9690 rpl_global_filter.add_ignore_db(argument);
9691 rpl_global_filter.ignore_db_statistics.set_all(
9692 CONFIGURED_BY_STARTUP_OPTIONS);
9693 } else {
9694 parse_filter_arg(&channel_name, &filter_val, argument);
9695 rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9696 rpl_filter->add_ignore_db(filter_val);
9697 rpl_filter->ignore_db_statistics.set_all(
9698 CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9699 }
9700 break;
9701 }
9702 case (int)OPT_REPLICATE_DO_DB: {
9703 if (is_rpl_global_filter_setting(argument)) {
9704 rpl_global_filter.add_do_db(argument);
9705 rpl_global_filter.do_db_statistics.set_all(
9706 CONFIGURED_BY_STARTUP_OPTIONS);
9707 } else {
9708 parse_filter_arg(&channel_name, &filter_val, argument);
9709 rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9710 rpl_filter->add_do_db(filter_val);
9711 rpl_filter->do_db_statistics.set_all(
9712 CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9713 }
9714 break;
9715 }
9716 case (int)OPT_REPLICATE_REWRITE_DB: {
9717 char *key, *val;
9718 if (is_rpl_global_filter_setting(argument)) {
9719 if (parse_replicate_rewrite_db(&key, &val, argument)) return true;
9720 rpl_global_filter.add_db_rewrite(key, val);
9721 rpl_global_filter.rewrite_db_statistics.set_all(
9722 CONFIGURED_BY_STARTUP_OPTIONS);
9723 } else {
9724 parse_filter_arg(&channel_name, &filter_val, argument);
9725 rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9726 if (parse_replicate_rewrite_db(&key, &val, filter_val)) return true;
9727 rpl_filter->add_db_rewrite(key, val);
9728 rpl_filter->rewrite_db_statistics.set_all(
9729 CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9730 }
9731 break;
9732 }
9733
9734 case (int)OPT_BINLOG_IGNORE_DB: {
9735 binlog_filter->add_ignore_db(argument);
9736 break;
9737 }
9738 case (int)OPT_BINLOG_DO_DB: {
9739 binlog_filter->add_do_db(argument);
9740 break;
9741 }
9742 case (int)OPT_REPLICATE_DO_TABLE: {
9743 if (is_rpl_global_filter_setting(argument)) {
9744 if (rpl_global_filter.add_do_table_array(argument)) {
9745 LogErr(ERROR_LEVEL, ER_RPL_CANT_ADD_DO_TABLE, argument);
9746 return true;
9747 }
9748 rpl_global_filter.do_table_statistics.set_all(
9749 CONFIGURED_BY_STARTUP_OPTIONS);
9750 } else {
9751 parse_filter_arg(&channel_name, &filter_val, argument);
9752 rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9753 if (rpl_filter->add_do_table_array(filter_val)) {
9754 LogErr(ERROR_LEVEL, ER_RPL_CANT_ADD_DO_TABLE, argument);
9755 return true;
9756 }
9757 rpl_filter->do_table_statistics.set_all(
9758 CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9759 }
9760 break;
9761 }
9762 case (int)OPT_REPLICATE_WILD_DO_TABLE: {
9763 if (is_rpl_global_filter_setting(argument)) {
9764 if (rpl_global_filter.add_wild_do_table(argument)) {
9765 LogErr(ERROR_LEVEL, ER_RPL_FILTER_ADD_WILD_DO_TABLE_FAILED, argument);
9766 return true;
9767 }
9768 rpl_global_filter.wild_do_table_statistics.set_all(
9769 CONFIGURED_BY_STARTUP_OPTIONS);
9770 } else {
9771 parse_filter_arg(&channel_name, &filter_val, argument);
9772 rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9773 if (rpl_filter->add_wild_do_table(filter_val)) {
9774 LogErr(ERROR_LEVEL, ER_RPL_FILTER_ADD_WILD_DO_TABLE_FAILED, argument);
9775 return true;
9776 }
9777 rpl_filter->wild_do_table_statistics.set_all(
9778 CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9779 }
9780 break;
9781 }
9782 case (int)OPT_REPLICATE_WILD_IGNORE_TABLE: {
9783 if (is_rpl_global_filter_setting(argument)) {
9784 if (rpl_global_filter.add_wild_ignore_table(argument)) {
9785 LogErr(ERROR_LEVEL, ER_RPL_FILTER_ADD_WILD_IGNORE_TABLE_FAILED,
9786 argument);
9787 return true;
9788 }
9789 rpl_global_filter.wild_ignore_table_statistics.set_all(
9790 CONFIGURED_BY_STARTUP_OPTIONS);
9791 } else {
9792 parse_filter_arg(&channel_name, &filter_val, argument);
9793 rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9794 if (rpl_filter->add_wild_ignore_table(filter_val)) {
9795 LogErr(ERROR_LEVEL, ER_RPL_FILTER_ADD_WILD_IGNORE_TABLE_FAILED,
9796 argument);
9797 return true;
9798 }
9799 rpl_filter->wild_ignore_table_statistics.set_all(
9800 CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9801 }
9802 break;
9803 }
9804 case (int)OPT_REPLICATE_IGNORE_TABLE: {
9805 if (is_rpl_global_filter_setting(argument)) {
9806 if (rpl_global_filter.add_ignore_table_array(argument)) {
9807 LogErr(ERROR_LEVEL, ER_RPL_CANT_ADD_IGNORE_TABLE, argument);
9808 return true;
9809 }
9810 rpl_global_filter.ignore_table_statistics.set_all(
9811 CONFIGURED_BY_STARTUP_OPTIONS);
9812 } else {
9813 parse_filter_arg(&channel_name, &filter_val, argument);
9814 rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9815 if (rpl_filter->add_ignore_table_array(filter_val)) {
9816 LogErr(ERROR_LEVEL, ER_RPL_CANT_ADD_IGNORE_TABLE, argument);
9817 return true;
9818 }
9819 rpl_filter->ignore_table_statistics.set_all(
9820 CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9821 }
9822 break;
9823 }
9824 case (int)OPT_MASTER_RETRY_COUNT:
9825 push_deprecated_warn(nullptr, "--master-retry-count",
9826 "'CHANGE MASTER TO master_retry_count = <num>'");
9827 break;
9828 case (int)OPT_SKIP_NEW:
9829 opt_specialflag |= SPECIAL_NO_NEW_FUNC;
9830 delay_key_write_options = DELAY_KEY_WRITE_NONE;
9831 myisam_concurrent_insert = 0;
9832 myisam_recover_options = HA_RECOVER_OFF;
9833 sp_automatic_privileges = false;
9834 my_enable_symlinks = false;
9835 ha_open_options &= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
9836 break;
9837 case (int)OPT_SKIP_HOST_CACHE:
9838 opt_specialflag |= SPECIAL_NO_HOST_CACHE;
9839 break;
9840 case (int)OPT_SKIP_RESOLVE:
9841 if (argument && (argument == disabled_my_option ||
9842 !my_strcasecmp(system_charset_info, argument, "OFF")))
9843 opt_skip_name_resolve = false;
9844 else {
9845 opt_skip_name_resolve = true;
9846 opt_specialflag |= SPECIAL_NO_RESOLVE;
9847 }
9848 break;
9849 case (int)OPT_WANT_CORE:
9850 test_flags |= TEST_CORE_ON_SIGNAL;
9851 break;
9852 case (int)OPT_SKIP_STACK_TRACE:
9853 test_flags |= TEST_NO_STACKTRACE;
9854 break;
9855 case OPT_SERVER_ID:
9856 /*
9857 Consider that one received a Server Id when 2 conditions are present:
9858 1) The argument is on the list
9859 2) There is a value present
9860 */
9861 server_id_supplied = (*argument != 0);
9862 break;
9863 case OPT_LOWER_CASE_TABLE_NAMES:
9864 lower_case_table_names_used = true;
9865 break;
9866 #if defined(ENABLED_DEBUG_SYNC)
9867 case OPT_DEBUG_SYNC_TIMEOUT:
9868 /*
9869 Debug Sync Facility. See debug_sync.cc.
9870 Default timeout for WAIT_FOR action.
9871 Default value is zero (facility disabled).
9872 If option is given without an argument, supply a non-zero value.
9873 */
9874 if (!argument) {
9875 /* purecov: begin tested */
9876 opt_debug_sync_timeout = DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT;
9877 /* purecov: end */
9878 }
9879 break;
9880 #endif /* defined(ENABLED_DEBUG_SYNC) */
9881 case OPT_LOG_ERROR:
9882 /*
9883 "No --log-error" == "write errors to stderr",
9884 "--log-error without argument" == "write errors to a file".
9885 */
9886 if (argument == nullptr) /* no argument */
9887 log_error_dest = "";
9888 break;
9889
9890 case OPT_EARLY_PLUGIN_LOAD:
9891 free_list(opt_early_plugin_load_list_ptr);
9892 opt_early_plugin_load_list_ptr->push_back(new i_string(argument));
9893 break;
9894 case OPT_PLUGIN_LOAD:
9895 free_list(opt_plugin_load_list_ptr);
9896 /* fall through */
9897 case OPT_PLUGIN_LOAD_ADD:
9898 opt_plugin_load_list_ptr->push_back(new i_string(argument));
9899 break;
9900 case OPT_PFS_INSTRUMENT: {
9901 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
9902 /*
9903 Parse instrument name and value from argument string. Handle leading
9904 and trailing spaces. Also handle single quotes.
9905
9906 Acceptable:
9907 performance_schema_instrument = ' foo/%/bar/ = ON '
9908 performance_schema_instrument = '%=OFF'
9909 Not acceptable:
9910 performance_schema_instrument = '' foo/%/bar = ON ''
9911 performance_schema_instrument = '%='OFF''
9912 */
9913 char *name = argument, *p = nullptr, *val = nullptr;
9914 bool quote = false; /* true if quote detected */
9915 bool error = true; /* false if no errors detected */
9916 const int PFS_BUFFER_SIZE = 128;
9917 char orig_argument[PFS_BUFFER_SIZE + 1];
9918 orig_argument[0] = 0;
9919
9920 if (!argument) goto pfs_error;
9921
9922 /* Save original argument string for error reporting */
9923 strncpy(orig_argument, argument, PFS_BUFFER_SIZE);
9924
9925 /* Split instrument name and value at the equal sign */
9926 if (!(p = strchr(argument, '='))) goto pfs_error;
9927
9928 /* Get option value */
9929 val = p + 1;
9930 if (!*val) goto pfs_error;
9931
9932 /* Trim leading spaces and quote from the instrument name */
9933 while (*name && (my_isspace(mysqld_charset, *name) || (*name == '\''))) {
9934 /* One quote allowed */
9935 if (*name == '\'') {
9936 if (!quote)
9937 quote = true;
9938 else
9939 goto pfs_error;
9940 }
9941 name++;
9942 }
9943
9944 /* Trim trailing spaces from instrument name */
9945 while ((p > name) && my_isspace(mysqld_charset, p[-1])) p--;
9946 *p = 0;
9947
9948 /* Remove trailing slash from instrument name */
9949 if (p > name && (p[-1] == '/')) p[-1] = 0;
9950
9951 if (!*name) goto pfs_error;
9952
9953 /* Trim leading spaces from option value */
9954 while (*val && my_isspace(mysqld_charset, *val)) val++;
9955
9956 /* Trim trailing spaces and matching quote from value */
9957 p = val + strlen(val);
9958 while (p > val && (my_isspace(mysqld_charset, p[-1]) || p[-1] == '\'')) {
9959 /* One matching quote allowed */
9960 if (p[-1] == '\'') {
9961 if (quote)
9962 quote = false;
9963 else
9964 goto pfs_error;
9965 }
9966 p--;
9967 }
9968
9969 *p = 0;
9970
9971 if (!*val) goto pfs_error;
9972
9973 /* Add instrument name and value to array of configuration options */
9974 if (add_pfs_instr_to_array(name, val)) goto pfs_error;
9975
9976 error = false;
9977
9978 pfs_error:
9979 if (error) {
9980 LogErr(WARNING_LEVEL, ER_INVALID_INSTRUMENT, orig_argument);
9981 return false;
9982 }
9983 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
9984 break;
9985 }
9986 case OPT_THREAD_CACHE_SIZE:
9987 thread_cache_size_specified = true;
9988 break;
9989 case OPT_HOST_CACHE_SIZE:
9990 host_cache_size_specified = true;
9991 break;
9992 case OPT_TABLE_DEFINITION_CACHE:
9993 table_definition_cache_specified = true;
9994 break;
9995 case OPT_SKIP_INNODB:
9996 LogErr(WARNING_LEVEL, ER_INNODB_MANDATORY);
9997 break;
9998 case OPT_AVOID_TEMPORAL_UPGRADE:
9999 push_deprecated_warn_no_replacement(nullptr, "avoid_temporal_upgrade");
10000 break;
10001 case OPT_SHOW_OLD_TEMPORALS:
10002 push_deprecated_warn_no_replacement(nullptr, "show_old_temporals");
10003 break;
10004 case 'p':
10005 if (argument) {
10006 char *start = argument;
10007 my_free(opt_keyring_migration_password);
10008 opt_keyring_migration_password =
10009 my_strdup(PSI_NOT_INSTRUMENTED, argument, MYF(MY_FAE));
10010 while (*argument) *argument++ = 'x';
10011 if (*start) start[1] = 0;
10012 } else
10013 opt_keyring_migration_password = get_tty_password(NullS);
10014 migrate_connect_options = true;
10015 break;
10016 case OPT_KEYRING_MIGRATION_USER:
10017 case OPT_KEYRING_MIGRATION_HOST:
10018 case OPT_KEYRING_MIGRATION_SOCKET:
10019 case OPT_KEYRING_MIGRATION_PORT:
10020 migrate_connect_options = true;
10021 break;
10022 case OPT_LOG_SLAVE_UPDATES:
10023 log_slave_updates_supplied = true;
10024 break;
10025 case OPT_SLAVE_PRESERVE_COMMIT_ORDER:
10026 slave_preserve_commit_order_supplied = true;
10027 break;
10028 case OPT_ENFORCE_GTID_CONSISTENCY: {
10029 const char *wrong_value =
10030 fixup_enforce_gtid_consistency_command_line(argument);
10031 if (wrong_value != nullptr)
10032 LogErr(WARNING_LEVEL, ER_INVALID_VALUE_FOR_ENFORCE_GTID_CONSISTENCY,
10033 wrong_value);
10034 } break;
10035 case OPT_NAMED_PIPE_FULL_ACCESS_GROUP:
10036 #ifdef _WIN32
10037 if (!is_valid_named_pipe_full_access_group(argument)) {
10038 LogErr(ERROR_LEVEL, ER_INVALID_NAMED_PIPE_FULL_ACCESS_GROUP);
10039 return 1;
10040 }
10041 #endif // _WIN32
10042 break;
10043 case OPT_RELAY_LOG_INFO_FILE:
10044 push_deprecated_warn_no_replacement(nullptr, "--relay-log-info-file");
10045 break;
10046 case OPT_MASTER_INFO_FILE:
10047 push_deprecated_warn_no_replacement(nullptr, "--master-info-file");
10048 break;
10049 case OPT_LOG_BIN_USE_V1_ROW_EVENTS:
10050 push_deprecated_warn_no_replacement(nullptr,
10051 "--log-bin-use-v1-row-events");
10052 break;
10053 case OPT_SLAVE_ROWS_SEARCH_ALGORITHMS:
10054 push_deprecated_warn_no_replacement(nullptr,
10055 "--slave-rows-search-algorithms");
10056 break;
10057 }
10058 return false;
10059 }
10060
10061 /** Handle arguments for multiple key caches. */
10062
mysql_getopt_value(const char * keyname,size_t key_length,const struct my_option * option,int * error)10063 static void *mysql_getopt_value(const char *keyname, size_t key_length,
10064 const struct my_option *option, int *error) {
10065 if (error) *error = 0;
10066 switch (option->id) {
10067 case OPT_KEY_BUFFER_SIZE:
10068 case OPT_KEY_CACHE_BLOCK_SIZE:
10069 case OPT_KEY_CACHE_DIVISION_LIMIT:
10070 case OPT_KEY_CACHE_AGE_THRESHOLD: {
10071 KEY_CACHE *key_cache;
10072 if (!(key_cache = get_or_create_key_cache(keyname, key_length))) {
10073 if (error) *error = EXIT_OUT_OF_MEMORY;
10074 return nullptr;
10075 }
10076 switch (option->id) {
10077 case OPT_KEY_BUFFER_SIZE:
10078 return &key_cache->param_buff_size;
10079 case OPT_KEY_CACHE_BLOCK_SIZE:
10080 return &key_cache->param_block_size;
10081 case OPT_KEY_CACHE_DIVISION_LIMIT:
10082 return &key_cache->param_division_limit;
10083 case OPT_KEY_CACHE_AGE_THRESHOLD:
10084 return &key_cache->param_age_threshold;
10085 }
10086 }
10087 }
10088 return option->value;
10089 }
10090
10091 /**
10092 Get server options from the command line,
10093 and perform related server initializations.
10094 @param [in, out] argc_ptr command line options (count)
10095 @param [in, out] argv_ptr command line options (values)
10096 @return 0 on success
10097
10098 @todo
10099 - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
10100 */
get_options(int * argc_ptr,char *** argv_ptr)10101 static int get_options(int *argc_ptr, char ***argv_ptr) {
10102 int ho_error;
10103
10104 my_getopt_register_get_addr(mysql_getopt_value);
10105
10106 /* prepare all_options array */
10107 all_options.reserve(array_elements(my_long_options));
10108 for (my_option *opt = my_long_options;
10109 opt < my_long_options + array_elements(my_long_options) - 1; opt++) {
10110 all_options.push_back(*opt);
10111 }
10112 sys_var_add_options(&all_options, sys_var::PARSE_NORMAL);
10113 add_terminator(&all_options);
10114
10115 if (is_help_or_validate_option() || opt_initialize) {
10116 /*
10117 Show errors during --help, but mute everything else so the info the
10118 user actually wants isn't lost in the spam. (For --help --verbose,
10119 we need to set up far enough to be able to print variables provided
10120 by plugins, so a good number of warnings/notes might get printed.)
10121 Likewise for --initialize.
10122 */
10123 struct my_option *opt = &all_options[0];
10124 for (; opt->name; opt++)
10125 if (!strcmp("log_error_verbosity", opt->name))
10126 opt->def_value = opt_initialize ? 2 : 1;
10127 }
10128
10129 /* Skip unknown options so that they may be processed later by plugins */
10130 my_getopt_skip_unknown = true;
10131
10132 if ((ho_error = handle_options(argc_ptr, argv_ptr, &all_options[0],
10133 mysqld_get_one_option)))
10134 return ho_error;
10135
10136 // update verbosity in filter engine, if needed
10137 log_builtins_filter_update_verbosity(log_error_verbosity);
10138
10139 // update suppression list in filter engine
10140 {
10141 int rr;
10142 // try to set the list
10143 if (((rr = log_builtins_filter_parse_suppression_list(
10144 opt_log_error_suppression_list, false)) != 0) ||
10145 ((rr = log_builtins_filter_parse_suppression_list(
10146 opt_log_error_suppression_list, true)) != 0)) {
10147 rr = -(rr + 1);
10148 LogErr(ERROR_LEVEL, ER_CANT_SET_ERROR_SUPPRESSION_LIST_FROM_COMMAND_LINE,
10149 "log_error_suppression_list", &opt_log_error_suppression_list[rr]);
10150
10151 /*
10152 We were given an illegal value at start-up, so the default will be
10153 used instead. We have reported the problem (and the dodgy value);
10154 let's now point our variable back at the default (i.e. the value
10155 actually used) so SELECT @@GLOBAL.log_error_suppression_list will
10156 render correct results.
10157 */
10158 sys_var *var =
10159 intern_find_sys_var(STRING_WITH_LEN("log_error_suppression_list"));
10160 if (var != nullptr) {
10161 opt_log_error_suppression_list = (char *)var->get_default();
10162 /*
10163 During unit-testing, the log subsystem is not initialized,
10164 so while the default should always check out as a valid
10165 argument, actually setting it will still fail in this
10166 particular case as we cannot acquire the rule-set or its
10167 lock.
10168 */
10169 if (log_builtins_filter_parse_suppression_list(
10170 opt_log_error_suppression_list, false) == 0) {
10171 log_builtins_filter_parse_suppression_list(
10172 opt_log_error_suppression_list, true);
10173 } else {
10174 DBUG_ASSERT(false); /* purecov: inspected */
10175 }
10176 }
10177 }
10178 }
10179
10180 if (!is_help_or_validate_option())
10181 vector<my_option>().swap(all_options); // Deletes the vector contents.
10182
10183 /* Add back the program name handle_options removes */
10184 (*argc_ptr)++;
10185 (*argv_ptr)--;
10186
10187 /*
10188 Options have been parsed. Now some of them need additional special
10189 handling, like custom value checking, checking of incompatibilites
10190 between options, setting of multiple variables, etc.
10191 Do them here.
10192 */
10193
10194 if (!opt_help && opt_verbose) LogErr(ERROR_LEVEL, ER_VERBOSE_REQUIRES_HELP);
10195
10196 if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
10197 opt_log_slow_slave_statements) &&
10198 !opt_slow_log)
10199 LogErr(WARNING_LEVEL, ER_POINTLESS_WITHOUT_SLOWLOG);
10200
10201 if (global_system_variables.net_buffer_length >
10202 global_system_variables.max_allowed_packet) {
10203 LogErr(WARNING_LEVEL, ER_WASTEFUL_NET_BUFFER_SIZE,
10204 global_system_variables.net_buffer_length,
10205 global_system_variables.max_allowed_packet);
10206 }
10207
10208 /*
10209 TIMESTAMP columns get implicit DEFAULT values when
10210 --explicit_defaults_for_timestamp is not set.
10211 This behavior is deprecated now.
10212 */
10213 if (!is_help_or_validate_option() &&
10214 !global_system_variables.explicit_defaults_for_timestamp)
10215 LogErr(WARNING_LEVEL, ER_DEPRECATED_TIMESTAMP_IMPLICIT_DEFAULTS);
10216
10217 if (!is_help_or_validate_option() &&
10218 opt_mi_repository_id == INFO_REPOSITORY_FILE)
10219 push_deprecated_warn(nullptr, "--master-info-repository=FILE",
10220 "'--master-info-repository=TABLE'");
10221
10222 if (!is_help_or_validate_option() &&
10223 opt_rli_repository_id == INFO_REPOSITORY_FILE)
10224 push_deprecated_warn(nullptr, "--relay-log-info-repository=FILE",
10225 "'--relay-log-info-repository=TABLE'");
10226
10227 opt_init_connect.length = strlen(opt_init_connect.str);
10228 opt_init_slave.length = strlen(opt_init_slave.str);
10229 opt_mandatory_roles.length = strlen(opt_mandatory_roles.str);
10230
10231 if (global_system_variables.low_priority_updates)
10232 thr_upgraded_concurrent_insert_lock = TL_WRITE_LOW_PRIORITY;
10233
10234 if (ft_boolean_check_syntax_string(
10235 pointer_cast<const uchar *>(ft_boolean_syntax))) {
10236 LogErr(ERROR_LEVEL, ER_FT_BOOL_SYNTAX_INVALID, ft_boolean_syntax);
10237 return 1;
10238 }
10239
10240 if (opt_noacl && !is_help_or_validate_option()) opt_disable_networking = true;
10241
10242 if (opt_disable_networking) mysqld_port = 0;
10243
10244 if (opt_skip_show_db) opt_specialflag |= SPECIAL_SKIP_SHOW_DB;
10245
10246 if (myisam_flush) flush_time = 0;
10247
10248 if (opt_slave_skip_errors) add_slave_skip_errors(opt_slave_skip_errors);
10249
10250 if (global_system_variables.max_join_size == HA_POS_ERROR)
10251 global_system_variables.option_bits |= OPTION_BIG_SELECTS;
10252 else
10253 global_system_variables.option_bits &= ~OPTION_BIG_SELECTS;
10254
10255 // Synchronize @@global.autocommit value on --autocommit
10256 const ulonglong turn_bit_on =
10257 opt_autocommit ? OPTION_AUTOCOMMIT : OPTION_NOT_AUTOCOMMIT;
10258 global_system_variables.option_bits =
10259 (global_system_variables.option_bits &
10260 ~(OPTION_NOT_AUTOCOMMIT | OPTION_AUTOCOMMIT)) |
10261 turn_bit_on;
10262
10263 // Synchronize @@global.autocommit metadata on --autocommit
10264 my_option *opt = &my_long_options[3];
10265 DBUG_ASSERT(strcmp(opt->name, "autocommit") == 0);
10266 DBUG_ASSERT(opt->arg_source != nullptr);
10267 Sys_autocommit_ptr->set_source_name(opt->arg_source->m_path_name);
10268 Sys_autocommit_ptr->set_source(opt->arg_source->m_source);
10269
10270 global_system_variables.sql_mode =
10271 expand_sql_mode(global_system_variables.sql_mode, nullptr);
10272
10273 if (!my_enable_symlinks) have_symlink = SHOW_OPTION_DISABLED;
10274
10275 if (opt_debugging) {
10276 /* Allow break with SIGINT, no core or stack trace */
10277 test_flags |= TEST_SIGINT | TEST_NO_STACKTRACE;
10278 test_flags &= ~TEST_CORE_ON_SIGNAL;
10279 }
10280 /* Set global MyISAM variables from delay_key_write_options */
10281 fix_delay_key_write(nullptr, nullptr, OPT_GLOBAL);
10282
10283 #ifndef _WIN32
10284 if (mysqld_chroot) set_root(mysqld_chroot);
10285 #endif
10286 if (fix_paths()) return 1;
10287
10288 /*
10289 Set some global variables from the global_system_variables
10290 In most cases the global variables will not be used
10291 */
10292 my_disable_locking = myisam_single_user = (opt_external_locking == 0);
10293 my_default_record_cache_size = global_system_variables.read_buff_size;
10294
10295 global_system_variables.long_query_time =
10296 (ulonglong)(global_system_variables.long_query_time_double * 1e6);
10297
10298 if (opt_short_log_format) opt_specialflag |= SPECIAL_SHORT_LOG_FORMAT;
10299
10300 if (Connection_handler_manager::init()) {
10301 LogErr(ERROR_LEVEL, ER_CONNECTION_HANDLING_OOM);
10302 return 1;
10303 }
10304 if (Global_THD_manager::create_instance()) {
10305 LogErr(ERROR_LEVEL, ER_THREAD_HANDLING_OOM);
10306 return 1;
10307 }
10308
10309 /* If --super-read-only was specified, set read_only to 1 */
10310 read_only = super_read_only ? super_read_only : read_only;
10311 opt_readonly = read_only;
10312
10313 return 0;
10314 }
10315
10316 /*
10317 Create version name for running mysqld version
10318 We automaticly add suffixes -debug, -valgrind, -asan, -ubsan
10319 to the version name to make the version more descriptive.
10320 (MYSQL_SERVER_SUFFIX is set by the compilation environment)
10321 */
10322
10323 /*
10324 The following code is quite ugly as there is no portable way to easily set a
10325 string to the value of a macro
10326 */
10327 #ifdef MYSQL_SERVER_SUFFIX
10328 #define MYSQL_SERVER_SUFFIX_STR STRINGIFY_ARG(MYSQL_SERVER_SUFFIX)
10329 #else
10330 #define MYSQL_SERVER_SUFFIX_STR MYSQL_SERVER_SUFFIX_DEF
10331 #endif
10332
set_server_version(void)10333 static void set_server_version(void) {
10334 char *end MY_ATTRIBUTE((unused)) = strxmov(
10335 server_version, MYSQL_SERVER_VERSION, MYSQL_SERVER_SUFFIX_STR, NullS);
10336 #ifndef DBUG_OFF
10337 if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
10338 end = my_stpcpy(end, "-debug");
10339 #endif
10340 #ifdef HAVE_VALGRIND
10341 if (SERVER_VERSION_LENGTH - (end - server_version) >
10342 static_cast<int>(sizeof("-valgrind")))
10343 end = my_stpcpy(end, "-valgrind");
10344 #endif
10345 #ifdef HAVE_ASAN
10346 if (SERVER_VERSION_LENGTH - (end - server_version) >
10347 static_cast<int>(sizeof("-asan")))
10348 end = my_stpcpy(end, "-asan");
10349 #endif
10350 #ifdef HAVE_LSAN
10351 if (SERVER_VERSION_LENGTH - (end - server_version) >
10352 static_cast<int>(sizeof("-lsan")))
10353 end = my_stpcpy(end, "-lsan");
10354 #endif
10355 #ifdef HAVE_UBSAN
10356 if (SERVER_VERSION_LENGTH - (end - server_version) >
10357 static_cast<int>(sizeof("-ubsan")))
10358 end = my_stpcpy(end, "-ubsan");
10359 #endif
10360 #ifdef HAVE_TSAN
10361 if (SERVER_VERSION_LENGTH - (end - server_version) >
10362 static_cast<int>(sizeof("-tsan")))
10363 end = my_stpcpy(end, "-tsan");
10364 #endif
10365 }
10366
get_relative_path(const char * path)10367 static const char *get_relative_path(const char *path) {
10368 if (test_if_hard_path(path) && is_prefix(path, DEFAULT_MYSQL_HOME) &&
10369 strcmp(DEFAULT_MYSQL_HOME, FN_ROOTDIR)) {
10370 path += strlen(DEFAULT_MYSQL_HOME);
10371 while (is_directory_separator(*path)) path++;
10372 }
10373 return path;
10374 }
10375
10376 /**
10377 Test a file path to determine if the path is compatible with the secure file
10378 path restriction.
10379
10380 @param path null terminated character string
10381
10382 @retval true The path is secure
10383 @retval false The path isn't secure
10384 */
10385
is_secure_file_path(const char * path)10386 bool is_secure_file_path(const char *path) {
10387 char buff1[FN_REFLEN], buff2[FN_REFLEN];
10388 size_t opt_secure_file_priv_len;
10389 /*
10390 All paths are secure if opt_secure_file_priv is 0
10391 */
10392 if (!opt_secure_file_priv[0]) return true;
10393
10394 opt_secure_file_priv_len = strlen(opt_secure_file_priv);
10395
10396 if (strlen(path) >= FN_REFLEN) return false;
10397
10398 if (!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
10399 return false;
10400
10401 if (my_realpath(buff1, path, 0)) {
10402 /*
10403 The supplied file path might have been a file and not a directory.
10404 */
10405 int length = (int)dirname_length(path);
10406 if (length >= FN_REFLEN) return false;
10407 memcpy(buff2, path, length);
10408 buff2[length] = '\0';
10409 if (length == 0 || my_realpath(buff1, buff2, 0)) return false;
10410 }
10411 convert_dirname(buff2, buff1, NullS);
10412 if (!lower_case_file_system) {
10413 if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
10414 return false;
10415 } else {
10416 if (files_charset_info->coll->strnncoll(
10417 files_charset_info, (uchar *)buff2, strlen(buff2),
10418 pointer_cast<const uchar *>(opt_secure_file_priv),
10419 opt_secure_file_priv_len, true))
10420 return false;
10421 }
10422 return true;
10423 }
10424
10425 /**
10426 check_secure_file_priv_path : Checks path specified through
10427 --secure-file-priv and raises warning in following cases:
10428 1. If path is empty string or NULL and mysqld is not running
10429 with --initialize (bootstrap mode).
10430 2. If path can access data directory
10431 3. If path points to a directory which is accessible by
10432 all OS users (non-Windows build only)
10433
10434 It throws error in following cases:
10435
10436 1. If path normalization fails
10437 2. If it can not get stats of the directory
10438
10439 Assumptions :
10440 1. Data directory path has been normalized
10441 2. opt_secure_file_priv has been normalized unless it is set
10442 to "NULL".
10443
10444 @returns Status of validation
10445 @retval true : Validation is successful with/without warnings
10446 @retval false : Validation failed. Error is raised.
10447 */
10448
check_secure_file_priv_path()10449 static bool check_secure_file_priv_path() {
10450 char datadir_buffer[FN_REFLEN + 1] = {0};
10451 char plugindir_buffer[FN_REFLEN + 1] = {0};
10452 char whichdir[20] = {0};
10453 size_t opt_plugindir_len = 0;
10454 size_t opt_datadir_len = 0;
10455 size_t opt_secure_file_priv_len = 0;
10456 bool warn = false;
10457 bool case_insensitive_fs;
10458 #ifndef _WIN32
10459 MY_STAT dir_stat;
10460 #endif
10461
10462 if (!opt_secure_file_priv[0]) {
10463 if (opt_initialize) {
10464 /*
10465 Do not impose --secure-file-priv restriction
10466 in bootstrap mode
10467 */
10468 LogErr(INFORMATION_LEVEL, ER_SEC_FILE_PRIV_IGNORED);
10469 } else {
10470 LogErr(WARNING_LEVEL, ER_SEC_FILE_PRIV_EMPTY);
10471 }
10472 return true;
10473 }
10474
10475 /*
10476 Setting --secure-file-priv to NULL would disable
10477 reading/writing from/to file
10478 */
10479 if (!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL")) {
10480 LogErr(INFORMATION_LEVEL, ER_SEC_FILE_PRIV_NULL);
10481 return true;
10482 }
10483
10484 /*
10485 Check if --secure-file-priv can access data directory
10486 */
10487 opt_secure_file_priv_len = strlen(opt_secure_file_priv);
10488
10489 /*
10490 Adds dir seperator at the end.
10491 This is required in subsequent comparison
10492 */
10493 convert_dirname(datadir_buffer, mysql_unpacked_real_data_home, NullS);
10494 opt_datadir_len = strlen(datadir_buffer);
10495
10496 case_insensitive_fs = (test_if_case_insensitive(datadir_buffer) == 1);
10497
10498 if (!case_insensitive_fs) {
10499 if (!strncmp(datadir_buffer, opt_secure_file_priv,
10500 opt_datadir_len < opt_secure_file_priv_len
10501 ? opt_datadir_len
10502 : opt_secure_file_priv_len)) {
10503 warn = true;
10504 strcpy(whichdir, "Data directory");
10505 }
10506 } else {
10507 if (!files_charset_info->coll->strnncoll(
10508 files_charset_info, (uchar *)datadir_buffer, opt_datadir_len,
10509 pointer_cast<const uchar *>(opt_secure_file_priv),
10510 opt_secure_file_priv_len, true)) {
10511 warn = true;
10512 strcpy(whichdir, "Data directory");
10513 }
10514 }
10515
10516 /*
10517 Don't bother comparing --secure-file-priv with --plugin-dir
10518 if we already have a match against --datdir or
10519 --plugin-dir is not pointing to a valid directory.
10520 */
10521 if (!warn && !my_realpath(plugindir_buffer, opt_plugin_dir, 0)) {
10522 convert_dirname(plugindir_buffer, plugindir_buffer, NullS);
10523 opt_plugindir_len = strlen(plugindir_buffer);
10524
10525 if (!case_insensitive_fs) {
10526 if (!strncmp(plugindir_buffer, opt_secure_file_priv,
10527 opt_plugindir_len < opt_secure_file_priv_len
10528 ? opt_plugindir_len
10529 : opt_secure_file_priv_len)) {
10530 warn = true;
10531 strcpy(whichdir, "Plugin directory");
10532 }
10533 } else {
10534 if (!files_charset_info->coll->strnncoll(
10535 files_charset_info, (uchar *)plugindir_buffer, opt_plugindir_len,
10536 pointer_cast<const uchar *>(opt_secure_file_priv),
10537 opt_secure_file_priv_len, true)) {
10538 warn = true;
10539 strcpy(whichdir, "Plugin directory");
10540 }
10541 }
10542 }
10543
10544 if (warn)
10545 LogErr(WARNING_LEVEL, ER_SEC_FILE_PRIV_DIRECTORY_INSECURE, whichdir);
10546
10547 #ifndef _WIN32
10548 /*
10549 Check for --secure-file-priv directory's permission
10550 */
10551 if (!(my_stat(opt_secure_file_priv, &dir_stat, MYF(0)))) {
10552 LogErr(ERROR_LEVEL, ER_SEC_FILE_PRIV_CANT_STAT);
10553 return false;
10554 }
10555
10556 if (dir_stat.st_mode & S_IRWXO)
10557 LogErr(WARNING_LEVEL, ER_SEC_FILE_PRIV_DIRECTORY_PERMISSIONS);
10558 #endif
10559 return true;
10560 }
10561
fix_paths(void)10562 static int fix_paths(void) {
10563 char buff[FN_REFLEN];
10564 bool secure_file_priv_nonempty = false;
10565 convert_dirname(mysql_home, mysql_home, NullS);
10566 /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
10567 my_realpath(mysql_home, mysql_home, MYF(0));
10568 /* Ensure that mysql_home ends in FN_LIBCHAR */
10569 char *pos = strend(mysql_home);
10570 if (pos == mysql_home || pos[-1] != FN_LIBCHAR) {
10571 pos[0] = FN_LIBCHAR;
10572 pos[1] = 0;
10573 }
10574 convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
10575 convert_dirname(mysql_real_data_home, mysql_real_data_home, NullS);
10576 (void)my_load_path(mysql_home, mysql_home, ""); // Resolve current dir
10577 (void)my_load_path(mysql_real_data_home, mysql_real_data_home, mysql_home);
10578 (void)my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
10579
10580 convert_dirname(
10581 opt_plugin_dir,
10582 opt_plugin_dir_ptr ? opt_plugin_dir_ptr : get_relative_path(PLUGINDIR),
10583 NullS);
10584 (void)my_load_path(opt_plugin_dir, opt_plugin_dir, mysql_home);
10585 opt_plugin_dir_ptr = opt_plugin_dir;
10586
10587 my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
10588 mysql_unpacked_real_data_home_len = strlen(mysql_unpacked_real_data_home);
10589 if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len - 1] ==
10590 FN_LIBCHAR)
10591 --mysql_unpacked_real_data_home_len;
10592
10593 const char *sharedir = get_relative_path(SHAREDIR);
10594 if (test_if_hard_path(sharedir))
10595 strmake(buff, sharedir, sizeof(buff) - 1); /* purecov: tested */
10596 else
10597 strxnmov(buff, sizeof(buff) - 1, mysql_home, sharedir, NullS);
10598 convert_dirname(buff, buff, NullS);
10599 (void)my_load_path(lc_messages_dir, lc_messages_dir, buff);
10600
10601 /* If --character-sets-dir isn't given, use shared library dir */
10602 if (charsets_dir)
10603 strmake(mysql_charsets_dir, charsets_dir, sizeof(mysql_charsets_dir) - 1);
10604 else
10605 strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir) - 1, buff,
10606 CHARSET_DIR, NullS);
10607 (void)my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
10608 convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
10609 charsets_dir = mysql_charsets_dir;
10610
10611 if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) return 1;
10612 if (!opt_mysql_tmpdir) opt_mysql_tmpdir = mysql_tmpdir;
10613 if (!slave_load_tmpdir) slave_load_tmpdir = mysql_tmpdir;
10614
10615 if (opt_help) return 0;
10616 /*
10617 Convert the secure-file-priv option to system format, allowing
10618 a quick strcmp to check if read or write is in an allowed dir
10619 */
10620 if (opt_initialize) opt_secure_file_priv = "";
10621 secure_file_priv_nonempty = opt_secure_file_priv[0] ? true : false;
10622
10623 if (secure_file_priv_nonempty && strlen(opt_secure_file_priv) > FN_REFLEN) {
10624 LogErr(WARNING_LEVEL, ER_SEC_FILE_PRIV_ARGUMENT_TOO_LONG, FN_REFLEN - 1);
10625 return 1;
10626 }
10627
10628 memset(buff, 0, sizeof(buff));
10629 if (secure_file_priv_nonempty &&
10630 my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL")) {
10631 int retval = my_realpath(buff, opt_secure_file_priv, MYF(MY_WME));
10632 if (!retval) {
10633 convert_dirname(secure_file_real_path, buff, NullS);
10634 #ifdef WIN32
10635 MY_DIR *dir = my_dir(secure_file_real_path, MYF(MY_DONT_SORT + MY_WME));
10636 if (!dir) {
10637 retval = 1;
10638 } else {
10639 my_dirend(dir);
10640 }
10641 #endif
10642 }
10643
10644 if (retval) {
10645 LogErr(ERROR_LEVEL, ER_SEC_FILE_PRIV_CANT_ACCESS_DIR,
10646 opt_secure_file_priv);
10647 return 1;
10648 }
10649 opt_secure_file_priv = secure_file_real_path;
10650 }
10651
10652 if (!check_secure_file_priv_path()) return 1;
10653
10654 return 0;
10655 }
10656
10657 /**
10658 Check if file system used for databases is case insensitive.
10659
10660 @param dir_name Directory to test
10661
10662 @retval
10663 -1 Don't know (Test failed)
10664 @retval
10665 0 File system is case sensitive
10666 @retval
10667 1 File system is case insensitive
10668 */
10669
test_if_case_insensitive(const char * dir_name)10670 static int test_if_case_insensitive(const char *dir_name) {
10671 int result = 0;
10672 File file;
10673 char buff[FN_REFLEN], buff2[FN_REFLEN];
10674 MY_STAT stat_info;
10675 const char *const tmp_file_name = "mysqld_tmp_file_case_insensitive_test";
10676 DBUG_TRACE;
10677
10678 fn_format(buff, tmp_file_name, dir_name, ".lower-test",
10679 MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
10680 fn_format(buff2, tmp_file_name, dir_name, ".LOWER-TEST",
10681 MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
10682 mysql_file_delete(key_file_casetest, buff2, MYF(0));
10683 if ((file = mysql_file_create(key_file_casetest, buff, 0666, O_RDWR,
10684 MYF(0))) < 0) {
10685 LogErr(WARNING_LEVEL, ER_CANT_CREATE_TEST_FILE, buff);
10686 return -1;
10687 }
10688 mysql_file_close(file, MYF(0));
10689 if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
10690 result = 1; // Can access file
10691 mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
10692 DBUG_PRINT("exit", ("result: %d", result));
10693 return result;
10694 }
10695
10696 /**
10697 Create file to store pid number.
10698 */
create_pid_file()10699 static bool create_pid_file() {
10700 File file;
10701 bool check_parent_path = true, is_path_accessible = true;
10702 char pid_filepath[FN_REFLEN], *pos = nullptr;
10703 /* Copy pid file name to get pid file path */
10704 strcpy(pid_filepath, pidfile_name);
10705
10706 /* Iterate through the entire path to check if even one of the sub-dirs
10707 is world-writable */
10708 while (check_parent_path && (pos = strrchr(pid_filepath, FN_LIBCHAR)) &&
10709 (pos != pid_filepath)) /* shouldn't check root */
10710 {
10711 *pos = '\0'; /* Trim the inner-most dir */
10712 switch (is_file_or_dir_world_writable(pid_filepath)) {
10713 case -2:
10714 is_path_accessible = false;
10715 break;
10716 case -1:
10717 LogErr(ERROR_LEVEL, ER_CANT_CHECK_PID_PATH, strerror(errno));
10718 exit(MYSQLD_ABORT_EXIT);
10719 case 1:
10720 LogErr(WARNING_LEVEL, ER_PID_FILE_PRIV_DIRECTORY_INSECURE,
10721 pid_filepath);
10722 check_parent_path = false;
10723 break;
10724 case 0:
10725 continue; /* Keep checking the parent dir */
10726 }
10727 }
10728 if (!is_path_accessible) {
10729 LogErr(WARNING_LEVEL, ER_PID_FILEPATH_LOCATIONS_INACCESSIBLE);
10730 }
10731 if ((file = mysql_file_create(key_file_pid, pidfile_name, 0664,
10732 O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) {
10733 char buff[MAX_BIGINT_WIDTH + 1], *end;
10734 end = longlong10_to_str(getpid(), buff, -10);
10735 *end++ = '\n';
10736 if (!mysql_file_write(file, (uchar *)buff, (uint)(end - buff),
10737 MYF(MY_WME | MY_NABP))) {
10738 mysql_file_close(file, MYF(0));
10739 pid_file_created = true;
10740 return false;
10741 }
10742 mysql_file_close(file, MYF(0));
10743 }
10744 LogErr(ERROR_LEVEL, ER_CANT_CREATE_PID_FILE, strerror(errno));
10745 return true;
10746 }
10747
10748 /**
10749 Remove the process' pid file.
10750
10751 @param flags file operation flags
10752 */
10753
delete_pid_file(myf flags)10754 static void delete_pid_file(myf flags) {
10755 File file;
10756 if (opt_initialize || !pid_file_created ||
10757 !(file = mysql_file_open(key_file_pid, pidfile_name, O_RDONLY, flags)))
10758 return;
10759
10760 if (file == -1) {
10761 LogErr(INFORMATION_LEVEL, ER_CANT_REMOVE_PID_FILE, strerror(errno));
10762 return;
10763 }
10764
10765 uchar buff[MAX_BIGINT_WIDTH + 1];
10766 /* Make sure that the pid file was created by the same process. */
10767 size_t error = mysql_file_read(file, buff, sizeof(buff), flags);
10768 mysql_file_close(file, flags);
10769 buff[sizeof(buff) - 1] = '\0';
10770 if (error != MY_FILE_ERROR && atol((char *)buff) == (long)getpid()) {
10771 mysql_file_delete(key_file_pid, pidfile_name, flags);
10772 pid_file_created = false;
10773 }
10774 return;
10775 }
10776
10777 /**
10778 Delete mysql.ibd after aborting upgrade.
10779 */
delete_dictionary_tablespace()10780 static void delete_dictionary_tablespace() {
10781 char path[FN_REFLEN + 1];
10782 bool not_used;
10783
10784 build_table_filename(path, sizeof(path) - 1, "", "mysql", ".ibd", 0,
10785 ¬_used);
10786 (void)mysql_file_delete(key_file_misc, path, MYF(MY_WME));
10787
10788 // Drop file which tracks progress of upgrade.
10789 dd::upgrade_57::Upgrade_status().remove();
10790 }
10791
10792 /**
10793 Returns the current state of the server : booting, operational or shutting
10794 down.
10795
10796 @return
10797 SERVER_BOOTING Server is not operational. It is starting.
10798 SERVER_OPERATING Server is fully initialized and operating.
10799 SERVER_SHUTTING_DOWN Server is shutting down.
10800 */
get_server_state()10801 enum_server_operational_state get_server_state() {
10802 return server_operational_state;
10803 }
10804
10805 /**
10806 Reset status for all threads.
10807 */
10808 class Reset_thd_status : public Do_THD_Impl {
10809 public:
Reset_thd_status()10810 Reset_thd_status() {}
operator ()(THD * thd)10811 virtual void operator()(THD *thd) {
10812 /* Update the global status if not done so already. */
10813 if (!thd->status_var_aggregated) {
10814 add_to_status(&global_status_var, &thd->status_var);
10815 }
10816 reset_system_status_vars(&thd->status_var);
10817 }
10818 };
10819
10820 /**
10821 Reset global and session status variables.
10822 */
refresh_status()10823 void refresh_status() {
10824 mysql_mutex_lock(&LOCK_status);
10825
10826 /* For all threads, add status to global status and then reset. */
10827 Reset_thd_status reset_thd_status;
10828 Global_THD_manager::get_instance()->do_for_all_thd_copy(&reset_thd_status);
10829 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
10830 /* Reset aggregated status counters. */
10831 reset_pfs_status_stats();
10832 #endif
10833
10834 /* Reset some global variables. */
10835 reset_status_vars();
10836
10837 /* Reset the counters of all key caches (default and named). */
10838 process_key_caches(reset_key_cache_counters);
10839 flush_status_time = time((time_t *)nullptr);
10840 mysql_mutex_unlock(&LOCK_status);
10841
10842 /*
10843 Set max_used_connections to the number of currently open
10844 connections. Do this out of LOCK_status to avoid deadlocks.
10845 Status reset becomes not atomic, but status data is not exact anyway.
10846 */
10847 Connection_handler_manager::reset_max_used_connections();
10848 }
10849
10850 /*****************************************************************************
10851 Instantiate variables for missing storage engines
10852 This section should go away soon
10853 *****************************************************************************/
10854
10855 #ifdef HAVE_PSI_INTERFACE
10856 PSI_mutex_key key_LOCK_tc;
10857 PSI_mutex_key key_hash_filo_lock;
10858 PSI_mutex_key key_LOCK_error_log;
10859 PSI_mutex_key key_LOCK_thd_data;
10860 PSI_mutex_key key_LOCK_thd_sysvar;
10861 PSI_mutex_key key_LOCK_thd_protocol;
10862 PSI_mutex_key key_LOG_LOCK_log;
10863 PSI_mutex_key key_master_info_data_lock;
10864 PSI_mutex_key key_master_info_run_lock;
10865 PSI_mutex_key key_master_info_sleep_lock;
10866 PSI_mutex_key key_master_info_thd_lock;
10867 PSI_mutex_key key_master_info_rotate_lock;
10868 PSI_mutex_key key_mutex_slave_reporting_capability_err_lock;
10869 PSI_mutex_key key_relay_log_info_data_lock;
10870 PSI_mutex_key key_relay_log_info_sleep_lock;
10871 PSI_mutex_key key_relay_log_info_thd_lock;
10872 PSI_mutex_key key_relay_log_info_log_space_lock;
10873 PSI_mutex_key key_relay_log_info_run_lock;
10874 PSI_mutex_key key_mutex_slave_parallel_pend_jobs;
10875 PSI_mutex_key key_mutex_slave_parallel_worker_count;
10876 PSI_mutex_key key_mutex_slave_parallel_worker;
10877 PSI_mutex_key key_structure_guard_mutex;
10878 PSI_mutex_key key_TABLE_SHARE_LOCK_ha_data;
10879 PSI_mutex_key key_LOCK_query_plan;
10880 PSI_mutex_key key_LOCK_thd_query;
10881 PSI_mutex_key key_LOCK_cost_const;
10882 PSI_mutex_key key_LOCK_current_cond;
10883 PSI_mutex_key key_RELAYLOG_LOCK_commit;
10884 PSI_mutex_key key_RELAYLOG_LOCK_commit_queue;
10885 PSI_mutex_key key_RELAYLOG_LOCK_done;
10886 PSI_mutex_key key_RELAYLOG_LOCK_flush_queue;
10887 PSI_mutex_key key_RELAYLOG_LOCK_index;
10888 PSI_mutex_key key_RELAYLOG_LOCK_log;
10889 PSI_mutex_key key_RELAYLOG_LOCK_log_end_pos;
10890 PSI_mutex_key key_RELAYLOG_LOCK_sync;
10891 PSI_mutex_key key_RELAYLOG_LOCK_sync_queue;
10892 PSI_mutex_key key_RELAYLOG_LOCK_xids;
10893 PSI_mutex_key key_gtid_ensure_index_mutex;
10894 PSI_mutex_key key_object_cache_mutex; // TODO need to initialize
10895 PSI_cond_key key_object_loading_cond; // TODO need to initialize
10896 PSI_mutex_key key_mts_temp_table_LOCK;
10897 PSI_mutex_key key_mts_gaq_LOCK;
10898 PSI_mutex_key key_thd_timer_mutex;
10899 PSI_mutex_key key_commit_order_manager_mutex;
10900 PSI_mutex_key key_mutex_slave_worker_hash;
10901
10902 /* clang-format off */
10903 static PSI_mutex_info all_server_mutexes[]=
10904 {
10905 { &key_LOCK_tc, "TC_LOG_MMAP::LOCK_tc", 0, 0, PSI_DOCUMENT_ME},
10906 { &key_BINLOG_LOCK_commit, "MYSQL_BIN_LOG::LOCK_commit", 0, 0, PSI_DOCUMENT_ME},
10907 { &key_BINLOG_LOCK_commit_queue, "MYSQL_BIN_LOG::LOCK_commit_queue", 0, 0, PSI_DOCUMENT_ME},
10908 { &key_BINLOG_LOCK_done, "MYSQL_BIN_LOG::LOCK_done", 0, 0, PSI_DOCUMENT_ME},
10909 { &key_BINLOG_LOCK_flush_queue, "MYSQL_BIN_LOG::LOCK_flush_queue", 0, 0, PSI_DOCUMENT_ME},
10910 { &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0, 0, PSI_DOCUMENT_ME},
10911 { &key_BINLOG_LOCK_log, "MYSQL_BIN_LOG::LOCK_log", 0, 0, PSI_DOCUMENT_ME},
10912 { &key_BINLOG_LOCK_binlog_end_pos, "MYSQL_BIN_LOG::LOCK_binlog_end_pos", 0, 0, PSI_DOCUMENT_ME},
10913 { &key_BINLOG_LOCK_sync, "MYSQL_BIN_LOG::LOCK_sync", 0, 0, PSI_DOCUMENT_ME},
10914 { &key_BINLOG_LOCK_sync_queue, "MYSQL_BIN_LOG::LOCK_sync_queue", 0, 0, PSI_DOCUMENT_ME},
10915 { &key_BINLOG_LOCK_xids, "MYSQL_BIN_LOG::LOCK_xids", 0, 0, PSI_DOCUMENT_ME},
10916 { &key_RELAYLOG_LOCK_commit, "MYSQL_RELAY_LOG::LOCK_commit", 0, 0, PSI_DOCUMENT_ME},
10917 { &key_RELAYLOG_LOCK_commit_queue, "MYSQL_RELAY_LOG::LOCK_commit_queue", 0, 0, PSI_DOCUMENT_ME},
10918 { &key_RELAYLOG_LOCK_done, "MYSQL_RELAY_LOG::LOCK_done", 0, 0, PSI_DOCUMENT_ME},
10919 { &key_RELAYLOG_LOCK_flush_queue, "MYSQL_RELAY_LOG::LOCK_flush_queue", 0, 0, PSI_DOCUMENT_ME},
10920 { &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0, 0, PSI_DOCUMENT_ME},
10921 { &key_RELAYLOG_LOCK_log, "MYSQL_RELAY_LOG::LOCK_log", 0, 0, PSI_DOCUMENT_ME},
10922 { &key_RELAYLOG_LOCK_log_end_pos, "MYSQL_RELAY_LOG::LOCK_log_end_pos", 0, 0, PSI_DOCUMENT_ME},
10923 { &key_RELAYLOG_LOCK_sync, "MYSQL_RELAY_LOG::LOCK_sync", 0, 0, PSI_DOCUMENT_ME},
10924 { &key_RELAYLOG_LOCK_sync_queue, "MYSQL_RELAY_LOG::LOCK_sync_queue", 0, 0, PSI_DOCUMENT_ME},
10925 { &key_RELAYLOG_LOCK_xids, "MYSQL_RELAY_LOG::LOCK_xids", 0, 0, PSI_DOCUMENT_ME},
10926 { &key_hash_filo_lock, "hash_filo::lock", 0, 0, PSI_DOCUMENT_ME},
10927 { &Gtid_set::key_gtid_executed_free_intervals_mutex, "Gtid_set::gtid_executed::free_intervals_mutex", 0, 0, PSI_DOCUMENT_ME},
10928 { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10929 { &key_LOCK_error_log, "LOCK_error_log", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10930 { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10931 #if defined(_WIN32)
10932 { &key_LOCK_handler_count, "LOCK_handler_count", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10933 #endif
10934 { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10935 { &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10936 { &key_LOCK_sql_slave_skip_counter, "LOCK_sql_slave_skip_counter", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10937 { &key_LOCK_slave_net_timeout, "LOCK_slave_net_timeout", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10938 { &key_LOCK_slave_trans_dep_tracker, "LOCK_slave_trans_dep_tracker", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10939 { &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10940 #if !defined(_WIN32)
10941 { &key_LOCK_socket_listener_active, "LOCK_socket_listener_active", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10942 { &key_LOCK_start_signal_handler, "LOCK_start_signal_handler", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10943 #endif
10944 { &key_LOCK_status, "LOCK_status", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10945 { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10946 { &key_LOCK_thd_query, "THD::LOCK_thd_query", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10947 { &key_LOCK_thd_sysvar, "THD::LOCK_thd_sysvar", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10948 { &key_LOCK_thd_protocol, "THD::LOCK_thd_protocol", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10949 { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10950 { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10951 { &key_LOCK_sql_rand, "LOCK_sql_rand", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10952 { &key_LOG_LOCK_log, "LOG::LOCK_log", 0, 0, PSI_DOCUMENT_ME},
10953 { &key_master_info_data_lock, "Master_info::data_lock", 0, 0, PSI_DOCUMENT_ME},
10954 { &key_master_info_run_lock, "Master_info::run_lock", 0, 0, PSI_DOCUMENT_ME},
10955 { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0, 0, PSI_DOCUMENT_ME},
10956 { &key_master_info_thd_lock, "Master_info::info_thd_lock", 0, 0, PSI_DOCUMENT_ME},
10957 { &key_master_info_rotate_lock, "Master_info::rotate_lock", 0, 0, PSI_DOCUMENT_ME},
10958 { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0, 0, PSI_DOCUMENT_ME},
10959 { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0, 0, PSI_DOCUMENT_ME},
10960 { &key_relay_log_info_sleep_lock, "Relay_log_info::sleep_lock", 0, 0, PSI_DOCUMENT_ME},
10961 { &key_relay_log_info_thd_lock, "Relay_log_info::info_thd_lock", 0, 0, PSI_DOCUMENT_ME},
10962 { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0, 0, PSI_DOCUMENT_ME},
10963 { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0, 0, PSI_DOCUMENT_ME},
10964 { &key_mutex_slave_parallel_pend_jobs, "Relay_log_info::pending_jobs_lock", 0, 0, PSI_DOCUMENT_ME},
10965 { &key_mutex_slave_parallel_worker_count, "Relay_log_info::exit_count_lock", 0, 0, PSI_DOCUMENT_ME},
10966 { &key_mutex_slave_parallel_worker, "Worker_info::jobs_lock", 0, 0, PSI_DOCUMENT_ME},
10967 { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0, 0, PSI_DOCUMENT_ME},
10968 { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10969 { &key_LOCK_log_throttle_qni, "LOCK_log_throttle_qni", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10970 { &key_gtid_ensure_index_mutex, "Gtid_state", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10971 { &key_LOCK_query_plan, "THD::LOCK_query_plan", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10972 { &key_LOCK_cost_const, "Cost_constant_cache::LOCK_cost_const", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10973 { &key_LOCK_current_cond, "THD::LOCK_current_cond", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10974 { &key_mts_temp_table_LOCK, "key_mts_temp_table_LOCK", 0, 0, PSI_DOCUMENT_ME},
10975 { &key_LOCK_reset_gtid_table, "LOCK_reset_gtid_table", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10976 { &key_LOCK_compress_gtid_table, "LOCK_compress_gtid_table", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10977 { &key_LOCK_collect_instance_log, "LOCK_collect_instance_log", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10978 { &key_mts_gaq_LOCK, "key_mts_gaq_LOCK", 0, 0, PSI_DOCUMENT_ME},
10979 { &key_thd_timer_mutex, "thd_timer_mutex", 0, 0, PSI_DOCUMENT_ME},
10980 { &key_commit_order_manager_mutex, "Commit_order_manager::m_mutex", 0, 0, PSI_DOCUMENT_ME},
10981 { &key_mutex_slave_worker_hash, "Relay_log_info::slave_worker_hash_lock", 0, 0, PSI_DOCUMENT_ME},
10982 { &key_LOCK_default_password_lifetime, "LOCK_default_password_lifetime", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10983 { &key_LOCK_mandatory_roles, "LOCK_mandatory_roles", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10984 { &key_LOCK_password_history, "LOCK_password_history", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10985 { &key_LOCK_password_reuse_interval, "LOCK_password_reuse_interval", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10986 { &key_LOCK_keyring_operations, "LOCK_keyring_operations", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10987 { &key_LOCK_tls_ctx_options, "LOCK_tls_ctx_options", 0, 0, "A lock to control all of the --ssl-* CTX related command line options for client server connection port"},
10988 { &key_LOCK_admin_tls_ctx_options, "LOCK_admin_tls_ctx_options", 0, 0, "A lock to control all of the --ssl-* CTX related command line options for administrative connection port"},
10989 { &key_LOCK_rotate_binlog_master_key, "LOCK_rotate_binlog_master_key", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME}
10990 };
10991 /* clang-format on */
10992
10993 PSI_rwlock_key key_rwlock_LOCK_logger;
10994 PSI_rwlock_key key_rwlock_channel_map_lock;
10995 PSI_rwlock_key key_rwlock_channel_lock;
10996 PSI_rwlock_key key_rwlock_receiver_sid_lock;
10997 PSI_rwlock_key key_rwlock_rpl_filter_lock;
10998 PSI_rwlock_key key_rwlock_channel_to_filter_lock;
10999
11000 PSI_rwlock_key key_rwlock_Trans_delegate_lock;
11001 PSI_rwlock_key key_rwlock_Server_state_delegate_lock;
11002 PSI_rwlock_key key_rwlock_Binlog_storage_delegate_lock;
11003 PSI_rwlock_key key_rwlock_Binlog_transmit_delegate_lock;
11004 PSI_rwlock_key key_rwlock_Binlog_relay_IO_delegate_lock;
11005 PSI_rwlock_key key_rwlock_resource_group_mgr_map_lock;
11006
11007 /* clang-format off */
11008 static PSI_rwlock_info all_server_rwlocks[]=
11009 {
11010 { &key_rwlock_Binlog_transmit_delegate_lock, "Binlog_transmit_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11011 { &key_rwlock_Binlog_relay_IO_delegate_lock, "Binlog_relay_IO_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11012 { &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0, 0, PSI_DOCUMENT_ME},
11013 { &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11014 { &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11015 { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11016 { &key_rwlock_global_sid_lock, "gtid_commit_rollback", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11017 { &key_rwlock_gtid_mode_lock, "gtid_mode_lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11018 { &key_rwlock_channel_map_lock, "channel_map_lock", 0, 0, PSI_DOCUMENT_ME},
11019 { &key_rwlock_channel_lock, "channel_lock", 0, 0, PSI_DOCUMENT_ME},
11020 { &key_rwlock_Trans_delegate_lock, "Trans_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11021 { &key_rwlock_Server_state_delegate_lock, "Server_state_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11022 { &key_rwlock_Binlog_storage_delegate_lock, "Binlog_storage_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11023 { &key_rwlock_receiver_sid_lock, "gtid_retrieved", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11024 { &key_rwlock_rpl_filter_lock, "rpl_filter_lock", 0, 0, PSI_DOCUMENT_ME},
11025 { &key_rwlock_channel_to_filter_lock, "channel_to_filter_lock", 0, 0, PSI_DOCUMENT_ME},
11026 { &key_rwlock_resource_group_mgr_map_lock, "Resource_group_mgr::m_map_rwlock", 0, 0, PSI_DOCUMENT_ME},
11027 #ifdef _WIN32
11028 { &key_rwlock_LOCK_named_pipe_full_access_group, "LOCK_named_pipe_full_access_group", PSI_FLAG_SINGLETON, 0,
11029 "This lock protects named pipe security attributes, preventing their "
11030 "simultaneous application and modification."},
11031 #endif // _WIN32
11032 };
11033 /* clang-format on */
11034
11035 PSI_cond_key key_PAGE_cond;
11036 PSI_cond_key key_COND_active;
11037 PSI_cond_key key_COND_pool;
11038 PSI_cond_key key_COND_cache_status_changed;
11039 PSI_cond_key key_item_func_sleep_cond;
11040 PSI_cond_key key_master_info_data_cond;
11041 PSI_cond_key key_master_info_start_cond;
11042 PSI_cond_key key_master_info_stop_cond;
11043 PSI_cond_key key_master_info_sleep_cond;
11044 PSI_cond_key key_master_info_rotate_cond;
11045 PSI_cond_key key_relay_log_info_data_cond;
11046 PSI_cond_key key_relay_log_info_log_space_cond;
11047 PSI_cond_key key_relay_log_info_start_cond;
11048 PSI_cond_key key_relay_log_info_stop_cond;
11049 PSI_cond_key key_relay_log_info_sleep_cond;
11050 PSI_cond_key key_cond_slave_parallel_pend_jobs;
11051 PSI_cond_key key_cond_slave_parallel_worker;
11052 PSI_cond_key key_cond_mts_gaq;
11053 PSI_cond_key key_RELAYLOG_update_cond;
11054 PSI_cond_key key_RELAYLOG_COND_done;
11055 PSI_cond_key key_RELAYLOG_prep_xids_cond;
11056 PSI_cond_key key_gtid_ensure_index_cond;
11057 PSI_cond_key key_COND_thr_lock;
11058 PSI_cond_key key_commit_order_manager_cond;
11059 PSI_cond_key key_cond_slave_worker_hash;
11060
11061 /* clang-format off */
11062 static PSI_cond_info all_server_conds[]=
11063 {
11064 { &key_PAGE_cond, "PAGE::cond", 0, 0, PSI_DOCUMENT_ME},
11065 { &key_COND_active, "TC_LOG_MMAP::COND_active", 0, 0, PSI_DOCUMENT_ME},
11066 { &key_COND_pool, "TC_LOG_MMAP::COND_pool", 0, 0, PSI_DOCUMENT_ME},
11067 { &key_BINLOG_COND_done, "MYSQL_BIN_LOG::COND_done", 0, 0, PSI_DOCUMENT_ME},
11068 { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0, 0, PSI_DOCUMENT_ME},
11069 { &key_BINLOG_prep_xids_cond, "MYSQL_BIN_LOG::prep_xids_cond", 0, 0, PSI_DOCUMENT_ME},
11070 { &key_RELAYLOG_COND_done, "MYSQL_RELAY_LOG::COND_done", 0, 0, PSI_DOCUMENT_ME},
11071 { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0, 0, PSI_DOCUMENT_ME},
11072 { &key_RELAYLOG_prep_xids_cond, "MYSQL_RELAY_LOG::prep_xids_cond", 0, 0, PSI_DOCUMENT_ME},
11073 #if defined(_WIN32)
11074 { &key_COND_handler_count, "COND_handler_count", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11075 #endif
11076 { &key_COND_manager, "COND_manager", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11077 { &key_COND_server_started, "COND_server_started", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11078 #if !defined(_WIN32)
11079 { &key_COND_socket_listener_active, "COND_socket_listener_active", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11080 { &key_COND_start_signal_handler, "COND_start_signal_handler", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11081 #endif
11082 { &key_COND_thr_lock, "COND_thr_lock", 0, 0, PSI_DOCUMENT_ME},
11083 { &key_item_func_sleep_cond, "Item_func_sleep::cond", 0, 0, PSI_DOCUMENT_ME},
11084 { &key_master_info_data_cond, "Master_info::data_cond", 0, 0, PSI_DOCUMENT_ME},
11085 { &key_master_info_start_cond, "Master_info::start_cond", 0, 0, PSI_DOCUMENT_ME},
11086 { &key_master_info_stop_cond, "Master_info::stop_cond", 0, 0, PSI_DOCUMENT_ME},
11087 { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0, 0, PSI_DOCUMENT_ME},
11088 { &key_master_info_rotate_cond, "Master_info::rotate_cond", 0, 0, PSI_DOCUMENT_ME},
11089 { &key_relay_log_info_data_cond, "Relay_log_info::data_cond", 0, 0, PSI_DOCUMENT_ME},
11090 { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0, 0, PSI_DOCUMENT_ME},
11091 { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0, 0, PSI_DOCUMENT_ME},
11092 { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0, 0, PSI_DOCUMENT_ME},
11093 { &key_relay_log_info_sleep_cond, "Relay_log_info::sleep_cond", 0, 0, PSI_DOCUMENT_ME},
11094 { &key_cond_slave_parallel_pend_jobs, "Relay_log_info::pending_jobs_cond", 0, 0, PSI_DOCUMENT_ME},
11095 { &key_cond_slave_parallel_worker, "Worker_info::jobs_cond", 0, 0, PSI_DOCUMENT_ME},
11096 { &key_cond_mts_gaq, "Relay_log_info::mts_gaq_cond", 0, 0, PSI_DOCUMENT_ME},
11097 { &key_gtid_ensure_index_cond, "Gtid_state", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11098 { &key_COND_compress_gtid_table, "COND_compress_gtid_table", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11099 { &key_commit_order_manager_cond, "Commit_order_manager::m_workers.cond", 0, 0, PSI_DOCUMENT_ME},
11100 { &key_cond_slave_worker_hash, "Relay_log_info::slave_worker_hash_lock", 0, 0, PSI_DOCUMENT_ME}
11101 };
11102 /* clang-format on */
11103
11104 PSI_thread_key key_thread_bootstrap;
11105 PSI_thread_key key_thread_handle_manager;
11106 PSI_thread_key key_thread_one_connection;
11107 PSI_thread_key key_thread_compress_gtid_table;
11108 PSI_thread_key key_thread_parser_service;
11109 PSI_thread_key key_thread_handle_con_admin_sockets;
11110
11111 /* clang-format off */
11112 static PSI_thread_info all_server_threads[]=
11113 {
11114 #if defined (_WIN32)
11115 { &key_thread_handle_con_namedpipes, "con_named_pipes", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11116 { &key_thread_handle_con_sharedmem, "con_shared_mem", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11117 { &key_thread_handle_con_sockets, "con_sockets", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11118 { &key_thread_handle_shutdown_restart, "shutdown_restart", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11119 #endif /* _WIN32 */
11120 { &key_thread_bootstrap, "bootstrap", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11121 { &key_thread_handle_manager, "manager", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11122 { &key_thread_main, "main", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11123 { &key_thread_one_connection, "one_connection", PSI_FLAG_USER, 0, PSI_DOCUMENT_ME},
11124 { &key_thread_signal_hand, "signal_handler", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11125 { &key_thread_compress_gtid_table, "compress_gtid_table", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11126 { &key_thread_parser_service, "parser_service", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11127 { &key_thread_handle_con_admin_sockets, "admin_interface", PSI_FLAG_USER, 0, PSI_DOCUMENT_ME},
11128 };
11129 /* clang-format on */
11130
11131 PSI_file_key key_file_binlog;
11132 PSI_file_key key_file_binlog_index;
11133 PSI_file_key key_file_dbopt;
11134 PSI_file_key key_file_ERRMSG;
11135 PSI_file_key key_select_to_file;
11136 PSI_file_key key_file_fileparser;
11137 PSI_file_key key_file_frm;
11138 PSI_file_key key_file_load;
11139 PSI_file_key key_file_loadfile;
11140 PSI_file_key key_file_log_event_data;
11141 PSI_file_key key_file_log_event_info;
11142 PSI_file_key key_file_misc;
11143 PSI_file_key key_file_tclog;
11144 PSI_file_key key_file_trg;
11145 PSI_file_key key_file_trn;
11146 PSI_file_key key_file_init;
11147 PSI_file_key key_file_general_log;
11148 PSI_file_key key_file_slow_log;
11149 PSI_file_key key_file_relaylog;
11150 PSI_file_key key_file_relaylog_cache;
11151 PSI_file_key key_file_relaylog_index;
11152 PSI_file_key key_file_relaylog_index_cache;
11153 PSI_file_key key_file_sdi;
11154 PSI_file_key key_file_hash_join;
11155
11156 /* clang-format off */
11157 static PSI_file_info all_server_files[]=
11158 {
11159 { &key_file_binlog, "binlog", 0, 0, PSI_DOCUMENT_ME},
11160 { &key_file_binlog_cache, "binlog_cache", 0, 0, PSI_DOCUMENT_ME},
11161 { &key_file_binlog_index, "binlog_index", 0, 0, PSI_DOCUMENT_ME},
11162 { &key_file_binlog_index_cache, "binlog_index_cache", 0, 0, PSI_DOCUMENT_ME},
11163 { &key_file_relaylog, "relaylog", 0, 0, PSI_DOCUMENT_ME},
11164 { &key_file_relaylog_cache, "relaylog_cache", 0, 0, PSI_DOCUMENT_ME},
11165 { &key_file_relaylog_index, "relaylog_index", 0, 0, PSI_DOCUMENT_ME},
11166 { &key_file_relaylog_index_cache, "relaylog_index_cache", 0, 0, PSI_DOCUMENT_ME},
11167 { &key_file_io_cache, "io_cache", 0, 0, PSI_DOCUMENT_ME},
11168 { &key_file_casetest, "casetest", 0, 0, PSI_DOCUMENT_ME},
11169 { &key_file_dbopt, "dbopt", 0, 0, PSI_DOCUMENT_ME},
11170 { &key_file_ERRMSG, "ERRMSG", 0, 0, PSI_DOCUMENT_ME},
11171 { &key_select_to_file, "select_to_file", 0, 0, PSI_DOCUMENT_ME},
11172 { &key_file_fileparser, "file_parser", 0, 0, PSI_DOCUMENT_ME},
11173 { &key_file_frm, "FRM", 0, 0, PSI_DOCUMENT_ME},
11174 { &key_file_load, "load", 0, 0, PSI_DOCUMENT_ME},
11175 { &key_file_loadfile, "LOAD_FILE", 0, 0, PSI_DOCUMENT_ME},
11176 { &key_file_log_event_data, "log_event_data", 0, 0, PSI_DOCUMENT_ME},
11177 { &key_file_log_event_info, "log_event_info", 0, 0, PSI_DOCUMENT_ME},
11178 { &key_file_misc, "misc", 0, 0, PSI_DOCUMENT_ME},
11179 { &key_file_pid, "pid", 0, 0, PSI_DOCUMENT_ME},
11180 { &key_file_general_log, "query_log", 0, 0, PSI_DOCUMENT_ME},
11181 { &key_file_slow_log, "slow_log", 0, 0, PSI_DOCUMENT_ME},
11182 { &key_file_tclog, "tclog", 0, 0, PSI_DOCUMENT_ME},
11183 { &key_file_trg, "trigger_name", 0, 0, PSI_DOCUMENT_ME},
11184 { &key_file_trn, "trigger", 0, 0, PSI_DOCUMENT_ME},
11185 { &key_file_init, "init", 0, 0, PSI_DOCUMENT_ME},
11186 { &key_file_sdi, "SDI", 0, 0, PSI_DOCUMENT_ME},
11187 { &key_file_hash_join, "hash_join", 0, 0, PSI_DOCUMENT_ME}
11188 };
11189 /* clang-format on */
11190 #endif /* HAVE_PSI_INTERFACE */
11191
11192 /* clang-format off */
11193 PSI_stage_info stage_after_create= { 0, "After create", 0, PSI_DOCUMENT_ME};
11194 PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0, PSI_DOCUMENT_ME};
11195 PSI_stage_info stage_alter_inplace= { 0, "altering table", 0, PSI_DOCUMENT_ME};
11196 PSI_stage_info stage_alter_inplace_commit= { 0, "committing alter table to storage engine", 0, PSI_DOCUMENT_ME};
11197 PSI_stage_info stage_changing_master= { 0, "Changing master", 0, PSI_DOCUMENT_ME};
11198 PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0, PSI_DOCUMENT_ME};
11199 PSI_stage_info stage_checking_permissions= { 0, "checking permissions", 0, PSI_DOCUMENT_ME};
11200 PSI_stage_info stage_cleaning_up= { 0, "cleaning up", 0, PSI_DOCUMENT_ME};
11201 PSI_stage_info stage_closing_tables= { 0, "closing tables", 0, PSI_DOCUMENT_ME};
11202 PSI_stage_info stage_compressing_gtid_table= { 0, "Compressing gtid_executed table", 0, PSI_DOCUMENT_ME};
11203 PSI_stage_info stage_connecting_to_master= { 0, "Connecting to master", 0, PSI_DOCUMENT_ME};
11204 PSI_stage_info stage_converting_heap_to_ondisk= { 0, "converting HEAP to ondisk", 0, PSI_DOCUMENT_ME};
11205 PSI_stage_info stage_copy_to_tmp_table= { 0, "copy to tmp table", PSI_FLAG_STAGE_PROGRESS, PSI_DOCUMENT_ME};
11206 PSI_stage_info stage_creating_table= { 0, "creating table", 0, PSI_DOCUMENT_ME};
11207 PSI_stage_info stage_creating_tmp_table= { 0, "Creating tmp table", 0, PSI_DOCUMENT_ME};
11208 PSI_stage_info stage_deleting_from_main_table= { 0, "deleting from main table", 0, PSI_DOCUMENT_ME};
11209 PSI_stage_info stage_deleting_from_reference_tables= { 0, "deleting from reference tables", 0, PSI_DOCUMENT_ME};
11210 PSI_stage_info stage_discard_or_import_tablespace= { 0, "discard_or_import_tablespace", 0, PSI_DOCUMENT_ME};
11211 PSI_stage_info stage_end= { 0, "end", 0, PSI_DOCUMENT_ME};
11212 PSI_stage_info stage_executing= { 0, "executing", 0, PSI_DOCUMENT_ME};
11213 PSI_stage_info stage_execution_of_init_command= { 0, "Execution of init_command", 0, PSI_DOCUMENT_ME};
11214 PSI_stage_info stage_explaining= { 0, "explaining", 0, PSI_DOCUMENT_ME};
11215 PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog= { 0, "Finished reading one binlog; switching to next binlog", 0, PSI_DOCUMENT_ME};
11216 PSI_stage_info stage_flushing_relay_log_and_master_info_repository= { 0, "Flushing relay log and master info repository.", 0, PSI_DOCUMENT_ME};
11217 PSI_stage_info stage_flushing_relay_log_info_file= { 0, "Flushing relay-log info file.", 0, PSI_DOCUMENT_ME};
11218 PSI_stage_info stage_freeing_items= { 0, "freeing items", 0, PSI_DOCUMENT_ME};
11219 PSI_stage_info stage_fulltext_initialization= { 0, "FULLTEXT initialization", 0, PSI_DOCUMENT_ME};
11220 PSI_stage_info stage_init= { 0, "init", 0, PSI_DOCUMENT_ME};
11221 PSI_stage_info stage_killing_slave= { 0, "Killing slave", 0, PSI_DOCUMENT_ME};
11222 PSI_stage_info stage_logging_slow_query= { 0, "logging slow query", 0, PSI_DOCUMENT_ME};
11223 PSI_stage_info stage_making_temp_file_append_before_load_data= { 0, "Making temporary file (append) before replaying LOAD DATA INFILE", 0, PSI_DOCUMENT_ME};
11224 PSI_stage_info stage_manage_keys= { 0, "manage keys", 0, PSI_DOCUMENT_ME};
11225 PSI_stage_info stage_master_has_sent_all_binlog_to_slave= { 0, "Master has sent all binlog to slave; waiting for more updates", 0, PSI_DOCUMENT_ME};
11226 PSI_stage_info stage_opening_tables= { 0, "Opening tables", 0, PSI_DOCUMENT_ME};
11227 PSI_stage_info stage_optimizing= { 0, "optimizing", 0, PSI_DOCUMENT_ME};
11228 PSI_stage_info stage_preparing= { 0, "preparing", 0, PSI_DOCUMENT_ME};
11229 PSI_stage_info stage_purging_old_relay_logs= { 0, "Purging old relay logs", 0, PSI_DOCUMENT_ME};
11230 PSI_stage_info stage_query_end= { 0, "query end", 0, PSI_DOCUMENT_ME};
11231 PSI_stage_info stage_queueing_master_event_to_the_relay_log= { 0, "Queueing master event to the relay log", 0, PSI_DOCUMENT_ME};
11232 PSI_stage_info stage_reading_event_from_the_relay_log= { 0, "Reading event from the relay log", 0, PSI_DOCUMENT_ME};
11233 PSI_stage_info stage_registering_slave_on_master= { 0, "Registering slave on master", 0, PSI_DOCUMENT_ME};
11234 PSI_stage_info stage_removing_tmp_table= { 0, "removing tmp table", 0, PSI_DOCUMENT_ME};
11235 PSI_stage_info stage_rename= { 0, "rename", 0, PSI_DOCUMENT_ME};
11236 PSI_stage_info stage_rename_result_table= { 0, "rename result table", 0, PSI_DOCUMENT_ME};
11237 PSI_stage_info stage_requesting_binlog_dump= { 0, "Requesting binlog dump", 0, PSI_DOCUMENT_ME};
11238 PSI_stage_info stage_searching_rows_for_update= { 0, "Searching rows for update", 0, PSI_DOCUMENT_ME};
11239 PSI_stage_info stage_sending_binlog_event_to_slave= { 0, "Sending binlog event to slave", 0, PSI_DOCUMENT_ME};
11240 PSI_stage_info stage_setup= { 0, "setup", 0, PSI_DOCUMENT_ME};
11241 PSI_stage_info stage_slave_has_read_all_relay_log= { 0, "Slave has read all relay log; waiting for more updates", 0, PSI_DOCUMENT_ME};
11242 PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0, PSI_DOCUMENT_ME};
11243 PSI_stage_info stage_slave_waiting_for_workers_to_process_queue= { 0, "Waiting for slave workers to process their queues", 0, PSI_DOCUMENT_ME};
11244 PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0, PSI_DOCUMENT_ME};
11245 PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0, PSI_DOCUMENT_ME};
11246 PSI_stage_info stage_slave_waiting_worker_to_release_partition= { 0, "Waiting for Slave Worker to release partition", 0, PSI_DOCUMENT_ME};
11247 PSI_stage_info stage_slave_waiting_workers_to_exit= { 0, "Waiting for workers to exit", 0, PSI_DOCUMENT_ME};
11248 PSI_stage_info stage_rpl_apply_row_evt_write= { 0, "Applying batch of row changes (write)", PSI_FLAG_STAGE_PROGRESS, PSI_DOCUMENT_ME};
11249 PSI_stage_info stage_rpl_apply_row_evt_update= { 0, "Applying batch of row changes (update)", PSI_FLAG_STAGE_PROGRESS, PSI_DOCUMENT_ME};
11250 PSI_stage_info stage_rpl_apply_row_evt_delete= { 0, "Applying batch of row changes (delete)", PSI_FLAG_STAGE_PROGRESS, PSI_DOCUMENT_ME};
11251 PSI_stage_info stage_statistics= { 0, "statistics", 0, PSI_DOCUMENT_ME};
11252 PSI_stage_info stage_sql_thd_waiting_until_delay= { 0, "Waiting until MASTER_DELAY seconds after master executed event", 0, PSI_DOCUMENT_ME};
11253 PSI_stage_info stage_system_lock= { 0, "System lock", 0, PSI_DOCUMENT_ME};
11254 PSI_stage_info stage_update= { 0, "update", 0, PSI_DOCUMENT_ME};
11255 PSI_stage_info stage_updating= { 0, "updating", 0, PSI_DOCUMENT_ME};
11256 PSI_stage_info stage_updating_main_table= { 0, "updating main table", 0, PSI_DOCUMENT_ME};
11257 PSI_stage_info stage_updating_reference_tables= { 0, "updating reference tables", 0, PSI_DOCUMENT_ME};
11258 PSI_stage_info stage_user_sleep= { 0, "User sleep", 0, PSI_DOCUMENT_ME};
11259 PSI_stage_info stage_verifying_table= { 0, "verifying table", 0, PSI_DOCUMENT_ME};
11260 PSI_stage_info stage_waiting_for_gtid_to_be_committed= { 0, "Waiting for GTID to be committed", 0, PSI_DOCUMENT_ME};
11261 PSI_stage_info stage_waiting_for_handler_commit= { 0, "waiting for handler commit", 0, PSI_DOCUMENT_ME};
11262 PSI_stage_info stage_waiting_for_master_to_send_event= { 0, "Waiting for master to send event", 0, PSI_DOCUMENT_ME};
11263 PSI_stage_info stage_waiting_for_master_update= { 0, "Waiting for master update", 0, PSI_DOCUMENT_ME};
11264 PSI_stage_info stage_waiting_for_relay_log_space= { 0, "Waiting for the slave SQL thread to free enough relay log space", 0, PSI_DOCUMENT_ME};
11265 PSI_stage_info stage_waiting_for_slave_mutex_on_exit= { 0, "Waiting for slave mutex on exit", 0, PSI_DOCUMENT_ME};
11266 PSI_stage_info stage_waiting_for_slave_thread_to_start= { 0, "Waiting for slave thread to start", 0, PSI_DOCUMENT_ME};
11267 PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0, PSI_DOCUMENT_ME};
11268 PSI_stage_info stage_waiting_for_the_next_event_in_relay_log= { 0, "Waiting for the next event in relay log", 0, PSI_DOCUMENT_ME};
11269 PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position= { 0, "Waiting for the slave SQL thread to advance position", 0, PSI_DOCUMENT_ME};
11270 PSI_stage_info stage_waiting_to_finalize_termination= { 0, "Waiting to finalize termination", 0, PSI_DOCUMENT_ME};
11271 PSI_stage_info stage_worker_waiting_for_its_turn_to_commit= { 0, "Waiting for preceding transaction to commit", 0, PSI_DOCUMENT_ME};
11272 PSI_stage_info stage_worker_waiting_for_commit_parent= { 0, "Waiting for dependent transaction to commit", 0, PSI_DOCUMENT_ME};
11273 PSI_stage_info stage_suspending= { 0, "Suspending", 0, PSI_DOCUMENT_ME};
11274 PSI_stage_info stage_starting= { 0, "starting", 0, PSI_DOCUMENT_ME};
11275 PSI_stage_info stage_waiting_for_no_channel_reference= { 0, "Waiting for no channel reference.", 0, PSI_DOCUMENT_ME};
11276 PSI_stage_info stage_hook_begin_trans= { 0, "Executing hook on transaction begin.", 0, PSI_DOCUMENT_ME};
11277 PSI_stage_info stage_binlog_transaction_compress= { 0, "Compressing transaction changes.", 0, PSI_DOCUMENT_ME};
11278 PSI_stage_info stage_binlog_transaction_decompress= { 0, "Decompressing transaction changes.", 0, PSI_DOCUMENT_ME};
11279 /* clang-format on */
11280
11281 extern PSI_stage_info stage_waiting_for_disk_space;
11282
11283 #ifdef HAVE_PSI_INTERFACE
11284
11285 PSI_stage_info *all_server_stages[] = {
11286 &stage_after_create,
11287 &stage_alter_inplace_prepare,
11288 &stage_alter_inplace,
11289 &stage_alter_inplace_commit,
11290 &stage_changing_master,
11291 &stage_checking_master_version,
11292 &stage_checking_permissions,
11293 &stage_cleaning_up,
11294 &stage_closing_tables,
11295 &stage_compressing_gtid_table,
11296 &stage_connecting_to_master,
11297 &stage_converting_heap_to_ondisk,
11298 &stage_copy_to_tmp_table,
11299 &stage_creating_table,
11300 &stage_creating_tmp_table,
11301 &stage_deleting_from_main_table,
11302 &stage_deleting_from_reference_tables,
11303 &stage_discard_or_import_tablespace,
11304 &stage_end,
11305 &stage_executing,
11306 &stage_execution_of_init_command,
11307 &stage_explaining,
11308 &stage_finished_reading_one_binlog_switching_to_next_binlog,
11309 &stage_flushing_relay_log_and_master_info_repository,
11310 &stage_flushing_relay_log_info_file,
11311 &stage_freeing_items,
11312 &stage_fulltext_initialization,
11313 &stage_init,
11314 &stage_killing_slave,
11315 &stage_logging_slow_query,
11316 &stage_making_temp_file_append_before_load_data,
11317 &stage_manage_keys,
11318 &stage_master_has_sent_all_binlog_to_slave,
11319 &stage_opening_tables,
11320 &stage_optimizing,
11321 &stage_preparing,
11322 &stage_purging_old_relay_logs,
11323 &stage_query_end,
11324 &stage_queueing_master_event_to_the_relay_log,
11325 &stage_reading_event_from_the_relay_log,
11326 &stage_registering_slave_on_master,
11327 &stage_removing_tmp_table,
11328 &stage_rename,
11329 &stage_rename_result_table,
11330 &stage_requesting_binlog_dump,
11331 &stage_searching_rows_for_update,
11332 &stage_sending_binlog_event_to_slave,
11333 &stage_setup,
11334 &stage_slave_has_read_all_relay_log,
11335 &stage_slave_waiting_event_from_coordinator,
11336 &stage_slave_waiting_for_workers_to_process_queue,
11337 &stage_slave_waiting_worker_queue,
11338 &stage_slave_waiting_worker_to_free_events,
11339 &stage_slave_waiting_worker_to_release_partition,
11340 &stage_slave_waiting_workers_to_exit,
11341 &stage_rpl_apply_row_evt_write,
11342 &stage_rpl_apply_row_evt_update,
11343 &stage_rpl_apply_row_evt_delete,
11344 &stage_sql_thd_waiting_until_delay,
11345 &stage_statistics,
11346 &stage_system_lock,
11347 &stage_update,
11348 &stage_updating,
11349 &stage_updating_main_table,
11350 &stage_updating_reference_tables,
11351 &stage_user_sleep,
11352 &stage_verifying_table,
11353 &stage_waiting_for_gtid_to_be_committed,
11354 &stage_waiting_for_handler_commit,
11355 &stage_waiting_for_master_to_send_event,
11356 &stage_waiting_for_master_update,
11357 &stage_waiting_for_relay_log_space,
11358 &stage_waiting_for_slave_mutex_on_exit,
11359 &stage_waiting_for_slave_thread_to_start,
11360 &stage_waiting_for_table_flush,
11361 &stage_waiting_for_the_next_event_in_relay_log,
11362 &stage_waiting_for_the_slave_thread_to_advance_position,
11363 &stage_waiting_to_finalize_termination,
11364 &stage_worker_waiting_for_its_turn_to_commit,
11365 &stage_worker_waiting_for_commit_parent,
11366 &stage_suspending,
11367 &stage_starting,
11368 &stage_waiting_for_no_channel_reference,
11369 &stage_hook_begin_trans,
11370 &stage_waiting_for_disk_space,
11371 &stage_binlog_transaction_compress,
11372 &stage_binlog_transaction_decompress};
11373
11374 PSI_socket_key key_socket_tcpip;
11375 PSI_socket_key key_socket_unix;
11376 PSI_socket_key key_socket_client_connection;
11377
11378 /* clang-format off */
11379 static PSI_socket_info all_server_sockets[]=
11380 {
11381 { &key_socket_tcpip, "server_tcpip_socket", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11382 { &key_socket_unix, "server_unix_socket", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11383 { &key_socket_client_connection, "client_connection", PSI_FLAG_USER, 0, PSI_DOCUMENT_ME}
11384 };
11385 /* clang-format on */
11386
11387 /* TODO: find a good header */
11388 void init_client_psi_keys(void);
11389
11390 /**
11391 Initialise all the performance schema instrumentation points
11392 used by the server.
11393 */
init_server_psi_keys(void)11394 static void init_server_psi_keys(void) {
11395 const char *category = "sql";
11396 int count;
11397
11398 count = static_cast<int>(array_elements(all_server_mutexes));
11399 mysql_mutex_register(category, all_server_mutexes, count);
11400
11401 count = static_cast<int>(array_elements(all_server_rwlocks));
11402 mysql_rwlock_register(category, all_server_rwlocks, count);
11403
11404 count = static_cast<int>(array_elements(all_server_conds));
11405 mysql_cond_register(category, all_server_conds, count);
11406
11407 count = static_cast<int>(array_elements(all_server_threads));
11408 mysql_thread_register(category, all_server_threads, count);
11409
11410 count = static_cast<int>(array_elements(all_server_files));
11411 mysql_file_register(category, all_server_files, count);
11412
11413 count = static_cast<int>(array_elements(all_server_stages));
11414 mysql_stage_register(category, all_server_stages, count);
11415
11416 count = static_cast<int>(array_elements(all_server_sockets));
11417 mysql_socket_register(category, all_server_sockets, count);
11418
11419 register_server_memory_keys();
11420
11421 #ifdef HAVE_PSI_STATEMENT_INTERFACE
11422 init_sql_statement_info();
11423
11424 /* Register [0 .. SQLCOM_CLONE - 1] as "statement/sql/..." */
11425 count = (int)SQLCOM_CLONE;
11426 mysql_statement_register(category, sql_statement_info, count);
11427
11428 /* Exclude SQLCOM_CLONE as it mutates and is registered as abstract. */
11429 count = (int)SQLCOM_END - (int)SQLCOM_CLONE;
11430 mysql_statement_register(category, &sql_statement_info[(int)SQLCOM_CLONE + 1],
11431 count);
11432 category = "abstract";
11433 mysql_statement_register(category, &sql_statement_info[(int)SQLCOM_CLONE], 1);
11434
11435 init_sp_psi_keys();
11436
11437 init_scheduler_psi_keys();
11438
11439 category = "com";
11440 init_com_statement_info();
11441
11442 /*
11443 Register [0 .. COM_QUERY - 1] as "statement/com/..."
11444 */
11445 count = (int)COM_QUERY;
11446 mysql_statement_register(category, com_statement_info, count);
11447
11448 /* Exclude COM_CLONE as it would mutate */
11449 count = (int)COM_CLONE - (int)COM_QUERY - 1;
11450 mysql_statement_register(category, &com_statement_info[(int)COM_QUERY + 1],
11451 count);
11452 /*
11453 Register [COM_CLONE + 1 .. COM_END] as "statement/com/..."
11454 */
11455 count = (int)COM_END - (int)COM_CLONE;
11456 mysql_statement_register(category, &com_statement_info[(int)COM_CLONE + 1],
11457 count);
11458 category = "abstract";
11459 /*
11460 Register [COM_QUERY] as "statement/abstract/com_query"
11461 */
11462 mysql_statement_register(category, &com_statement_info[(int)COM_QUERY], 1);
11463 mysql_statement_register(category, &com_statement_info[(int)COM_CLONE], 1);
11464
11465 /*
11466 When a new packet is received,
11467 it is instrumented as "statement/abstract/new_packet".
11468 Based on the packet type found, it later mutates to the
11469 proper narrow type, for example
11470 "statement/abstract/query" or "statement/com/ping".
11471 In cases of "statement/abstract/query", SQL queries are given to
11472 the parser, which mutates the statement type to an even more
11473 narrow classification, for example "statement/sql/select".
11474 */
11475 stmt_info_new_packet.m_key = 0;
11476 stmt_info_new_packet.m_name = "new_packet";
11477 stmt_info_new_packet.m_flags = PSI_FLAG_MUTABLE;
11478 stmt_info_new_packet.m_documentation =
11479 "New packet just received from the network. "
11480 "At this point, the real command type is unknown, "
11481 "the type will be refined after reading the packet header.";
11482 mysql_statement_register(category, &stmt_info_new_packet, 1);
11483
11484 /*
11485 Statements processed from the relay log are initially instrumented as
11486 "statement/abstract/relay_log". The parser will mutate the statement type to
11487 a more specific classification, for example "statement/sql/insert".
11488 */
11489 stmt_info_rpl.m_key = 0;
11490 stmt_info_rpl.m_name = "relay_log";
11491 stmt_info_rpl.m_flags = PSI_FLAG_MUTABLE;
11492 stmt_info_rpl.m_documentation =
11493 "New event just read from the relay log. "
11494 "At this point, the real statement type is unknown, "
11495 "the type will be refined after parsing the event.";
11496 mysql_statement_register(category, &stmt_info_rpl, 1);
11497 #endif
11498
11499 /* Common client and server code. */
11500 init_client_psi_keys();
11501 /* Vio */
11502 init_vio_psi_keys();
11503 /* TLS interfaces */
11504 init_tls_psi_keys();
11505 }
11506 #endif /* HAVE_PSI_INTERFACE */
11507
do_create_native_table_for_pfs(THD * thd,const Plugin_table * t)11508 bool do_create_native_table_for_pfs(THD *thd, const Plugin_table *t) {
11509 const char *schema_name = t->get_schema_name();
11510 const char *table_name = t->get_name();
11511 MDL_request table_request;
11512 MDL_REQUEST_INIT(&table_request, MDL_key::TABLE, schema_name, table_name,
11513 MDL_EXCLUSIVE, MDL_TRANSACTION);
11514
11515 if (thd->mdl_context.acquire_lock(&table_request,
11516 thd->variables.lock_wait_timeout)) {
11517 /* Error, failed to get MDL lock. */
11518 return true;
11519 }
11520
11521 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, schema_name, table_name, false);
11522
11523 if (dd::create_native_table(thd, t)) {
11524 /* Error, failed to create DD table. */
11525 return true;
11526 }
11527
11528 return false;
11529 }
11530
create_native_table_for_pfs(const Plugin_table * t)11531 bool create_native_table_for_pfs(const Plugin_table *t) {
11532 /* If InnoDB is not initialized yet, return error */
11533 if (!is_builtin_and_core_se_initialized()) return true;
11534
11535 THD *thd = current_thd;
11536 DBUG_ASSERT(thd);
11537 return do_create_native_table_for_pfs(thd, t);
11538 }
11539
do_drop_native_table_for_pfs(THD * thd,const char * schema_name,const char * table_name)11540 static bool do_drop_native_table_for_pfs(THD *thd, const char *schema_name,
11541 const char *table_name) {
11542 MDL_request table_request;
11543 MDL_REQUEST_INIT(&table_request, MDL_key::TABLE, schema_name, table_name,
11544 MDL_EXCLUSIVE, MDL_TRANSACTION);
11545
11546 if (thd->mdl_context.acquire_lock(&table_request,
11547 thd->variables.lock_wait_timeout)) {
11548 /* Error, failed to get MDL lock. */
11549 return true;
11550 }
11551
11552 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, schema_name, table_name, false);
11553
11554 if (dd::drop_native_table(thd, schema_name, table_name)) {
11555 /* Error, failed to destroy DD table. */
11556 return true;
11557 }
11558
11559 return false;
11560 }
11561
drop_native_table_for_pfs(const char * schema_name,const char * table_name)11562 bool drop_native_table_for_pfs(const char *schema_name,
11563 const char *table_name) {
11564 /* If server is shutting down, by the time control reaches here, DD would have
11565 * already been shut down. Therefore return success and tables won't be
11566 * deleted and would be available at next server start.
11567 */
11568 if (get_server_state() == SERVER_SHUTTING_DOWN) {
11569 return false;
11570 }
11571
11572 /* During bootstrap error cleanup, we don't have THD. */
11573 THD *thd = current_thd;
11574 if (thd == nullptr) {
11575 DBUG_ASSERT(get_server_state() == SERVER_BOOTING);
11576 return false;
11577 }
11578 return do_drop_native_table_for_pfs(thd, schema_name, table_name);
11579 }
11580
11581 #ifdef _WIN32
11582 // update_named_pipe_full_access_group returns false on success, true on failure
update_named_pipe_full_access_group(const char * new_group_name)11583 bool update_named_pipe_full_access_group(const char *new_group_name) {
11584 if (named_pipe_acceptor) {
11585 return named_pipe_listener->update_named_pipe_full_access_group(
11586 new_group_name);
11587 }
11588 return true;
11589 }
11590
11591 #endif // _WIN32
11592
11593 /**
11594 Get status partial_revokes on server
11595
11596 @return a bool indicating partial_revokes status of the server.
11597 @retval true Parital revokes is ON
11598 @retval flase Partial revokes is OFF
11599 */
mysqld_partial_revokes()11600 bool mysqld_partial_revokes() {
11601 return partial_revokes.load(std::memory_order_relaxed);
11602 }
11603
11604 /**
11605 Set partial_revokes with a given value
11606
11607 @param value true or false indicating the status of partial revokes
11608 turned ON/OFF on server.
11609 */
set_mysqld_partial_revokes(bool value)11610 void set_mysqld_partial_revokes(bool value) {
11611 partial_revokes.store(value, std::memory_order_relaxed);
11612 }
11613
11614 /**
11615 Set m_opt_tracking_mode with a user given value associated with sysvar.
11616 */
set_mysqld_opt_tracking_mode()11617 void set_mysqld_opt_tracking_mode() {
11618 mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode.store(
11619 mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode_value,
11620 std::memory_order_relaxed);
11621 }
11622