【从入门到放弃-MySQL】数据库连接过程分析-客户端

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 前言上文分析了【从入门到放弃-MySQL】数据库连接过程分析。本文我们一起来追一下客户端和服务端建联的过程。这里客户端使用JDBC8.0,在SpringBoot2.1.3下验证。请求流程初始化SpringBoot2.

前言

上文分析了【从入门到放弃-MySQL】数据库连接过程分析。本文我们一起来追一下客户端和服务端建联的过程。
这里客户端使用JDBC8.0,在SpringBoot2.1.3下验证。

请求流程

初始化

SpringBoot2.1.3默认使用的HickriCP连接池

应用启动时,会先注册spring.datasource.driver-class-name配置的驱动,这里我们使用com.mysql.cj.jdbc.Driver

启动后,我们直接通过一个查询操作的http请求来验证一次查询操作中,客户端与服务端连接的过程

首次请求

当使用到Dao请求时,开始建立连接
调用堆栈如下:

checkErrorMessage:752, NativeProtocol (com.mysql.cj.protocol.a)
checkErrorMessage:741, NativeProtocol (com.mysql.cj.protocol.a)
checkErrorMessage:709, NativeProtocol (com.mysql.cj.protocol.a)
checkErrorMessage:132, NativeProtocol (com.mysql.cj.protocol.a)
proceedHandshakeWithPluggableAuthentication:540, NativeAuthenticationProvider (com.mysql.cj.protocol.a)
connect:202, NativeAuthenticationProvider (com.mysql.cj.protocol.a)
connect:1449, NativeProtocol (com.mysql.cj.protocol.a)
connect:165, NativeSession (com.mysql.cj)
connectOneTryOnly:955, ConnectionImpl (com.mysql.cj.jdbc)
createNewIO:825, ConnectionImpl (com.mysql.cj.jdbc)
<init>:455, ConnectionImpl (com.mysql.cj.jdbc)
getInstance:240, ConnectionImpl (com.mysql.cj.jdbc)
connect:199, NonRegisteringDriver (com.mysql.cj.jdbc)
getConnection:136, DriverDataSource (com.zaxxer.hikari.util)
newConnection:369, PoolBase (com.zaxxer.hikari.pool)
newPoolEntry:198, PoolBase (com.zaxxer.hikari.pool)
createPoolEntry:467, HikariPool (com.zaxxer.hikari.pool)
checkFailFast:541, HikariPool (com.zaxxer.hikari.pool)
<init>:115, HikariPool (com.zaxxer.hikari.pool)
getConnection:112, HikariDataSource (com.zaxxer.hikari)
fetchConnection:157, DataSourceUtils (org.springframework.jdbc.datasource)
doGetConnection:115, DataSourceUtils (org.springframework.jdbc.datasource)
getConnection:78, DataSourceUtils (org.springframework.jdbc.datasource)
openConnection:82, SpringManagedTransaction (org.mybatis.spring.transaction)
getConnection:68, SpringManagedTransaction (org.mybatis.spring.transaction)
getConnection:336, BaseExecutor (org.apache.ibatis.executor)
prepareStatement:85, SimpleExecutor (org.apache.ibatis.executor)
doQuery:62, SimpleExecutor (org.apache.ibatis.executor)
queryFromDatabase:324, BaseExecutor (org.apache.ibatis.executor)
query:156, BaseExecutor (org.apache.ibatis.executor)
query:109, CachingExecutor (org.apache.ibatis.executor)
query:83, CachingExecutor (org.apache.ibatis.executor)
selectList:148, DefaultSqlSession (org.apache.ibatis.session.defaults)
selectList:141, DefaultSqlSession (org.apache.ibatis.session.defaults)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:433, SqlSessionTemplate$SqlSessionInterceptor (org.mybatis.spring)
selectList:-1, $Proxy59 (com.sun.proxy)
selectList:230, SqlSessionTemplate (org.mybatis.spring)
executeForMany:144, MapperMethod (org.apache.ibatis.binding)
execute:77, MapperMethod (org.apache.ibatis.binding)
invoke:58, MapperProxy (org.apache.ibatis.binding)
selectByCondition:-1, $Proxy60 (com.sun.proxy)
getUserByCondition:40, UsersServiceImpl (com.springboot.demo.service.impl)
getUsersByCondition:74, IndexController (com.springboot.demo.controller)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:189, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:138, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:102, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:895, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:800, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1038, DispatcherServlet (org.springframework.web.servlet)
doService:942, DispatcherServlet (org.springframework.web.servlet)
processRequest:1005, FrameworkServlet (org.springframework.web.servlet)
doGet:897, FrameworkServlet (org.springframework.web.servlet)
service:634, HttpServlet (javax.servlet.http)
service:882, FrameworkServlet (org.springframework.web.servlet)
service:741, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:99, RequestContextFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:92, FormContentFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, HiddenHttpMethodFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:200, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:200, StandardWrapperValve (org.apache.catalina.core)
invoke:96, StandardContextValve (org.apache.catalina.core)
invoke:490, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:139, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:74, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:408, Http11Processor (org.apache.coyote.http11)
process:66, AbstractProcessorLight (org.apache.coyote)
process:834, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1415, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)

