検索
ホームページデータベースmysql チュートリアルMysql源码学习――Connection Manager_MySQL

bitsCN.com

 

1.连接的线程数

 

       Mysql支持单线程和多线程两种连接线程数。如果是单线程,则在同一时刻,只能有一个connection连接到Mysql,

 

其他的连接会被挂起。如果是多线程,则同一时刻可以支持多个connection同时连接到服务器。

 

     可以通过设置服务器的启动参数来设定连接的线程数:

 

mysqld.exe --thread-handling=no-threads

mysqld.exe --thread-handling=one-thread-per-connection

 

  

 

服务器如何通过参数来选择使用哪种方式的呢?且看服务器中的分支代码:

 

#ifdef EMBEDDED_LIBRARY

  one_thread_scheduler(&thread_scheduler);

#else

  if (global_system_variables.thread_handling

      SCHEDULER_ONE_THREAD_PER_CONNECTION)

    one_thread_per_connection_scheduler(&thread_scheduler);

  else if (global_system_variables.thread_handling == SCHEDULER_NO_THREADS)

    one_thread_scheduler(&thread_scheduler);

  else

    pool_of_threads_scheduler(&thread_scheduler);  /* purecov: tested */

#endif

 

  

 

这段代码出现在get_options函数中,此函数是根据传入的服务器参数,设置相应参数的模式。由这段代码可以看出,如果定义了EMBEDDED_LIBRARY宏定义(估计应该是嵌入式使用),则调用one_thread_scheduler,即使用单线程。如果参数小于等于SCHEDULER_ONE_THREAD_PER_CONNECTION,则调用one_thread_per_connection_scheduler,即每个连接一个线程,即多线程。 至于global_system_variables.thread_handling是如何进行设置的呢?其实就是根据我们传递给服务器的参数--thread-handling进行设置的,参数的设置统一在函数get_options中,其调用mysqld_get_one_option,其中有个分支,代码如下:

 

case OPT_THREAD_HANDLING:

  {

    global_system_variables.thread_handling=

      find_type_or_exit(argument, &thread_handling_typelib, opt->name)-1;

    break;

  }

 

  

 

对参数初始化有兴趣的可以具体的看下get_options这个函数,这里就不详细讲解了。 我们来看下one_thread_scheduler和one_thread_per_connection_scheduler的源代码,看下他们都做了些什么?

 

void one_thread_scheduler(scheduler_functions* func)

{

  func->max_threads= 1;

#ifndef EMBEDDED_LIBRARY

  func->add_connection= handle_connection_in_main_thread;

#endif

  func->init_new_connection_thread= init_dummy;

  func->end_thread= no_threads_end;

}

 

void one_thread_per_connection_scheduler(scheduler_functions* func)

{

  func->max_threads= max_connections;

  func->add_connection= create_thread_to_handle_connection;

  func->end_thread= one_thread_per_connection_end;

}

 

  

 

   原来就是设置了一个结构体中scheduler_functions的参数,只不过这些参数是一些函数指针罢了,也就是说在具体的调用中,

 

只需要调用add_connection或end_thread即可,不需要知道到底是调用了哪个函数,这大概就是一种变形的多态性吧。

 

2.初始化网络配置

 

   网络配置比较简单,就是设置端口,创建套接字,绑定端口,监听端口。实现全部集中在network_init函数中,由于这个函数确

 

实没什么好讲的,如果对socket不熟悉的话,可以去网上搜索下相关知识。这里直接给出相应的伪代码:

 

network_init

{

    set_ports; //设置端口号,#define MYSQL_PORT            3306

    socket;//创建套接字

    bind;       //绑定端口号

    listen;//监听端口号

}

 

3.连接的方式

 

   进程间通信的方式不止是SOCKET,还有其他很多方式。Mysql支持三种连接方式:namepipe、socket和shared memory,

 

即命名管道、套接字和共享内存的方式。这三种方式是可以共存的。默认只使用套接字。

 

      TCP/IP套接字方式是MySQL在任何平台下都提供的连接方式,也是网络中使用得最多的一种方式。这种方式在TCP/IP连接上建立

 

一个基于网络的连接请求,一般情况下客户端在一台服务器上,而MySQL实例在另一台服务器上,这两台机器通过一个TCP/IP网络连接。

 

例如,我可以在Windows服务器下请求一台远程Linux服务器下的MySQL实例。

 

     在Windows 2000、Windows XP、Windows 2003和Windows Vista以及在此之后的Windows操作系统中,如果两个需要通

 

信的进程在同一台服务器上,那么可以使用命名管道,SQL Server数据库默认安装后的本地连接也使用命名管道。在MySQL数据库中,

 

需在配置文件中启用--enable-named-pipe选项。在MySQL 4.1之后的版本中,MySQL还提供了共享内存的连接方式,在配置文件中

 

