-
RDS for MySQL实例无法访问解决办法故障描述客户端无法连接数据库,连接数据库时返回如下报错信息:故障一ERROR 1045 (28000): Access denied for user ‘root'@‘192.168.0.30' (using password:YES)故障二ERROR 1226 (42000):User‘test' has exceeded the‘max_user_connections' resource (current value:10)故障三ERROR 1129 (HY000): Host ‘192.168.0.111' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'故障一1.排查密码root账号的密码是否正确。一般情况下,ERROR 1045报错为密码错误引起的,因此需要首要排除是否密码错误问题。select password(‘Test1i@123');select host,user,Password from mysql.user where user=‘test1';使用错误的密码登录就会失败。2.确认该主机是否有连接数据库实例的权限。select user, host from mysql.user where user=‘username';如果该数据库用户需要从其他主机登录,则需要使用root用户连接数据库,并给该用户授权。以加入主机IP为192.168.0.76举例:GRANT all privileges ON test.* TO 'test1'@'192.168.0.76' identified by 'Test1i@123'; flush privileges;3.确认MySQL客户端和实例VIP的连通性。尝试进行ping连接性能,若可以ping通,排除telnet数据库端口的问题。4.查看实例安全组,排查是否因安全策略问题引起的报错。5.查询user表信息,确认用户信息。在排查中发现存在两个root用户。如果用户的客户端处于192.168的网段,MySQL数据库的是对root@'192.168.%'这个用户进行认证的。而用户登录时使用的为root@'%'这个帐号所对应的密码,因而导致连接失败,无法正常访问。此次问题是因密码错误引起的访问失败。说明:在此案例中,root@'%'为console创建实例时设置密码的帐号。故障二1.排查是否在创建MySQL用户时,添加了max_user_connections选项,导致限制了连接数。select user,host ,max_user_connections from mysql.user where user=‘test';经排查发现由于设置了max_user_connections选项,导致连接失败。2.增加该用户最大连接数。alter user test@‘192.168.0.100' with max_user_connections 15。3.查询变更结果,检查是否可正常访问数据库。故障三排查是否由于MySQL客户端连接数据库的失败次数(不包括密码错误),超过了max_connection_errors的值。在数据库端解除超出限值问题。使用root用户登录mysql,执行flush hosts。或者执行如下命令。mysqladmin flush-hosts –u<user> –p<password> -h<ip> -P<port >。再次连接,检查是否可正常访问数据库。End:欢迎各位小伙伴来交流提问啊。
-
MySQL 一般是安装在服务器上的,我们在客户端可以进行连接,然后可以进行一些增删改查操作。下面我们分服务器端和客户端来讲解一下 MySQL 的实用工具集。MySQL 服务器端实用工具1) mysqldSQL 后台程序(即 MySQL 服务器进程)。该程序必须运行之后,客户端才能通过连接服务器来访问数据库。2) mysqld_safe服务器启动脚本。在 UNIX 和 NewWare 中推荐使用 mysqld_safe 来启动 mysqld 服务器。mysqld_safe 增加了一些安全性,例如,当出现错误时,重启服务器并向错误日志文件中写入运行时间信息。3) mysql.server服务器启动脚本。该脚本用于使用包含为特定级别的、运行启动服务器脚本的、运行目录的系统。它调用 mysqld_safe 来启动 MySQL 服务器。4) mysqld_multi服务器启动脚本,可以启动或停止系统上安装的多个服务器。5) mysamchk用来描述、检查、优化和维护 MyISAM 表的实用工具。6) mysql.server服务器启动脚本。在 UNIX 中的 MySQL 分发版包括 mysql.server 脚本。7) mysqlbugMySQL 缺陷报告脚本。它可以用来向 MySQL 邮件系统发送缺陷报告。8) mysql_install_db该脚本用默认权限创建 MySQL 授予权表。通常只是在系统上首次安装 MySQL 时执行一次。MySQL 客户端实用工具1) myisampack压缩 MyISAM 表以产生更小的只读表的一个工具。2) mysql交互式输入 SQL 语句或从文件经批处理模式执行它们的命令行工具。3) mysqlacceess检查访问主机名、用户名和数据库组合的权限的脚本。4) mysqladmin执行管理操作的客户程序,例如创建或删除数据库、重载授权表、将表刷新到硬盘上以及重新打开日志文件。Mysqladmin 还可以用来检索版本、进程以及服务器的状态信息。5) mysqlbinlog从二进制日志读取语句的工具。在二进制日志文件中包含执行过的语句,可用来帮助系统从崩溃中恢复。6) mysqlcheck检查、修复、分析以及优化表的表维护客户程序。7) mysqldump将 MySQL 数据库转储到一个文件(例如 SQL 语句或 Tab 分隔符文本文件)的客户程序。8) mysqlhotcopy当服务器在运行时,快速备份 MyISAM 或 ISAM 表的工具。9) mysql import使用 LOAD DATA INFILE 将文本文件导入相应的客户程序。10) mysqlshow显示数据库、表、列以及索引相关信息的客户程序。11) perror显示系统或 MySQL 错误代码含义的工具。
-
第一次使用 MySQL Command Line Client 有可能输入密码后一按下回车键,程序窗口就自动关闭,出现闪退现象。本节主要分析产生闪退现象的原因以及如何处理这种情况。原因分析一首先可以查看程序默认执行文件是否存在,具体操作步骤如下:步骤 1):找到 MySQL 5.7 Command Line Client 程序右击,在弹出的菜单中选择属性。步骤 2):在打开的属性对话框中注意看“目标”文本框中的内容,如图所示。目标文本框中的内容如下:"C:\Program Files\MySQL\MySQL Server 5.7\bin\mysql.exe" "--defaults-file=C:\ProgramData\MySQL\MySQL Server 5.7\my.ini" "-uroot" "-p"可以看出程序默认执行的是 my.ini 文件,但是进入 MySQL 目录后会发现并没有 my.ini 文件。因为执行文件不存在,所以弹出的窗口会闪一下就消失了。这时大家可以将电脑中的 my-default.ini 文件复制粘贴,然后重命名为 my.ini 就可以了。原因分析二如果 MySQL 服务没有启动,MySQL Command Line Client 也会出现闪退现象。大多数用户没有启动 MySQL 服务就开始运行 MySQL Command Line Client,这样的情况下也是无法登录的。大家可以通过任务管理器来查看是否开启了这个程序,如图所示。原因分析三还有一种比较少的情况,那就是修改了安装路径。如果在安装 MySQL 的时候修改了安装保存的文件夹,那么软件的安装位置就会出现错误。如果是使用的默认的安装目录,一般是不会出现这样的故障。
-
摘要:百万级、千万级数据处理,核心关键在于数据存储方案设计,存储方案设计的是否合理,直接影响到数据CRUD操作。总体设计可以考虑一下几个方面进行设计考虑: 数据存储结构设计;索引设计;数据主键设计;查询方案设计。百万级、千万级数据处理,个人认为核心关键在于数据存储方案设计,存储方案设计的是否合理,直接影响到数据CRUD操作。总体设计可以考虑一下几个方面进行设计考虑:数据存储结构设计索引设计数据主键设计查询方案设计百万级数据处理方案:数据存储结构设计表字段设计 表字段 not null,因为 null 值很难查询优化且占用额外的索引空间,推荐默认数字 0。 数据状态类型的字段,比如 status, type 等等,尽量不要定义负数,如 -1。因为这样可以加上 UNSIGNED,数值容量就会扩大一倍。 可以的话用 TINYINT、SMALLINT 等代替 INT,尽量不使用 BIGINT,因为占的空间更小。 字符串类型的字段会比数字类型占的空间更大,所以尽量用整型代替字符串,很多场景是可以通过编码逻辑来实现用整型代替的。 字符串类型长度不要随意设置,保证满足业务的前提下尽量小。 用整型来存 IP。 单表不要有太多字段,建议在20以内。 为能预见的字段提前预留,因为数据量越大,修改数据结构越耗时。索引设计 索引,空间换时间的优化策略,基本上根据业务需求设计好索引,足以应付百万级的数据量,养成使用 explain 的习惯,关于 explain 也可以访问:explain 让你的 sql 写的更踏实了解更多。 一个常识:索引并不是越多越好,索引是会降低数据写入性能的。 索引字段长度尽量短,这样能够节省大量索引空间; 取消外键,可交由程序来约束,性能更好。 复合索引的匹配最左列规则,索引的顺序和查询条件保持一致,尽量去除没必要的单列索引。 值分布较少的字段(不重复的较少)不适合建索引,比如像性别这种只有两三个值的情况字段建立索引意义不大。 需要排序的字段建议加上索引,因为索引是会排序的,能提高查询性能。 字符串字段使用前缀索引,不使用全字段索引,可大幅减小索引空间。查询语句优化 尽量使用短查询替代复杂的内联查询。 查询不使用 select *,尽量查询带索引的字段,避免回表。 尽量使用 limit 对查询数量进行限制。 查询字段尽量落在索引上,尤其是复合索引,更需要注意最左前缀匹配。 拆分大的 delete / insert 操作,一方面会锁表,影响其他业务操作,还有一方面是 MySQL 对 sql 长度也是有限制的。 不建议使用 MySQL 的函数,计算等,可先由程序处理,从上面提的一些点会发现,能交由程序处理的尽量不要把压力转至数据库上。因为多数的服务器性能瓶颈都在数据库上。 查询 count,性能:count(1) = count(*) > count(主键) > count(其他字段)。 查询操作符能用 between 则不用 in,能用 in 则不用 or。 避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等这样的操作符,因为这些查询无法使用索引。 sql 尽量简单,少用 join,不建议两个 join 以上。千万级数据处理方案:数据存储结构设计到了这个阶段的数据量,数据本身已经有很大的价值了,数据除了满足常规业务需求外,还会有一些数据分析的需求。而这个时候数据可变动性不高,基本上不会考虑修改原有结构,一般会考虑从分区,分表,分库三方面做优化:分区分区是根据一定的规则,数据库把一个表分解成多个更小的、更容易管理的部分,是一种水平划分。对应用来说是完全透明的,不影响应用的业务逻辑,即不用修改代码。因此能存更多的数据,查询,删除也支持按分区来操作,从而达到优化的目的。如果有考虑分区,可以提前做准备,避免下列一些限制:一个表最多只能有1024个分区(mysql5.6之后支持8192个分区)。但你实际操作的时候,最好不要一次性打开超过 100 个分区,因为打开分区也是有时间损耗的。如果分区字段中有主键或者唯一索引列,那么所有主键列和唯一索引列都必须包含进来,如果表中有主键或唯一索引,那么分区键必须是主键或唯一索引。分区表中无法使用外键约束。NULL值会使分区过滤无效,这样会被放入默认的分区里,请千万不要让分区字段出现 NULL。所有分区必须使用相同的存储引擎。分表分表分水平分表和垂直分表。水平分表即拆分成数据结构相同的各个小表,如拆分成 table1, table2...,从而缓解数据库读写压力。垂直分表即将一些字段分出去形成一个新表,各个表数据结构不相同,可以优化高并发下锁表的情况。可想而知,分表的话,程序的逻辑是需要做修改的,所以,一般是在项目初期时,预见到大数据量的情况,才会考虑分表。后期阶段不建议分表,成本很大。分库分库一般是主从模式,一个数据库服务器主节点复制到一个或多个从节点多个数据库,主库负责写操作,从库负责读操作,从而达到主从分离,高可用,数据备份等优化目的。当然,主从模式也会有一些缺陷,主从同步延迟,binlog 文件太大导致的问题等等,这里不细讲(笔者也学不动了)。其他冷热表隔离。对于历史的数据,查询和使用的人数少的情况,可以移入另一个冷数据库里,只提供查询用,来缓解热表数据量大的情况。数据库表主键设计数据库主键设计,个人推荐带有时间属性的自增长数字ID。(分布式自增长ID生成算法)雪花算法百度分布式ID算法美团分布式ID算法为什么要使用这些算法呢,这个与MySQL数据存储结构有关从业务上来说在设计数据库时不需要费尽心思去考虑设置哪个字段为主键。然后是这些字段只是理论上是唯一的,例如使用图书编号为主键,这个图书编号只是理论上来说是唯一的,但实践中可能会出现重复的情况。所以还是设置一个与业务无关的自增ID作为主键,然后增加一个图书编号的唯一性约束。从技术上来说如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。 总的来说就是可以提高查询和插入的性能。对InnoDB来说主键索引既存储索引值,又在叶子节点中存储行的数据,也就是说数据文件本身就是按照b+树方式存放数据的。如果没有定义主键,则会使用非空的UNIQUE键做主键 ; 如果没有非空的UNIQUE键,则系统生成一个6字节的rowid做主键;聚簇索引中,N行形成一个页(一页通常大小为16K)。如果碰到不规则数据插入时,为了保持B+树的平衡,会造成频繁的页分裂和页旋转,插入速度比较慢。所以聚簇索引的主键值应尽量是连续增长的值,而不是随机值(不要用随机字符串或UUID)。故对于InnoDB的主键,尽量用整型,而且是递增的整型。这样在存储/查询上都是非常高效的。MySQL面试题MySQL数据库千万级数据查询优化方案limit分页查询越靠后查询越慢。这也让我们得出一个结论:1,limit语句的查询时间与起始记录的位置成正比。2,mysql的limit语句是很方便,但是对记录很多的表并不适合直接使用表使用InnoDB作为存储引擎,id作为自增主键,默认为主键索引SELECT id FROM test LIMIT 9000000,100;现在优化的方案有两种,即通过id作为查询条件使用子查询实现和使用join实现;1,id>=的(子查询)形式实现select * from test where id >= (select id from test limit 9000000,1)limit 0,100使用join的形式;SELECT * FROM test a JOIN (SELECT id FROM test LIMIT 9000000,100) b ON a.id = b.id这两种优化查询使用时间比较接近,其实两者用的都是一个原理,所以效果也差不多。但个人建议最好使用join,尽量减少子查询的使用。注:目前是千万级别查询,如果将至百万级别,速度会更快。SELECT * FROM test a JOIN (SELECT id FROM test LIMIT 1000000,100) b ON a.id = b.id你用过MySQL那些存储引擎,他们都有什么特点和区别?这是高级开发者面试时经常被问的问题。实际我们在平时的开发中,经常会遇到的。Mysql的存储引擎有这么多种,实际我们在平时用的最多的莫过于InnoDB和MyISAM了。所有如果面试官问道mysql有哪些存储引擎,你只需要告诉这两个常用的就行。那他们都有什么特点和区别呢?MyISAM:默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。不是事务安全的,而且不支持外键,如果执行大量的select,insert MyISAM比较适合。InnoDB:支持事务安全的引擎,支持外键、行锁、事务是他的最大特点。如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS较高的情况。注:在MySQL 5.5之前的版本中,默认的搜索引擎是MyISAM,从MySQL 5.5之后的版本中,默认的搜索引擎变更为InnoDBMyISAM和InnoDB的区别:InnoDB支持事务,MyISAM不支持。对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;InnoDB支持外键,而MyISAM不支持。InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快。Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;5.7以后的InnoDB支持全文索引了。InnoDB支持表、行级锁(默认),而MyISAM支持表级锁。;InnoDB表必须有主键(用户没有指定的话会自己找或生产一个主键),而Myisam可以没有。Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI。Innodb:frm是表定义文件,ibd是数据文件。Myisam:frm是表定义文件,myd是数据文件,myi是索引文件。MySQL复杂查询语句的优化,你会怎么做?说到复杂SQL优化,最多的是由于多表关联造成了大量的复杂的SQL语句,那我们拿到这种sql到底该怎么优化呢,实际优化也是有套路的,只要按照套路执行就行。复杂SQL优化方案:使用EXPLAIN关键词检查SQL。EXPLAIN可以帮你分析你的查询语句或是表结构的性能瓶颈,就得EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的,是否有全表扫描等;查询的条件尽量使用索引字段,如某一个表有多个条件,就尽量使用复合索引查询,复合索引使用要注意字段的先后顺序。多表关联尽量用join,减少子查询的使用。表的关联字段如果能用主键就用主键,也就是尽可能的使用索引字段。如果关联字段不是索引字段可以根据情况考虑添加索引。尽量使用limit进行分页批量查询,不要一次全部获取。绝对避免select *的使用,尽量select具体需要的字段,减少不必要字段的查询;尽量将or 转换为 union all。尽量避免使用is null或is not null。要注意like的使用,前模糊和全模糊不会走索引。Where后的查询字段尽量减少使用函数,因为函数会造成索引失效。避免使用不等于(!=),因为它不会使用索引。用exists代替in,not exists代替not in,效率会更好;避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤,这个处理需要排序,总计等操作。如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。千万不要 ORDER BY RAND()
-
当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令。开始介绍ALTER前让我们先创建一张表,表名为:testalter_tbl。root@host# mysql -u root -p password;Enter password:*******mysql> use RUNOOB;Database changed mysql> create table testalter_tbl -> ( -> i INT, -> c CHAR(1) -> );Query OK, 0 rows affected (0.05 sec)mysql> SHOW COLUMNS FROM testalter_tbl; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra |+-------+---------+------+-----+---------+-------+ | i | int(11) | YES | | NULL | | | c | char(1) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 2rows in set (0.00 sec)删除,添加或修改表字段如下命令使用了 ALTER 命令及 DROP 子句来删除以上创建表的 i 字段:mysql> ALTER TABLE testalter_tbl DROP i;如果数据表中只剩余一个字段则无法使用DROP来删除字段。MySQL 中使用 ADD 子句来向数据表中添加列,如下实例在表 testalter_tbl 中添加 i 字段,并定义数据类型:mysql> ALTER TABLE testalter_tbl ADD i INT;执行以上命令后,i 字段会自动添加到数据表字段的末尾。mysql> SHOW COLUMNS FROM testalter_tbl; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | c | char(1) | YES | | NULL | | | i | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.00 sec)如果你需要指定新增字段的位置,可以使用MySQL提供的关键字 FIRST (设定位第一列), AFTER 字段名(设定位于某个字段之后)。尝试以下 ALTER TABLE 语句, 在执行成功后,使用 SHOW COLUMNS 查看表结构的变化:ALTER TABLE testalter_tbl DROP i; ALTER TABLE testalter_tbl ADD i INT FIRST; ALTER TABLE testalter_tbl DROP i; ALTER TABLE testalter_tbl ADD i INT AFTER c;FIRST 和 AFTER 关键字可用于 ADD 与 MODIFY 子句,所以如果你想重置数据表字段的位置就需要先使用 DROP 删除字段然后使用 ADD 来添加字段并设置位置。修改字段类型及名称如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。例如,把字段 c 的类型从 CHAR(1) 改为 CHAR(10),可以执行以下命令:mysql> ALTER TABLE testalter_tbl MODIFY c CHAR(10);使用 CHANGE 子句, 语法有很大的不同。 在 CHANGE 关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型。尝试如下实例:mysql> ALTER TABLE testalter_tbl CHANGE i j BIGINT;<p如果你现在想把字段 j="" 从="" bigint="" 修改为="" int,sql语句如下:mysql> ALTER TABLE testalter_tbl CHANGE j j INT;ALTER TABLE 对 Null 值和默认值的影响当你修改字段时,你可以指定是否包含值或者是否设置默认值。以下实例,指定字段 j 为 NOT NULL 且默认值为100 。mysql> ALTER TABLE testalter_tbl -> MODIFY j BIGINT NOT NULL DEFAULT 100;如果你不设置默认值,MySQL会自动设置该字段默认为 NULL。修改字段默认值你可以使用 ALTER 来修改字段的默认值,尝试以下实例:mysql> ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000; mysql> SHOW COLUMNS FROM testalter_tbl; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | c | char(1) | YES | | NULL | | | i | int(11) | YES | | 1000 | | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.00 sec)你也可以使用 ALTER 命令及 DROP子句来删除字段的默认值,如下实例:mysql> ALTER TABLE testalter_tbl ALTER i DROP DEFAULT; mysql> SHOW COLUMNS FROM testalter_tbl; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | c | char(1) | YES | | NULL | | | i | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.00 sec)Changing a Table Type:修改数据表类型,可以使用 ALTER 命令及 TYPE 子句来完成。尝试以下实例,我们将表 testalter_tbl 的类型修改为 MYISAM :注意:查看数据表类型可以使用 SHOW TABLE STATUS 语句。mysql> ALTER TABLE testalter_tbl ENGINE = MYISAM;mysql> SHOW TABLE STATUS LIKE 'testalter_tbl'\G*************************** 1. row **************** Name: testalter_tbl Type: MyISAM Row_format: Fixed Rows: 0 Avg_row_length: 0 Data_length: 0Max_data_length: 25769803775 Index_length: 1024 Data_free: 0 Auto_increment: NULL Create_time: 2007-06-03 08:04:36 Update_time: 2007-06-03 08:04:36 Check_time: NULL Create_options: Comment:1 row in set (0.00 sec)修改表名如果需要修改数据表的名称,可以在 ALTER TABLE 语句中使用 RENAME 子句来实现。尝试以下实例将数据表 testalter_tbl 重命名为 alter_tbl:mysql> ALTER TABLE testalter_tbl RENAME TO alter_tbl;alter其他用途修改存储引擎:修改为myisamalter table tableName engine=myisam;删除外键约束:keyName是外键别名alter table tableName drop foreign key keyName;修改字段的相对位置:这里name1为想要修改的字段,type1为该字段原来类型,first和after二选一,这应该显而易见,first放在第一位,after放在name2字段后面alter table tableName modify name1 type1 first|after name2;
-
想进华为这样的大厂,mysql数据库不会那可不行,来看看最近几年的面试题,查漏补缺,看看你能坚持到哪里?然后针对这个不会的继续理解并学习Mysql请看题:能说下myisam 和 innodb的区别吗?myisam引擎是5.1版本之前的默认引擎,支持全文检索、压缩、空间函数等,但是不支持事务和行级锁,所以一般用于有大量查询少量插入的场景来使用,而且myisam不支持外键,并且索引和数据是分开存储的。innodb是基于聚簇索引建立的,和myisam相反它支持事务、外键,并且通过MVCC来支持高并发,索引和数据存储在一起。说下mysql的索引有哪些吧,聚簇和非聚簇索引又是什么?索引按照数据结构来说主要包含B+树和Hash索引。假设我们有张表,结构如下:create table user( id int(11) not null, age int(11) not null, primary key(id), key(age) );B+树是左小右大的顺序存储结构,节点只包含id索引列,而叶子节点包含索引列和数据,这种数据和索引在一起存储的索引方式叫做聚簇索引,一张表只能有一个聚簇索引。假设没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有的话则会隐式定义一个主键作为聚簇索引。这是主键聚簇索引存储的结构,那么非聚簇索引的结构是什么样子呢?非聚簇索引(二级索引)保存的是主键id值,这一点和myisam保存的是数据地址是不同的。最终,我们一张图看看InnoDB和Myisam聚簇和非聚簇索引的区别 图片源于网络,左为InnoDB,右为Myisam知道什么是覆盖索引和回表吗?覆盖索引指的是在一次查询中,如果一个索引包含或者说覆盖所有需要查询的字段的值,我们就称之为覆盖索引,而不再需要回表查询。而要确定一个查询是否是覆盖索引,我们只需要explain sql语句看Extra的结果是否是“Using index”即可。以上面的user表来举例,我们再增加一个name字段,然后做一些查询试试。explain select * from user where age=1; //查询的name无法从索引数据获取 explain select id,age from user where age=1; //可以直接从索引获取锁的类型有哪些呢mysql锁分为共享锁和排他锁,也叫做读锁和写锁。读锁是共享的,可以通过lock in share mode实现,这时候只能读不能写。写锁是排他的,它会阻塞其他的写锁和读锁。从颗粒度来区分,可以分为表锁和行锁两种。表锁会锁定整张表并且阻塞其他用户对该表的所有读写操作,比如alter修改表结构的时候会锁表。行锁又可以分为乐观锁和悲观锁,悲观锁可以通过for update实现,乐观锁则通过版本号实现。 你能说下事务的基本特性和隔离级别吗?事务基本特性ACID分别是:原子性指的是一个事务中的操作要么全部成功,要么全部失败。一致性指的是数据库总是从一个一致性的状态转换到另外一个一致性的状态。比如A转账给B100块钱,假设中间sql执行过程中系统崩溃A也不会损失100块,因为事务没有提交,修改也就不会保存到数据库。隔离性指的是一个事务的修改在最终提交前,对其他事务是不可见的。持久性指的是一旦事务提交,所做的修改就会永久保存到数据库中。而隔离性有4个隔离级别,分别是:read uncommit 读未提交,可能会读到其他事务未提交的数据,也叫做脏读。 用户本来应该读取到id=1的用户age应该是10,结果读取到了其他事务还没有提交的事务,结果读取结果age=20,这就是脏读。read commit 读已提交,两次读取结果不一致,叫做不可重复读。不可重复读解决了脏读的问题,他只会读取已经提交的事务。用户开启事务读取id=1用户,查询到age=10,再次读取发现结果=20,在同一个事务里同一个查询读取到不同的结果叫做不可重复读。repeatable read 可重复复读,这是mysql的默认级别,就是每次读取结果都一样,但是有可能产生幻读。serializable 串行,一般是不会使用的,他会给每一行读取的数据加锁,会导致大量超时和锁竞争的问题。那ACID靠什么保证的呢?A原子性由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sqlC一致性一般由代码层面来保证I隔离性由MVCC来保证D持久性由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复那你知道什么是间隙锁吗?间隙锁是可重复读级别下才会有的锁,结合MVCC和间隙锁可以解决幻读的问题。我们还是以user举例,假设现在user表有几条记录e data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">当我们执行:begin; select * from user where age=20 for update; begin; insert into user(age) values(10); #成功 insert into user(age) values(11); #失败 insert into user(age) values(20); #失败 insert into user(age) values(21); #失败 insert into user(age) values(30); #失败只有10可以插入成功,那么因为表的间隙mysql自动帮我们生成了区间(左开右闭)(negative infinity,10],(10,20],(20,30],(30,positive infinity)由于20存在记录,所以(10,20],(20,30]区间都被锁定了无法插入、删除。如果查询21呢?就会根据21定位到(20,30)的区间(都是开区间)。需要注意的是唯一索引是不会有间隙索引的。那分表后的ID怎么保证唯一性的呢?因为我们主键默认都是自增的,那么分表之后的主键在不同表就肯定会有冲突了。有几个办法考虑:设定步长,比如1-1024张表我们分别设定1-1024的基础步长,这样主键落到不同的表就不会冲突了。分布式ID,自己实现一套分布式ID生成算法或者使用开源的比如雪花算法这种分表后不使用主键作为查询依据,而是每张表单独新增一个字段作为唯一主键使用,比如订单表订单号是唯一的,不管最终落在哪张表都基于订单号作为查询依据,更新也一样。分表后非sharding_key的查询怎么处理呢?可以做一个mapping表,比如这时候商家要查询订单列表怎么办呢?不带user_id查询的话你总不能扫全表吧?所以我们可以做一个映射关系表,保存商家和用户的关系,查询的时候先通过商家查询到用户列表,再通过user_id去查询。打宽表,一般而言,商户端对数据实时性要求并不是很高,比如查询订单列表,可以把订单表同步到离线(实时)数仓,再基于数仓去做成一张宽表,再基于其他如es提供查询服务。数据量不是很大的话,比如后台的一些查询之类的,也可以通过多线程扫表,然后再聚合结果的方式来做。或者异步的形式也是可以的。List<Callable<List<User>>> taskList = Lists.newArrayList(); for (int shardingIndex = 0; shardingIndex < 1024; shardingIndex++) { taskList.add(() -> (userMapper.getProcessingAccountList(shardingIndex))); } List<ThirdAccountInfo> list = null; try { list = taskExecutor.executeTask(taskList); } catch (Exception e) { //do something } public class TaskExecutor { public <T> List<T> executeTask(Collection<? extends Callable<T>> tasks) throws Exception { List<T> result = Lists.newArrayList(); List<Future<T>> futures = ExecutorUtil.invokeAll(tasks); for (Future<T> future : futures) { result.add(future.get()); } return result; } }说说mysql主从同步怎么做的吧?首先先了解mysql主从同步的原理master提交完事务后,写入binlogslave连接到master,获取binlogmaster创建dump线程,推送binglog到slaveslave启动一个IO线程读取同步过来的master的binlog,记录到relay log中继日志中slave再开启一个sql线程读取relay log事件并在slave执行,完成同步slave记录自己的binglog由于mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。由此产生两个概念。全同步复制主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。半同步复制和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。
-
在银行业务中,有一条记账原则,即有借有贷,借贷相等。为了保证这种原则,每发生一笔银行业务,就必须确保会计账目上借方科目和贷方科目至少各记一笔,并且这两笔账要么同时成功,要么同时失败。如果出现只记录了借方科目,或者只记录了贷方科目的情况,就违反了记账原则。会出现记错账的情况。在银行的日常业务中,只要是同一银行(如都是中国农业银行,简称农行),一般都支持账户间的直接转账。因此,银行转账操作往往会涉及两个或两个以上的账户。在转出账户的存款减少一定金额的同时,转入账户的存款就要增加相应的金额。下面,在 MySQL 数据库中模拟一下上述提及的转账问题。假如要从张三的账户直接转账 500 元到李四的账户。首先需要创建账户表,存放用户张三和李四的账户信息。创建账户表和插入数据的 SQL 语句和运行结果如下所示:mysql> CREATE DATABASE mybank; Query OK, 1 row affected (0.02 sec) mysql> USE mybank; Database changed mysql> CREATE TABLE bank( -> customerName VARCHAR(20), #用户名 -> currentMoney DECIMAL(10,2) #当前余额 -> )ENGINE=InnoDB DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.26 sec) mysql> INSERT INTO bank (customerName,currentMoney) VALUES('张三',1000);; Query OK, 1 row affected (0.07 sec) mysql> INSERT INTO bank (customerName,currentMoney) VALUES('李四',1); Query OK, 1 row affected (0.08 sec)查询 bank 数据表的 SQL 语句和运行结果如下:mysql> SELECT * FROM bank; +--------------+--------------+ | customerName | currentMoney | +--------------+--------------+ | 张三 | 1000.00 | | 李四 | 1.00 | +--------------+--------------+ 2 rows in set (0.02 sec)结果显示,张三和李四两个账户的余额总和为 1000+1=1001 元。下面开始模拟实现转账功能。从张三的账户直接转账 500 元到李四的账户,可以使用 UPDATE 语句分别修改张三的账户和李四的账户。张三的账户减少 500 元,李四的账户增加 500 元, SQL 语句如下所示:/*转账测试:张三转账给李四 500 元*/ #张三的账户少 500 元,李四的账户多 500 元 UPDATE bank SET currentMoney = currentMoney-500 WHERE customerName = '张三'; UPDATE bank SET currentMoney = currentMoney+500 WHERE customerName = '李四';正常情况下,执行以上的转账操作后,余额总和应保持不变,仍为 1001 元。但是,如果在这个过程的其中一个环节出现差错,如在张三的账户减少 500 元之后,这时发生了服务器故障,李四的账户没有立即增加 500 元,此时,第三方读取到两个账户的余额总和变为 500+1=501 元,即账户总额间少了 500 元。MySQL 为了解决此类问题,提供了事务。事务可以将一系列的数据操作**成一个整体进行统一管理,如果某一事务执行成功,则在该事务中进行的所有数据更改均会提交,成为数据库中的永久组成部分。如果事务执行时遇到错误,则就必须取消或回滚。取消或回滚后,数据将全部恢复到操作前的状态,所有数据的更改均被清除。MySQL 通过事务保证了数据的一致性。上述提到的转账过程就是一个事务,它需要两条 UPDATE 语句来完成。这两条语句是一个整体,如果其中任何一个环节出现问题,则整个转账业务也应取消,两个账户中的余额应恢复为原来的数据,从而确保转账前和转账后的余额总和不变,即都是 1001 元。
-
2020-12-06:mysql中,多个索引会有多份数据吗?#福大大架构师每日一题#
-
数据库迁移就是把数据从一个系统移动到另一个系统上,迁移过程其实就是在源数据库备份和目标数据库恢复的过程组合。迁移的原因是多种多样的,比如:需要安装新的数据库服务器MySQL 版本更新数据库管理系统的变更(如从 SQL Server 迁移到 MySQL)根据实际操作等情况,可以将数据库迁移操作分成以下 3 种形式。相同版本 MySQL 数据库之间的迁移。不同版本 MySQL 数据库之间的迁移。不同数据库间的迁移。下面将详细介绍数据库迁移的各种方式。1. 相同版本的迁移相同版本的 MySQL 数据库是指主版本号一致的数据库。主版本号一致的数据库迁移最容易实现。由于迁移前后 MySQL 数据库的主版本号相同,所以可以通过复制数据库目录来实现数据库迁移。最安全和最常用的方式是通过使用 mysqldump 命令进行数据库备份,然后使用 mysql 命令将备份文件还原到新的 MySQL 数据库。迁移时的备份和还原操作可以同时执行。假设从一个名为 hostname1 的机器中备份出所有数据库,然后将这些数据库迁移到名为 hostname2 的机器上,具体语法形式如下:mysqldump -h hostname1 -u root -password=password1 -all-databases|mysql -h hostname2 -u root -password=password2其中:符号“|”用来实现将命令 mysqldump 备份的文件送给 mysql 命令;password1 为 hostname1 主机上 root 用户的密码;password2 为 hostname2 主机上 root 用户的密码;-all-databases 表示迁移全部的数据库,可省略。通过上述语句就可以直接迁移。2. 不同版本的迁移不同版本的 MySQL 数据库之间的数据迁移通常是 MySQL 升级的原因。例如,服务器使用 4.0 版本的 MySQL 数据库,现在要升级为 5.7 版本的。这样就需要不同版本的 MySQL 数据库之间进行数据迁移。不同版本下的数据库迁移,分为 2 种方式:低版本数据库向高版本数据库进行迁移高版本数据库向低版本数据库进行迁移低版本数据库向高版本数据库进行迁移时,由于高版本会兼容低版本,所以该种方式也是最容易实现的操作。对于存储类型为 MyISAM 的表,最安全和最常用的操作是直接复制数据文件。对于存储类型为 InnoDB 的表,最安全和最常用的操作是执行 mysqldump 命令进行备份和执行 mysql 命令还原恢复数据。但是高版本数据库向低版本数据库进行迁移时,因为高版本数据库可能有一些新的特性,这些特性是低版本数据库所不具有的,所以数据库迁移时要特别小心,最好使用 mysqldump 命令来进行备份,避免迁移时造成数据丢失。3. 不同数据库的迁移不同数据库之间的迁移是指从其它类型的数据库迁移到 MySQL 数据库,或者从 MySQL 数据库迁移到其他类型的数据库。例如,某个网站原来使用 Oracle 数据库,因为运营成本太高等诸多原因,希望改用 MySQL 数据库。或者,某个管理系统原来使用 MySQL 数据库,因为某种特殊性能的要求,希望改用 Oracle 数据库。这样的不同数据库之间的迁移也经常会发生。但是这种迁移没有普通适用的解决办法。其它数据库也有类似 mysqldump 这样的备份工具,可以将数据库中的文件备份成 sql 文件或普通文本。但是,不同的数据库厂商并没有完全按照 SQL 标准来设计数据库,这就造成了不同数据库使用的 SQL 语句的差异。例如,微软的 SQL Server 软件使用的是 T-SQL 语言。T-SQL 中包含了非标准的 SQL 语句。这就造成了 SQL Server 和 MySQL 的 SQL 语句不能兼容。除了 SQL 语句存在不兼容的情况外,不同的数据库之间的数据类型也有差异。例如,MySQL 不支持 SQL Server 中的 ntext、 Image 等数据类型。同样,SQL Server 也不支持 MySQL 中的 ENUM 和 SET 等数据类型。数据类型的差异也造成了迁移的困难。从某种意义上说,这种差异是商业数据库公司故意造成的壁垒,这种行为是阻碍数据库市场健康发展的。但是不同数据库服务器间的迁移并不是完全不可能。在 Windows 操作系统下,如果要实现从 MySQL 数据库服务器向 SQL SERVER 数据库服务器迁移,可以通过 MyODBC 来实现;如果要实现从 MySQL 数据库服务器向 ORACLE 数据库服务器迁移,可以先通过执行 mysqldump 命令导出 sql 文件,然后手动修改 sql 文件中的 CREATE 语句。数据库迁移就是把数据从一个系统移动到另一个系统上,迁移过程其实就是在源数据库备份和目标数据库恢复的过程组合。迁移的原因是多种多样的,比如:需要安装新的数据库服务器MySQL 版本更新数据库管理系统的变更(如从 SQL Server 迁移到 MySQL)根据实际操作等情况,可以将数据库迁移操作分成以下 3 种形式。相同版本 MySQL 数据库之间的迁移。不同版本 MySQL 数据库之间的迁移。不同数据库间的迁移。下面将详细介绍数据库迁移的各种方式。1. 相同版本的迁移相同版本的 MySQL 数据库是指主版本号一致的数据库。主版本号一致的数据库迁移最容易实现。由于迁移前后 MySQL 数据库的主版本号相同,所以可以通过复制数据库目录来实现数据库迁移。最安全和最常用的方式是通过使用 mysqldump 命令进行数据库备份,然后使用 mysql 命令将备份文件还原到新的 MySQL 数据库。迁移时的备份和还原操作可以同时执行。假设从一个名为 hostname1 的机器中备份出所有数据库,然后将这些数据库迁移到名为 hostname2 的机器上,具体语法形式如下:mysqldump -h hostname1 -u root -password=password1 -all-databases|mysql -h hostname2 -u root -password=password2其中:符号“|”用来实现将命令 mysqldump 备份的文件送给 mysql 命令;password1 为 hostname1 主机上 root 用户的密码;password2 为 hostname2 主机上 root 用户的密码;-all-databases 表示迁移全部的数据库,可省略。通过上述语句就可以直接迁移。2. 不用版本的迁移不同版本的 MySQL 数据库之间的数据迁移通常是 MySQL 升级的原因。例如,服务器使用 4.0 版本的 MySQL 数据库,现在要升级为 5.7 版本的。这样就需要不同版本的 MySQL 数据库之间进行数据迁移。不同版本下的数据库迁移,分为 2 种方式:低版本数据库向高版本数据库进行迁移高版本数据库向低版本数据库进行迁移低版本数据库向高版本数据库进行迁移时,由于高版本会兼容低版本,所以该种方式也是最容易实现的操作。对于存储类型为 MyISAM 的表,最安全和最常用的操作是直接复制数据文件。对于存储类型为 InnoDB 的表,最安全和最常用的操作是执行 mysqldump 命令进行备份和执行 mysql 命令还原恢复数据。但是高版本数据库向低版本数据库进行迁移时,因为高版本数据库可能有一些新的特性,这些特性是低版本数据库所不具有的,所以数据库迁移时要特别小心,最好使用 mysqldump 命令来进行备份,避免迁移时造成数据丢失。3. 不同数据库的迁移不同数据库之间的迁移是指从其它类型的数据库迁移到 MySQL 数据库,或者从 MySQL 数据库迁移到其他类型的数据库。例如,某个网站原来使用 Oracle 数据库,因为运营成本太高等诸多原因,希望改用 MySQL 数据库。或者,某个管理系统原来使用 MySQL 数据库,因为某种特殊性能的要求,希望改用 Oracle 数据库。这样的不同数据库之间的迁移也经常会发生。但是这种迁移没有普通适用的解决办法。其它数据库也有类似 mysqldump 这样的备份工具,可以将数据库中的文件备份成 sql 文件或普通文本。但是,不同的数据库厂商并没有完全按照 SQL 标准来设计数据库,这就造成了不同数据库使用的 SQL 语句的差异。例如,微软的 SQL Server 软件使用的是 T-SQL 语言。T-SQL 中包含了非标准的 SQL 语句。这就造成了 SQL Server 和 MySQL 的 SQL 语句不能兼容。除了 SQL 语句存在不兼容的情况外,不同的数据库之间的数据类型也有差异。例如,MySQL 不支持 SQL Server 中的 ntext、 Image 等数据类型。同样,SQL Server 也不支持 MySQL 中的 ENUM 和 SET 等数据类型。数据类型的差异也造成了迁移的困难。从某种意义上说,这种差异是商业数据库公司故意造成的壁垒,这种行为是阻碍数据库市场健康发展的。但是不同数据库服务器间的迁移并不是完全不可能。在 Windows 操作系统下,如果要实现从 MySQL 数据库服务器向 SQL SERVER 数据库服务器迁移,可以通过 MyODBC 来实现;如果要实现从 MySQL 数据库服务器向 ORACLE 数据库服务器迁移,可以先通过执行 mysqldump 命令导出 sql 文件,然后手动修改 sql 文件中的 CREATE 语句。
-
2020-12-04:mysql 表中允许有多少个 TRIGGERS?#福大大架构师每日一题#
-
2020-12-03:mysql中,Heap 表是什么?#福大大架构师每日一题#
-
2020-12-02:mysql中,一张表里面有 ID 自增主键,当 insert 了 17 条记录之后,删除了第 15,16,17 条记录,再把 Mysql 重启,再 insert 一条记录,这条记录的 ID 是 18 还是 15 ?#福大大架构师每日一题#
-
简而言之,性能优化就是在不影响系统能正确运行的前提下,运行速度更快,完成特定功能所需的时间更短。我们可以通过某些有效的方法来提高 MySQL 数据库的性能,目的是让 MySQL 数据库的运行速度更快、占用的磁盘空间更小。性能优化包括很多方面,例如优化查询速度、优化更新速度和优化 MySQL 服务器等。通过不同的优化方式达到提高 MySQL 数据库性能的目的。优化数据库是数据库管理员和开发人员的必备技能。下面将为读者介绍优化的基本知识。MySQL 数据库的用户和数据非常少时,很难判断数据库性能的好坏。只有当长时间运行,并且有大量用户进行频繁操作时,MySQL 数据库的性能才能体现出来。例如,一个每天有几万用户同时在线的大型网站,它的数据库性能的优劣就很明显。这么多用户同时连接 MySQL 数据库,并且进行查询、插入和更新的操作。如果 MySQL 数据库的性能很差,很可能无法承受如此多用户的同时操作。另外,如果用户查询一条记录需要花费很长时间,那么用户很难会喜欢这个网站。因此,为了提高 MySQL 数据库的性能,需要进行一系列的优化措施。一方面是找出系统的瓶颈,提高 MySQL 数据库整体的性能,另一方面需要合理的数据库结构设计和参数调整,来提高用户操作响应的速度,同时还要尽可能节省系统资源,以便系统可以提供更大负荷的服务。例如,通过优化文件系统,提高磁盘 I\O 的读写速度;通过优化操作系统调度策略,提高 MySQL 在高负荷情况下的负载能力;优化表结构、索引、查询语句等使查询响应更快。如果 MySQL 数据库中需要进行大量的查询操作,那么就需要对查询语句进行优化。对于耗费时间的查询语句进行优化,可以提高整体的查询速度。如果连接 MySQL 数据库的用户很多,那么就需要对 MySQL 服务器进行优化。否则,大量的用户同时连接 MySQL 数据库,可能会造成数据库系统崩溃。那么我们应该如何进行系统的分析,来尽快定位效率低下的 SQL 呢?主要有以下两种方法:1. 使用 SHOW STATUS 命令数据库管理员可以使用 SHOW STATUS 语句查询 MySQL 数据库的性能参数,了解各种 SQL 的执行频率。语法形式如下:SHOW STATUS LIKE 'value';其中,value 参数是常用的几个统计参数,常用参数介绍如下:Connections:连接 MySQL 服务器的次数;Uptime:MySQL 服务器的上线时间;Slow_queries:慢查询的次数;Com_select:查询操作的次数;Com_insert:插入操作的次数,对于批量插入操作,只累加一次;Com_update:更新操作的次数;Com_delete:删除操作的次数。以上参数针对于所有存储引擎的表,下面几个参数只针对 InnoDB 存储引擎。Innodb_rows_read:表示 SELECT 语句查询的记录数;Innodb_rows_inserted:表示 INSERT 语句插入的记录数;Innodb_rows_updated:表示 UPDATE 语句更新的记录数;Innodb_rows_deleted:表示 DELETE 语句删除的记录数。比如,需要查询 MySQL 服务器的连接次数,可以执行下面的 SHOW STATUS 语句:SHOW STATUS LIKE 'Connections';查询其它参数的方法和以上参数的查询方法相同。通过以上几个参数,可以很容易的了解当前数据库的应用是以插入为主还是以查询为主,以及各种类型的 SQL 语句的大致执行比例。然后根据分析结果,进行相应的性能优化。2. 使用慢查询日志慢查询次数参数可以结合慢查询日志,找出慢查询语句,然后针对慢查询语句进行表结构优化或者查询语句优化。
-
重庆高校行福利来袭【7天玩转MySQL基础实战营】课程免费学啦!活动时间2020年12月6日活动对象面向重庆大学在校大学生、开发者、数据库初学者等活动内容活动:7天玩转MySQL基础实战营课程免费学,报名送文件夹一个;https://education.huaweicloud.com/courses/course-v1:HuaweiX+CBUCNXD014+Self-paced/about奖品展示:本活动最终解释权归华为云所有。
-
MySQL 服务器可以支持多种字符集,在同一台服务器、同一个数据库甚至同一个表的不同字段中,都可以使用不同的字符集。Oracle 等其它数据库管理系统都只能使用相同的字符集,相比之下,MySQL 明显存在更大的灵活性。MySQL 的字符集和校对规则有 4 个级别的默认设置,即服务器级、数据库级、表级和字段级。它们分别在不同的地方设置,作用也不相同。服务器字符集和校对规则修改服务器默认字符集和校对规则的方法如下。1)可以在 my.ini 配置文件中设置服务器字符集和校对规则,添加内容如下:[mysqld]character-set-server=字符集名称2)连接 MySQL 服务器时指定字符集:mysql --default-character-set=字符集名称 -h 主机IP地址 -u 用户名 -p 密码如果没有指定服务器字符集,MySQL 会默认使用 latin1 作为服务器字符集。如果只指定了字符集,没有指定校对规则,MySQL 会使用该字符集对应的默认校对规则。如果要使用字符集的非默认校对规则,需要在指定字符集的同时指定校对规则。可以用 SHOW VARIABLES LIKE 'character_set_server' 和 SHOW VARIABLES LIKE 'collation_server' 命令查询当前服务器的字符集和校对规则。mysql> SHOW VARIABLES LIKE 'character_set_server'; +----------------------+--------+ | Variable_name | Value | +----------------------+--------+ | character_set_server | gbk | +----------------------+--------+ 1 row in set, 1 warning (0.01 sec) mysql> SHOW VARIABLES LIKE 'collation_server'; +------------------+-------------------+ | Variable_name | Value | +------------------+-------------------+ | collation_server | gbk_chinese_ci | +------------------+-------------------+ 1 row in set, 1 warning (0.01 sec)数据库字符集和校对规则数据库的字符集和校对规则在创建数据库时指定,也可以在创建完数据库后通过 ALTER DATABASE 命令进行修改。需要注意的是,如果数据库里已经存在数据,修改字符集后,已有的数据不会按照新的字符集重新存放,所以不能通过修改数据库的字符集来修改数据的内容。设置数据库字符集的规则如下:如果指定了字符集和校对规则,则使用指定的字符集和校对规则;如果指定了字符集没有指定校对规则,则使用指定字符集的默认校对规则;如果指定了校对规则但未指定字符集,则字符集使用与该校对规则关联的字符集;如果没有指定字符集和校对规则,则使用服务器字符集和校对规则作为数据库的字符集和校对规则。为了避免受到默认值的影响,推荐在创建数据库时指定字符集和校对规则。可以使用 SHOW VARIABLES LIKE 'character_set_database' 和 SHOW VARIABLES LIKE 'collation_database' 命令查看当前数据库的字符集和校对规则。mysql> SHOW VARIABLES LIKE 'character_set_database'; +------------------------+--------+ | Variable_name | Value | +------------------------+--------+ | character_set_database | latin1 | +------------------------+--------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW VARIABLES LIKE 'collation_database'; +--------------------+-------------------+ | Variable_name | Value | +--------------------+-------------------+ | collation_database | latin1_swedish_ci | +--------------------+-------------------+ 1 row in set, 1 warning (0.00 sec)表字符集和校对规则表的字符集和校对规则在创建表的时候指定,也可以在创建完表后通过 ALTER TABLE 命令进行修改。同样,如果表中已有记录,修改字符集后,原有的记录不会按照新的字符集重新存放。表的字段仍然使用原来的字符集。设置表的字符集规则和设置数据库字符集的规则基本类似:如果指定了字符集和校对规则,使用指定的字符集和校对规则;如果指定了字符集没有指定校对规则,使用指定字符集的默认校对规则;如果指定了校对规则但未指定字符集,则字符集使用与该校对规则关联的字符集;如果没有指定字符集和校对规则,使用数据库字符集和校对规则作为表的字符集和校对规则。为了避免受到默认值的影响,推荐在创建表的时候指定字符集和校对规则。可以使用 SHOW CREATE TABLE 命令查看当前表的字符集和校对规则,SQL 语句和运行结果如下:mysql> SHOW CREATE TABLE tb_students_info \G *************************** 1. row *************************** Table: tb_students_info Create Table: CREATE TABLE `tb_students_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, `age` int(11) DEFAULT NULL, `sex` char(1) DEFAULT NULL, `height` float DEFAULT NULL, `course_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 1 row in set (0.00 sec)列字符集和校对规则MySQL 可以定义列级别的字符集和校对规则,主要是针对相同表的不同字段需要使用不同字符集的情况。一般遇到这种情况的几率比较小,这只是 MySQL 提供给我们一个灵活设置的手段。列字符集和校对规则的定义可以在创建表时指定,或者在修改表时调整。语法格式如下:ALTER TABLE 表名 MODIFY 列名 数据类型 CHARACTER SET 字符集名;例 1修改 tb_students_info 表中 name 列的字符集,并查看。SQL 语句和运行结果如下:mysql> ALTER TABLE tb_students_info MODIFY name VARCHAR(10) CHARACTER SET gbk; Query OK, 11 rows affected (0.11 sec) Records: 11 Duplicates: 0 Warnings: 0 mysql> SHOW CREATE TABLE tb_students_info \G *************************** 1. row *************************** Table: tb_students_info Create Table: CREATE TABLE `tb_students_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) CHARACTER SET gbk DEFAULT NULL, `age` int(11) DEFAULT NULL, `sex` char(1) DEFAULT NULL, `height` float DEFAULT NULL, `course_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 1 row in set (0.00 sec)结果显示,name 列字符集修改成功。如果在创建列的时候没有特别指定字符集和校对规则,默认使用表的字符集和校对规则。连接字符集和校对规则上面所讲的 4 种设置方式,确定的都是数据保存的字符集和校对规则。实际应用中,还需要设置客户端和服务器之间交互的字符集和校对规则。对于客户端和服务器的交互操作,MySQL 提供了 3 个不同的参数:character_set_client、character_set_connection 和 character_set_results,分别代表客户端、连接和返回结果的字符集。通常情况下,这 3 个字符集是相同的,这样可以确保正确读出用户写入的数据,尤其是中文字符。字符集不同时,容易导致写入的记录不能正确读出。设置客户端和服务器连接的字符集和校对规则有以下几种方法:1)在 my.ini 配置文件中,设置以下语句:[mysql]default-character-set=gbk这样服务器启动后,所有连接默认使用 GBK 字符集进行连接。2)可以通过以下命令来设置连接的字符集和校对规则,这个命令可以同时修改以上 3 个参数(character_set_client、character_set_connection 和 character_set_results)的值。SET NAMES gbk;使用这个方法可以“临时一次性地”修改客户端和服务器连接时的字符集为 gbk。3)MySQL 还提供了下列 MySQL 命令“临时地”修改 MySQL“当前会话的”字符集和校对规则。set character_set_client = gbk;set character_set_connection = gbk;set character_set_database = gbk;set character_set_results = gbk;set character_set_server = gbk;set collation_connection = gbk_chinese_ci;set collation_database = gbk_chinese_ci;set collation_server = gbk_chinese_ci;
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签