再次请求

连接建立后,再次请求的调用栈

createProxyConnection:97, PoolEntry (com.zaxxer.hikari.pool)
getConnection:185, HikariPool (com.zaxxer.hikari.pool)
getConnection:155, HikariPool (com.zaxxer.hikari.pool)
getConnection:128, HikariDataSource (com.zaxxer.hikari)
fetchConnection:157, DataSourceUtils (org.springframework.jdbc.datasource)
doGetConnection:115, DataSourceUtils (org.springframework.jdbc.datasource)
getConnection:78, DataSourceUtils (org.springframework.jdbc.datasource)
openConnection:82, SpringManagedTransaction (org.mybatis.spring.transaction)
getConnection:68, SpringManagedTransaction (org.mybatis.spring.transaction)
getConnection:336, BaseExecutor (org.apache.ibatis.executor)
prepareStatement:85, SimpleExecutor (org.apache.ibatis.executor)
doQuery:62, SimpleExecutor (org.apache.ibatis.executor)
queryFromDatabase:324, BaseExecutor (org.apache.ibatis.executor)
query:156, BaseExecutor (org.apache.ibatis.executor)
query:109, CachingExecutor (org.apache.ibatis.executor)
query:83, CachingExecutor (org.apache.ibatis.executor)
selectList:148, DefaultSqlSession (org.apache.ibatis.session.defaults)
selectList:141, DefaultSqlSession (org.apache.ibatis.session.defaults)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:433, SqlSessionTemplate$SqlSessionInterceptor (org.mybatis.spring)
selectList:-1, $Proxy59 (com.sun.proxy)
selectList:230, SqlSessionTemplate (org.mybatis.spring)
executeForMany:144, MapperMethod (org.apache.ibatis.binding)
execute:77, MapperMethod (org.apache.ibatis.binding)
invoke:58, MapperProxy (org.apache.ibatis.binding)
selectByCondition:-1, $Proxy60 (com.sun.proxy)
getUserByCondition:40, UsersServiceImpl (com.springboot.demo.service.impl)
getUsersByCondition:74, IndexController (com.springboot.demo.controller)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:189, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:138, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:102, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:895, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:800, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1038, DispatcherServlet (org.springframework.web.servlet)
doService:942, DispatcherServlet (org.springframework.web.servlet)
processRequest:1005, FrameworkServlet (org.springframework.web.servlet)
doGet:897, FrameworkServlet (org.springframework.web.servlet)
service:634, HttpServlet (javax.servlet.http)
service:882, FrameworkServlet (org.springframework.web.servlet)
service:741, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:99, RequestContextFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:92, FormContentFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, HiddenHttpMethodFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:200, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:200, StandardWrapperValve (org.apache.catalina.core)
invoke:96, StandardContextValve (org.apache.catalina.core)
invoke:490, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:139, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:74, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:408, Http11Processor (org.apache.coyote.http11)
process:66, AbstractProcessorLight (org.apache.coyote)
process:834, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1415, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)