添加--shared-memory。如果想使用共享内存的方式,在连接时,Mysql客户端还必须使用-protocol=memory选项。

 

     启动时可以通过下面的参数进行设置。

 

mysqld.exe --enable-named-pipe

mysqld.exe --shared-memory

 

   

 

除了在启动时进行参数设置外,也可以通过修改MY.INI文件进行设置。我们来看下源码中选择连接方式的分支函数handle_connections_methods:

 

handle_connections_methods()

{

if (hPipe != INVALID_HANDLE_VALUE)

{

       handler_count++;

       if (pthread_create(&hThread,&connection_attrib,

               handle_connections_namedpipes, 0))

       {

      sql_print_warning("Can't create thread to handle named pipes");

      handler_count--;

    }

}

    if (have_tcpip && !opt_disable_networking)

  {

    handler_count++;

    if (pthread_create(&hThread,&connection_attrib,

               handle_connections_sockets, 0))

    {

      sql_print_warning("Can't create thread to handle TCP/IP");

      handler_count--;

    }

  }

 

if (opt_enable_shared_memory)

  {

    handler_count++;

    if (pthread_create(&hThread,&connection_attrib,

               handle_connections_shared_memory, 0))

    {

      sql_print_warning("Can't create thread to handle shared memory");

      handler_count--;

    }

  }

}

 

  

 

由于对于namepipe和memory share的通信方式不太了解,这里只研究socket的通信方式。从代码中可以看出,handle_connections_sockets便是socket的设置,我们就来看下它。

 

4.socket管理创建新线程socket管理其实比较简单,直接给出其伪代码:

 

handle_connections_sockets

{

    select; //监视socket文件描述符

    new_socket = accept;//处理到来的客户端连接

    thd = new THD;创建THD类

    vio_tmp = vio_new(new_socket,VIO_TYPE_TCPIP, 0);   //初始化VIO结构体

    my_net_init(&thd->net, vio_tmp);//初始化thd的net结构体

    create_new_thread(thd);//为这个连接创建一个新的线程,如果是单线程模式的话,就不会创建一个新线程

}

 

  

 

首先是select函数进行监视socket端口,如果监控到有连接,则通过accept函数接受客户端的连接,然后新建一个THD类,将连接参数全部设置到THD类的参数上,最后调用create_new_thread函数,这个函数便是重点。 我们进入这个函数,看下做了啥。

 

create_new_thread

{

    ++connection_count;//全局连接数自增

    thread_count++;    //全局线程数自增

    thread_scheduler.add_connection(thd);//真正创建线程

}

 

  

 

     So easy,首先将全局连接数+1,全局线程数+1,然后调用add_connection函数,这个函数就是我们在上面第一步设置连接的

 

线程数中,one_thread_scheduler和one_thread_per_connection_scheduler中设置的一个参数。这两者的区别便是是否创建了

 

一个新的线程来处理到来的连接。one_thread_scheduler是单线程方式,木有新建线程。我们重点研究one_thread_per_connection_scheduler,其设置的add_connection函数为create_thread_to_handle_connection:

 

create_thread_to_handle_connection(THD *thd)

{

    thread_created++;

    threads.append(thd); // 创建线程数自增,并加入到threads链表上

    pthread_create(&thd->real_id,&connection_attrib,

                              handle_one_connection,

                              (void*) thd);//这就是真正创建线程的地方了,函数便是handle_one_connection

}

 

  

 

    可见,最后调用了pthread_create函数,这个函数便是创建一个新的线程,新线程的处理函数为handle_one_connection.

 

5.新线程处理流程

 

     新线程处理函数为handle_one_connection,到此位置,一个新的connection被一个新创建的线程所单独处理。我们看下其中

 

是如何进行处理的。

 

handle_one_connection(void *arg)

{

    for (;;)

    {

        lex_start(thd); //初始化词法分析结构体

        login_connection(thd); //用户认证,失败报错

        prepare_new_connection_state(THD* thd);//Initialize THD to handle queries

         while (!net->error && net->vio != 0 &&   //循环处理command

           !(thd->killed == THD::KILL_CONNECTION))

        {

            if (do_command(thd))

              break;                   //处理失败跳出

          }

          end_connection(thd);         //关闭连接

          close_connection(thd, 0, 1);

         thread_scheduler.end_thread(thd,1);//结束线程

                  return 0;

    }

}

 

  

 

    首先进行了词法分析结构体的初始化,然后进行用户认证,认证成功后通过do_command循环执行客户端发过来的命令。

 

6.总结

 

     整个connection manager的流程十分清晰,单线程的连接一般很少使用,大多使用多线程方式。多线程连接中其实还涉及到线程缓冲

 

池的概念,即如果一个连接断开后,其所创建的线程不会被销毁掉,而是放到缓冲池中,等待下一个新的connection到来时,首先去线程

 

