Connection Manager for MySQL source code learning

Source: Internet
Author: User

MySQLDatabaseConnection ManagerThe related knowledge is what we will introduce in this article. Let's take a look at it.

1. Number of connected threads

MySQL supports single-thread and multi-thread connection threads. If it is a single thread, only one connection can be connected to MySQL at the same time, and other connections will be suspended. For multithreading, multiple connections can be connected to the server at the same time. You can set the number of connection threads by setting the server startup parameters:

 
 
  1. mysqld.exe --thread-handling=no-threads  
  2. mysqld.exe --thread-handling=one-thread-per-connection 

How does the server choose which method to use through parameters? Check the branch code on the server:

 
 
  1. #ifdef EMBEDDED_LIBRARY  
  2. one_thread_scheduler(&thread_scheduler);  
  3. #else  
  4. if (global_system_variables.thread_handling <=  
  5. SCHEDULER_ONE_THREAD_PER_CONNECTION)  
  6. one_thread_per_connection_scheduler(&thread_scheduler);  
  7. else if (global_system_variables.thread_handling == SCHEDULER_NO_THREADS)  
  8. one_thread_scheduler(&thread_scheduler);  
  9. else  
  10. pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */  
  11. #endif 

This code appears in the get_options function. This function sets the mode of corresponding parameters based on the input server parameters. From this code, we can see that if the EMBEDDED_LIBRARY macro definition is defined (it should be embedded), one_thread_scheduler is called to use a single thread. If the parameter is smaller than or equal to SCHEDULER_ONE_THREAD_PER_CONNECTION, one_thread_per_connection_scheduler is called, that is, each connection has one thread, that is, multiple threads.

How do I set global_system_variables.thread_handling? In fact, it is set based on the parameter -- thread-handling passed to the server. The parameter settings are unified in the get_options function. It calls mysqld_get_one_option, which has a branch and the code is as follows:

 
 
  1. case OPT_THREAD_HANDLING:  
  2. {  
  3. global_system_variables.thread_handling=  
  4. find_type_or_exit(argument, &thread_handling_typelib, opt->name)-1;  
  5. break;  

If you are interested in parameter initialization, you can refer to the get_options function in detail. Let's take a look at the source code of one_thread_scheduler and one_thread_per_connection_scheduler. What have they done?

 
 
  1. void one_thread_scheduler(scheduler_functions* func)  
  2. {  
  3. func->max_threads= 1;  
  4. #ifndef EMBEDDED_LIBRARY  
  5. func->add_connection= handle_connection_in_main_thread;  
  6. #endif  
  7. func->init_new_connection_thread= init_dummy;  
  8. func->end_thread= no_threads_end;  
  9. }  
  10.  
  11. void one_thread_per_connection_scheduler(scheduler_functions* func)  
  12. {  
  13. func->max_threads= max_connections;  
  14. func->add_connection= create_thread_to_handle_connection;  
  15. func->end_thread= one_thread_per_connection_end;  
  16. }  

It turns out that scheduler_functions parameters in a struct are set, but these parameters are some function pointers, that is, in the specific call,

You only need to call add_connection or end_thread. You don't need to know which function is called. This is probably a variant polymorphism.

2. initialize Network Configuration

The network configuration is simple, that is, to set the port, create a socket, bind the port, and listen to the port. All implementations are concentrated in the network_init function.

There is nothing to talk about. If you are not familiar with socket, you can search for related knowledge online. The corresponding pseudo code is provided here:

 
 
  1. Network_init
  2. {
  3. Set_ports; // set the port number, # define MYSQL_PORT 3306
  4. Socket; // create a socket
  5. Bind; // bind the port number.
  6. Listen; // listening port number
  7. }

3. Connection Method

The methods for inter-process communication are not only SOCKET, but also many other methods. Mysql supports three connection modes: namepipe, socket, and shared memory, namely named pipe, socket, and shared memory. These three methods can coexist. By default, only sockets are used.

The TCP/IP socket method is the connection method provided by MySQL in any platform and the most widely used method in the network. This method creates a network-based connection request on a TCP/IP connection. Generally, the client is on one server while the MySQL instance is on another server, the two machines are connected through a TCP/IP network.

For example, on a Windows Server, I can request a MySQL instance on a remote Linux server. In Windows 2000, Windows XP, Windows 2003, Windows Vista, and later Windows operating systems, if two processes that need to communicate on the same server, you can use the named pipe, the local connection after the SQL Server database is installed by default also uses the named pipe. In the MySQL database, you must enable the -- enable-named-pipe option in the configuration file.

In Versions later than MySQL 4.1, MySQL also provides a shared memory connection mode by adding -- shared-memory to the configuration file. To use shared memory, the Mysql client must also use the-protocol = memory option during connection. You can set the parameters below during startup.

 
 
  1. mysqld.exe --enable-named-pipe  
  2. mysqld.exe --shared-memory 

In addition to setting parameters at startup, you can also modify the MY. ini file. Let's take a look at handle_connections_methods, the branch function that selects the connection method in the source code:

 
 
  1. handle_connections_methods()  
  2. {  
  3. if (hPipe != INVALID_HANDLE_VALUE)  
  4. {  
  5. handler_count++;  
  6. if (pthread_create(&hThread,&connection_attrib,  
  7. handle_connections_namedpipes, 0))  
  8. {  
  9. sql_print_warning("Can't create thread to handle named pipes");  
  10. handler_count--;  
  11. }  
  12. }  
  13. if (have_tcpip && !opt_disable_networking)  
  14. {  
  15. handler_count++;  
  16. if (pthread_create(&hThread,&connection_attrib,  
  17. handle_connections_sockets, 0))  
  18. {  
  19. sql_print_warning("Can't create thread to handle TCP/IP");  
  20. handler_count--;  
  21. }  
  22. }  
  23.  
  24. if (opt_enable_shared_memory)  
  25. {  
  26. handler_count++;  
  27. if (pthread_create(&hThread,&connection_attrib,  
  28. handle_connections_shared_memory, 0))  
  29. {  
  30. sql_print_warning("Can't create thread to handle shared memory");  
  31. handler_count--;  
  32. }  
  33. }  

Because I don't know much about the communication methods between namepipe and memory share, I will only study the socket communication methods here. From the code, we can see that handle_connections_sockets is the socket setting. Let's look at it.

4. socket management creates a new thread

Socket management is actually relatively simple, and its pseudo code is directly provided:

 
 
  1. Handle_connections_sockets
  2. {
  3. Select; // monitor the socket file descriptor
  4. New_socket = accept; // process the incoming client connection
  5. Thd = new THD; Create THD class
  6. Vi_tmp = vi_new (new_socket, vi_type_tcpip, 0); // initialize the VIO struct
  7. My_net_init (& thd-> net, vie_tmp); // initialize the net struct of thd.
  8. Create_new_thread (thd); // create a new thread for this connection. If it is in single thread mode, no new thread will be created.
  9. }

First, the select function monitors the socket port. If a connection is monitored, the accept function is used to accept the connection from the client, and a new THD class is created, set all connection parameters to THD class parameters and call the create_new_thread function. This function is the focus. Let's go to this function and see what we have done.

 
 
  1. Create_new_thread
  2. {
  3. + + Connection_count; // The number of global connections increases.
  4. Thread_count ++; // auto-increment of the number of global threads
  5. Thread_scheduler.add_connection (thd); // create a thread
  6. }

So easy: first, add the number of global connections + 1, the number of global threads + 1, and then call the add_connection function. This function is the first step in which we set the connection

Among the threads, one parameter set in one_thread_scheduler and one_thread_per_connection_scheduler. The difference between the two is whether or not they have been created.

A new thread to process incoming connections. One_thread_scheduler is a single-thread method, with a newly created thread. We will focus on one_thread_per_connection_scheduler. The add_connection function is create_thread_to_handle_connection:

 
 
  1. Create_thread_to_handle_connection (THD * thd)
  2. {
  3. Thread_created ++;
  4. Threads. append (thd); // The number of created threads is auto-incrementing and added to the threads linked list.
  5. Pthread_create (& thd-> real_id, & connection_attrib,
  6. Handle_one_connection,
  7. (Void *) thd); // This is where the thread is actually created. The function is handle_one_connection.
  8. }

It can be seen that the pthread_create function is called at last. This function creates a new thread and the processing function of the new thread is handle_one_connection.

5. New thread processing process

The new thread processing function is handle_one_connection. At this point, a new connection is independently processed by a newly created thread. Let's take a look at it.

Is how to process.

 
 
  1. Handle_one_connection (void * arg)
  2. {
  3. For (;;)
  4. {
  5. Lex_start (thd); // initialize the lexical analysis structure.
  6. Login_connection (thd); // user authentication, error
  7. Prepare_new_connection_state (THD * thd); // Initialize THD to handle queries
  8. While (! Net-> error & net-> vio! = 0 & // cyclic Processing command
  9. ! (Thd-> killed = THD: KILL_CONNECTION ))
  10. {
  11. If (do_command (thd ))
  12. Break; // handle failed jumps out
  13. }
  14. End_connection (thd); // close the connection
  15. Close_connection (thd, 0, 1 );
  16. Thread_scheduler.end_thread (thd, 1); // end the thread
  17. Return 0;
  18. }
  19. }

First, initialize the lexical analysis structure, and then perform user authentication. After successful authentication, execute the commands sent from the client through the do_command loop.

6. Summary

The entire connection manager process is very clear, and single-threaded connections are rarely used. Most of them use multithreading. The thread buffer pool concept is also involved in multi-threaded connections, that is, if a connection is disconnected, the threads it creates will not be destroyed, but will be placed in the buffer pool, wait for the next new connection to arrive, first go to the thread buffer pool to check whether there are Idle threads. If yes, use them directly. If yes, create a new thread to manage the connection.

This article introduces the related knowledge of MySQL database Connection Manager. I hope this introduction will be helpful to you!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.