因为两次请求的调用栈都比较深且有很大一部分重合路径,我们使用Beyond Compare将两次调用栈对比来看。

Mybatis处理

如上图所示 selectByCondition 是请求中dao层的调用方法,这个方法调用之前是spring对http请求的处理动作,
处理的流程暂不分析。直接看selectByCondition之后处理流程。

  • MyBatis通过SqlSessionFactoryBuilder对mybatis-config.xml进行解析,从中构建出SqlSessionFactory,
  • 再创建出SqlSession实例,
  • SqlSession调用Executor生成StatementHandler对象。
  • 然后通过Spring框架的DataSourceUtils::getConnection方法获取连接。

连接

对比两次请求不同的地方,对比HikariDataSource源码。

  • 首次请求会调用112行,第二次会调用128行。
  • 可以看到Hikari连接池使用了双重检查锁的方式来实现单例,避免重复创建连接池。
  • 一次请求结束后,连接会放在连接池中,在连接池中,使用connectionBag控制一个连接“借出”、“归还”。详细信息可参考Hikari的线程池的生命周期

我们分析下首次调用建立连接的过程。

Hikari会先创建一个连接池,然后使用我们在启动时注册的驱动(com.mysql.cj.jdbc.Driver)创建连接。

可以从NonRegisteringDriver::connect一直追下去,可以看到com.mysql.cj.NativeSession::connect方法实现如下:

    public void connect(HostInfo hi, String user, String password, String database, int loginTimeout, TransactionEventHandler transactionManager)
            throws IOException {

        this.hostInfo = hi;

        // reset max-rows to default value
        this.setSessionMaxRows(-1);

        // TODO do we need different types of physical connections?
        SocketConnection socketConnection = new NativeSocketConnection();
        socketConnection.connect(this.hostInfo.getHost(), this.hostInfo.getPort(), this.propertySet, getExceptionInterceptor(), this.log, loginTimeout);

        // we use physical connection to create a -> protocol
        // this configuration places no knowledge of protocol or session on physical connection.
        // physical connection is responsible *only* for I/O streams
        if (this.protocol == null) {
            this.protocol = NativeProtocol.getInstance(this, socketConnection, this.propertySet, this.log, transactionManager);
        } else {
            this.protocol.init(this, socketConnection, this.propertySet, transactionManager);
        }

        // use protocol to create a -> session
        // protocol is responsible for building a session and authenticating (using AuthenticationProvider) internally
        this.protocol.connect(user, password, database);

        // error messages are returned according to character_set_results which, at this point, is set from the response packet
        this.protocol.getServerSession().setErrorMessageEncoding(this.protocol.getAuthenticationProvider().getEncodingForHandshake());

        this.isClosed = false;
    }
  • 先创建一个socket与服务端建立连接
  • 通过NativeProtocol.getInstance初始化MySQL协议相关信息
  • 调用NativeProtocol::connect方法根据MySQL账号、密码、使用数据库等信息向服务端请求认证。
  • 使用proceedHandshakeWithPluggableAuthentication对返回的数据包根据MySQL协议进行解析。
  • 调用NativeProtocol::checkErrorMessage对解析后的内容做判断,如果没问题则正常连接,如果返回错误信息则抛出异常。
  • 连接建立后,通过Hikari连接池保存,下次使用直接用(如对比文件所示)。
    MySQL协议详解可参考:http://hutaow.com/blog/2013/11/06/mysql-protocol-analysis/

事务处理

org.springframework.jdbc.datasource.DataSourceTransactionManager会维护一个DataSourceTransactionObject。
里面存放事务请求的连接。保证事务里的所有请求都是同一个连接在执行。

总结

通过对数据库连接过程的分析,对数据库服务端、客户端的连接过程有了一个初步的认识,脑海中有个大概的体系,但还是不够深入,如MySQL协议的具体协议内容、连接鉴权的细节、Hikari连接池、Jdbc。。。都需要大量时间去深入研究,接下来要逐步去学习、沉淀下来。

更多文章见:https://nc2era.com

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
15天前
|
SQL 关系型数据库 MySQL
网安入门之MySQL后端基础
《网安入门之MySQL后端基础》简介: 本文介绍了数据库及MySQL的基础知识,涵盖数据库的概念、结构与操作。数据库是组织化存储数据的集合,通过表、列、行等结构实现高效管理。MySQL作为开源的关系型数据库管理系统,广泛应用于Web开发。文中详细讲解了MySQL的基本操作,如增(INSERT)、删(DELETE)、改(UPDATE)、查(SELECT)等语句的使用方法,并介绍了数据库事务的ACID特性。此外,还探讨了SQL注入攻击的风险及防范措施,强调了预处理语句的重要性。最后,简述了PHP中mysqli扩展的使用方法,包括连接数据库、执行查询和关闭连接等步骤。
|
19天前
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
MySQL事务日志-Undo Log工作原理分析
|
2天前
|
关系型数据库 MySQL 数据库
mysql慢查询每日汇报与分析
通过启用慢查询日志、提取和分析慢查询日志,可以有效识别和优化数据库中的性能瓶颈。结合适当的自动化工具和优化措施,可以显著提高MySQL数据库的性能和稳定性。希望本文的详解和示例能够为数据库管理人员提供有价值的参考,帮助实现高效的数据库管理。
27 11
|
13天前
|
安全 关系型数据库 MySQL
CentOS7仅安装部署MySQL80客户端
通过上述步骤,你可以在CentOS 7上成功安装并配置MySQL 8.0客户端。这个过程确保你能够使用MySQL客户端工具连接和管理远程的MySQL数据库,而不需要在本地安装MySQL服务器。定期更新MySQL客户端可以确保你使用的是最新的功能和安全修复。
94 16
|
7天前
|
关系型数据库 分布式数据库 数据库
瑶池数据库大讲堂|PolarDB HTAP:为在线业务插上实时分析的翅膀
瑶池数据库大讲堂介绍PolarDB HTAP,为在线业务提供实时分析能力。内容涵盖MySQL在线业务的分析需求与现有解决方案、PolarDB HTAP架构优化、针对分析型负载的优化(如向量化执行、多核并行处理)及近期性能改进和用户体验提升。通过这些优化,PolarDB HTAP实现了高效的数据处理和查询加速,帮助用户更好地应对复杂业务场景。
|
3天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
41 0
|
1月前
|
SQL 关系型数据库 MySQL
MySQL 窗口函数详解:分析性查询的强大工具
MySQL 窗口函数从 8.0 版本开始支持,提供了一种灵活的方式处理 SQL 查询中的数据。无需分组即可对行集进行分析,常用于计算排名、累计和、移动平均值等。基本语法包括 `function_name([arguments]) OVER ([PARTITION BY columns] [ORDER BY columns] [frame_clause])`,常见函数有 `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, `SUM()`, `AVG()` 等。窗口框架定义了计算聚合值时应包含的行。适用于复杂数据操作和分析报告。
79 11
|
30天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
60 3
|
30天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
76 3
|
30天前
|
SQL 关系型数据库 MySQL
MySQL操作利器大公开!这几款客户端让你事半功倍
本文介绍了多种MySQL数据库管理工具,包括命令行工具、图形化用户界面(GUI)工具和Web界面工具。主要工具有: 1. **Navicat for MySQL**:功能强大,支持多种数据库管理任务,但需付费。 2. **DBeaver**:开源免费,支持多种数据库,安装包较大。 3. **MySQL Workbench**:官方提供的图形化工具,适合MySQL全家桶用户。 4. **HeidiSQL**:轻量级Windows客户端,简单易用。 5. **phpMyAdmin**:基于Web的管理工具,易于部署和使用。 6. **SQLyog**:适用于Windows,功能丰富,有免费
88 3