缓冲池查找是否有空闲的线程,有的话直接使用,木有的话才去创建新的线程来管理这个connection。这些属于Thread Manage的内容,

 

下节进行Thread Manage的学习。

 

PS. 上周六迎来第一个双休,结果还是被叫道公司改BUG,我忍。不过,BOSS,前几个月的加班费啥时候发啊?不准拖欠民工工资…

 

踏着落叶,追寻着我的梦想。转载请注明出处

 



摘自 心中无码 bitsCN.com
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
MySQLの役割:WebアプリケーションのデータベースMySQLの役割:WebアプリケーションのデータベースApr 17, 2025 am 12:23 AM

WebアプリケーションにおけるMySQLの主な役割は、データを保存および管理することです。 1.MYSQLは、ユーザー情報、製品カタログ、トランザクションレコード、その他のデータを効率的に処理します。 2。SQLクエリを介して、開発者はデータベースから情報を抽出して動的なコンテンツを生成できます。 3.MYSQLは、クライアントサーバーモデルに基づいて機能し、許容可能なクエリ速度を確保します。

MySQL:最初のデータベースを構築しますMySQL:最初のデータベースを構築しますApr 17, 2025 am 12:22 AM

MySQLデータベースを構築する手順には次のものがあります。1。データベースとテーブルの作成、2。データの挿入、および3。クエリを実行します。まず、createdAtabaseおよびcreateTableステートメントを使用してデータベースとテーブルを作成し、InsertINTOステートメントを使用してデータを挿入し、最後にSelectステートメントを使用してデータを照会します。

MySQL:データストレージに対する初心者向けのアプローチMySQL:データストレージに対する初心者向けのアプローチApr 17, 2025 am 12:21 AM

MySQLは、使いやすく強力であるため、初心者に適しています。 1.MYSQLはリレーショナルデータベースであり、CRUD操作にSQLを使用します。 2。インストールは簡単で、ルートユーザーのパスワードを構成する必要があります。 3.挿入、更新、削除、および選択してデータ操作を実行します。 4. Orderby、Where and Joinは複雑なクエリに使用できます。 5.デバッグでは、構文をチェックし、説明を使用してクエリを分析する必要があります。 6.最適化の提案には、インデックスの使用、適切なデータ型の選択、優れたプログラミング習慣が含まれます。

MySQLは初心者に優しいですか?学習曲線の評価MySQLは初心者に優しいですか?学習曲線の評価Apr 17, 2025 am 12:19 AM

MySQLは初心者に適しています。1)インストールと構成、2)リッチラーニングリソース、3)直感的なSQL構文、4)強力なツールサポート。それにもかかわらず、初心者はデータベースの設計、クエリの最適化、セキュリティ管理、データのバックアップなどの課題を克服する必要があります。

SQLはプログラミング言語ですか?用語を明確にするSQLはプログラミング言語ですか?用語を明確にするApr 17, 2025 am 12:17 AM

はい、sqlisaprogramginglanguagespecializedfordatamanamanagement.1)それはdeclarative、focusingonwhattoachieveratherthanhow.2)

酸性の特性(原子性、一貫性、分離、耐久性)を説明します。酸性の特性(原子性、一貫性、分離、耐久性)を説明します。Apr 16, 2025 am 12:20 AM

酸性属性には、原子性、一貫性、分離、耐久性が含まれ、データベース設計の基礎です。 1.原子性は、トランザクションが完全に成功するか、完全に失敗することを保証します。 2.一貫性により、データベースがトランザクションの前後に一貫性を保証します。 3.分離により、トランザクションが互いに干渉しないようにします。 4.永続性により、トランザクションの提出後にデータが永久に保存されることが保証されます。

MySQL:データベース管理システムとプログラミング言語MySQL:データベース管理システムとプログラミング言語Apr 16, 2025 am 12:19 AM

MySQLは、データベース管理システム(DBMS)であるだけでなく、プログラミング言語にも密接に関連しています。 1)DBMSとして、MySQLはデータを保存、整理、取得するために使用され、インデックスを最適化するとクエリのパフォーマンスが向上する可能性があります。 2)SQLとPythonに埋め込まれたプログラミング言語とSQLalchemyなどのORMツールを使用すると、操作を簡素化できます。 3)パフォーマンスの最適化には、インデックス、クエリ、キャッシュ、ライブラリ、テーブル分割、およびトランザクション管理が含まれます。

MySQL:SQLコマンドでデータの管理MySQL:SQLコマンドでデータの管理Apr 16, 2025 am 12:19 AM

MySQLはSQLコマンドを使用してデータを管理します。 1.基本コマンドには、select、挿入、更新、削除が含まれます。 2。高度な使用には、参加、サブクエリ、および集計関数が含まれます。 3.一般的なエラーには、構文、ロジック、パフォーマンスの問題が含まれます。 4。最適化のヒントには、インデックスの使用、Select*の回避、制限の使用が含まれます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター