Bootstrap

(001)mysql全接触

1. MySQL 如何优化SQL查询语句?

  正确回答通过率:73.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

建议性操作方案如下:

1:避免全表扫描
考虑在 where 和 order by 涉及的列上建立索引,in 和 not in 也要慎用,尽量用 between 取代。

2:优化 COUNT 查询
count 可以统计列的数量,统计列值时要求列非空;COUNT 还可以统计行数,当 MySQL 确定括号内的表达式不可能为 NULL 时,实际上就是在统计行数。当使用 COUNT(*) 时,会忽略所有列而直接统计行数。
某些业务场景不要求完全精确的 COUNT 值,此时可以使用近似值来代替,EXPLAIN 估算的行数就是一个不错的近似值。

3:避免子查询
在 MySQL5.5 及以下版本避免子查询,因为执行器会先执行外部的 SQL 再执行内部的 SQL,可以用关联查询代替。

4:禁止排序
当查询使用 GROUP BY 时,结果集默认会按照分组的字段进行排序,如果不关心顺序,可以使用 ORDER BY NULL 禁止排序。

5:优化分页
在偏移量非常大的时候,需要查询很多条数据再舍弃,代价非常高。最简单的优化是尽可能地使用覆盖索引扫描,而不是查询所有的列,然后做关联操作再返回所需的列。还有一种方法是从上一次取数据的位置开始扫描,避免使用 OFFSET。

6:优化 UNION
MySQL 通过创建并填充临时表的方式来执行 UNION 查询,除非确实需要消除重复的行,否则使用 UNION ALL,如果没有 ALL 关键字,MySQL 会给临时表加上 DISTINCT 选项,对整个临时表的数据做唯一性检查,代价非常高。

7:使用用户自定义变量
用户自定义变量是一个用来存储内容的临时容器,在连接 MySQL 的整个过程中都存在,可以在任何可以使用表达式的地方使用自定义变量,避免重复查询刚刚更新过的数据

2. 简述优化MySQL数据库的方法?

  正确回答通过率:49.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

1、选取合适的字段属性
MySQL支持大数据的储存,但是一般来说,数据库中的表越小查询速度越快,所以在建表的时候尽量将表的宽度设小,另一个就是在尽可能的情况下把字段设置为NOTNULL

2、使用连接(JOIN)来代替子查询(Sub-Queries)
MySQL从4.1开始就支持SQL子查询,他可以使用SELECT语句来创建一个单列的查询结果,然后将这个结果作为过滤条件用在另一个查询中比如
SELRCT FROM ** WHERE *** NOT IN(SELECT *** FROM *)
如果使用连接(JOIN)来做查询回快很多尤其使查询字段中有索引的情况下

3、使用联合(UNION)来代替手动创建的临时表
MYSQL从4.0开始支持UNION查询,它可以把需要的使用临时表的select(两条及以上)的select查询合并到一个查询中。在客户端查询会话结束之后,临时表回会自动删除,使用UNION创建查寻时,只需要把UNION作为关键字将多个select语句连接起来(select中的字段数目要相同)
SELECT Name,Age FROM one UNION
SELECT Name,Phone FROM two UNION
SELECT Name,emile FROM three

4、事务
虽然我们可以使用子查询(Sub-Queries)、连接(JIOIN)联合(UNION)来来创建各种查寻,但并不是所有的数据库操作都是可以用一条或几条SQL语句就可以完成的,大多时候我们都需要一系列的语句来完成某种工作,当同时对两个关联表操作时可能会出现一条语句操作成功后,数据库库突然出现意外,第二个没有执行成功,这样就造成数据的不完整,甚至破坏数据中的数据,为了避免发生这种情况,我i们就应该使用事务,他的作用就是,要么全成功,要么全失败,可以保证数据库的一致性和完整性
事务是以BEGIN关键字开始,以COMMIT关键字结束,在这之间的的SQL操作只要一条失败,那么,ROLLBACK命令就可以把数据库恢复到BEGIN开始之前的状态。事务还有一个重要的作用就是当多用户同时操作相同的数据源时,它可以利用锁定数据库的方法来为客户提供安全访问方式,保证用户操作不被其他用户干扰。

5、锁定表
虽然事务是维护数据库完整性的一个好方法,但是它具有独占性,有时候会影响数据库的性能所以我们可以通过使用锁定表表来实现更好的性能,使用有WRITE关键字的sql语句可以保证在UNLPCKTABLES命令执行前,不会有其他的对该表的插入,更新删除操作
LOCK TABLE one WRITE SELECT Name FROM one WHERE Age=11;

UPDATE one SET Name =“王五” WHERE Age=16; UNLOCKTABLES

6、使用外键
锁定表方法可以维护数据的完整性,但是不能确保数据的关联性。这时候我们可以使用外键。

CREATE TABLE customerinfo ( CustomerIDINT NOT NULL, PRIMARYKEY ( CustomerID ) ) TYPE = INNODB;
CREATE TABLE salesinfo (
SalesIDNT NOT NULL,
CustomerIDINT NOT NULL,
PRIMARYKEY ( CustomerID, SalesID ),
FOREIGNKEY ( CustomerID ) REFERENCES customerinfo ( CustomerID ) ON DELETE CASCADE
) TYPE = INNODB;
注意一定要使用参数ON DELETE CASCADE保证数据的一致性,使用外键时在创建表的时候一定要将表的类型定义为事务安全表InnoDB类型。

7、使用索引
建立索引是提高数据库性能的常用方法,它可以使数据库比没有索引快的多的速度检索特定的行,尤其实在有序的情况下性能会更好。
建立索引的时候尽量建在将用于JOIN,WHERE和ORDERBY排序的字段上,尽量不要在含有大量重复的值的字段建立索引

8、优化查询语句
搜索字符型字段时减少使用LIKE关键字和通配符
尽量不要使用自动类型转换
不要在列上进行运算,
不使用NOT IN和<>操作

3. MySQL数据库,一天五万条以上的增量,预计运维三年怎么优化?

 正确回答通过率:68.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

MySQL建议优化方向:

1:设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率。
2:选择合适的表字段数据类型和存储引擎,适当的添加索引。
3:mysql库主从读写分离。
4:找规律分表,减少单表中的数据量提高查询速度。
5:添加缓存机制,比如memcached,apc等。
6:不经常改动的页面,生成静态页面。
7:书写高效率的SQL。比如 SELECT * FROM TABEL 改为 SELECT field_1, field_2, field_3 FROM TABLE.

4. 如何查看 MySQL 是否处于运行状态?

 正确回答通过率:82.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

可以通过以下方法检查MySQL服务是否正常运行:

  1. 查看MySQL的进程是否存在。打开终端或命令提示符,执行命令:ps aux | grep mysql。如果MySQL的进程存在,则表示MySQL服务正在运行。
  2. 通过服务管理工具检查MySQL服务状态。在Linux系统中,可以使用service或systemctl命令,例如:service mysql status或systemctl status mysql。在Windows系统中,可以使用服务管理器(services.msc)查看MySQL服务的状态。
  3. 登录MySQL,查看是否能够连接数据库。使用MySQL客户端连接到MySQL数据库,例如:mysql -u 用户名 -p。如果能够连接成功,则表示MySQL服务正在运行。
  4. 命令行方式检查MySQL服务状态。打开终端或命令提示符,执行命令:mysqladmin -u 用户名 -p status。如果能够正常返回MySQL服务状态信息,则表示MySQL服务正在运行。

5. 如何开启或停止 MySQL 服务?

 正确回答通过率:70.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 中级

MySQL是一种广泛使用的关系型数据库管理系统,它拥有强大的数据管理功能。在使用MySQL时,我们需要了解如何启动和停止MySQL服务。
一、开启MySQL服务

  1. 打开命令提示符
    dowsdux或MacOS系统中,可以通过打开终端来打开命令提示符。
  2. 进入MySQL安装目录
    在命令提示符中输入cd加上MySQL安装目录的路径,例如:
  3. 启动MySQL服务
    在命令提示符中输入以下命令来启动MySQL服务:
    ysql -u root -p
    其中,root为MySQL管理员账户,-p表示需要输入密码。如果您没有设置MySQL管理员账户的密码,则不需要输入-p。
  4. 输入密码
    在命令提示符中输入MySQL管理员账户的密码,然后按下回车键。
  5. 检查MySQL服务是否已启动
    输入以下命令来检查MySQL服务是否已启动:
    show databases;
    如果MySQL服务已启动,则会显示MySQL中已有的数据库名称。

二、关闭MySQL服务

  1. 关闭MySQL服务
    在MySQL服务已启动的情况下,可以通过以下命令来关闭MySQL服务:
    ysqladmin
    其中,root为MySQL管理员账户,-p表示需要输入密码。
  2. 确认MySQL服务已关闭
    输入以下命令来确认MySQL服务已关闭:
    show databases;
    如果MySQL服务已关闭,则会提示无法连接到MySQL服务。

6. 如何通过 Shell 登入 MySQL?

 正确回答通过率:87.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

运行命令 mysql -u用户名 -p登陆密码

7. MySQL如何列出所有数据库?

 正确回答通过率:95.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

  1. 打开命令行窗口
    dowsdux或Mac系统中,可以打开终端窗口。

  2. 登录MySQL
    在命令行窗口中输入以下命令登录MySQL:
    ysql -u 用户名 -p
    其中,用户名为MySQL中的用户名。输入命令后按下回车键,系统会提示输入密码。输入密码后按下回车键即可登录MySQL。

  3. 查看所有数据库
    登录MySQL后,可以使用以下命令查看所有的数据库:
    show databases;
    输入命令后按下回车键,系统会列出所有的数据库名称。

8. 如何MySQL切换到某个数据库并在上面工作?

 正确回答通过率:80.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

(1)运行命令 use database_name;
(2)进入名为 database_name 的数据库。

9. MySQL如何列出某个数据库内所有表?

 正确回答通过率:73.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

在使用MySQL数据库时,经常需要查看所有的数据表。下面我们就来介绍几种查看MySQL数据库所有数据表的方法。
方法一:通过show命令查看
show tables;
运行上述命令后,会列出当前数据库中的所有数据表。
方法二:通过desc命令查看
desc table_name;
将上述命令中的table_name替换为具体的数据表名称,运行后会显示数据表中的字段信息。如果输入非数据表名称,可能会报错。
方法三:通过information_schema数据库查看
SELECT table_name FROM information_schema.tables WHERE table_schema=‘database_name’;
将上述命令中的database_name替换为具体的数据库名称,运行后会列出该数据库中的所有数据表名称。这种方法适用于无法登录MySQL服务器的情况。
总之,以上三种方法都可以帮助我们查看MySQL数据库中的所有数据表。

10. MySQL 如何获取表内所有 Field 对象的名称和类型?

 正确回答通过率:80.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

运行命令 describe 表名;

11. MYSQL支持事务吗?

  正确回答通过率:87.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

在缺省模式下,MYSQL是autocommit模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql是不支持事务的。
但是如果你的MYSQL表类型是使用InnoDB Tables 或 BDB tables的话,你的MYSQL就可以使用事务处理,使用SET AUTOCOMMIT=0就可以使MYSQL允许在非autocommit模式,在非autocommit模式下,你必须使用COMMIT来提交你的更改,或者用ROLLBACK来回滚你的更改。
示例如下:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;

12. MYSQL相比于其他数据库有哪些特点?

  正确回答通过率:82.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

MySQL是一个小型关系型数据库管理系统,开发者为瑞典MySQL AB公司,现在已经被Sun公司收购,支持FreeBSD、Linux、MAC、Windows等多种操作系统与其他的大型数据库例如Oracle、DB2、SQL Server等相比功能稍弱一些
1、可以处理拥有上千万条记录的大型数据
2、支持常见的SQL语句规范
3、可移植行高,安装简单小巧
4、良好的运行效率,有丰富信息的网络支持
5、调试、管理,优化简单(相对其他大型数据库)

13. 请简洁地描述下MySQL中InnoDB支持的四种事务隔离级别名称,以及逐级之间的区别?

  正确回答通过率:60.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

SQL标准定义的四个隔离级别为:
read uncommited:读取未提交内容
read committed:读取提交内容
repeatable read:可重读
serializable:可串行化
详细解释如下:
Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control 间隙锁)机制解决了该问题。注:其实多版本只是解决不可重复读问题,而加上间隙锁(也就是它这里所谓的并发控制)才解决了幻读问题。
Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
对于不同的事务,采用不同的隔离级别分别有不同的结果。不同的隔离级别有不同的现象。主要有下面3种现在:
1、脏读(dirty read):一个事务可以读取另一个尚未提交事务的修改数据。
2、非重复读(nonrepeatable read):在同一个事务中,同一个查询在T1时间读取某一行,在T2时间重新读取这一行时候,这一行的数据已经发生修改,可能被更新了(update),也可能被删除了(delete)。
3、幻像读(phantom read):在同一事务中,同一查询多次进行时候,由于其他插入操作(insert)的事务提交,导致每次返回不同的结果集。
不同的隔离级别有不同的现象,并有不同的锁定/并发机制,隔离级别越高,数据库的并发性就越差,4种事务隔离级别分别表现的现象

14. MySQL有关权限的表 ?

 正确回答通过率:92.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。下面分别介绍一下这些表的结构和内容:
user权限表:记录允许连接到服务器的用户帐号信息,里面的权限是全局级的。
db权限表:记录各个帐号在各个数据库上的操作权限。
table_priv权限表:记录数据表级的操作权限。
columns_priv权限表:记录数据列级的操作权限。
host权限表:配合db权限表对给定主机上数据库级操作权限作更细致的控制。这个权限表不受GRANT和REVOKE语句的影响。

15. MySQLl存储引擎有哪些?

 正确回答通过率:82.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MyISAM indexed sequential access method (有索引的顺序访问方法)
MyISAM 具有检查和修复表格的大多数工具。表格可以被压缩,而且支持全文收索
不是事务安全的,而且不支持外键。
MEMORY 也是以前的(HEAP) 该类型表存储在内存中,表的索引是哈希分布的。
merge 这些表为了查询目的,把myisam 表集合作为单个表,因此你可以在某些操作系统中避开最大文件大小的限制。
archive 这种类型的表只支持,insert ,select 不支持delete,update,replace ,不使用索引。
csv 这些表保存在服务器的单个文件中,它包含了用逗号间隔的数据。

innodb 这种表是事务安全的。提供了commit(提交) rollback(实务回滚)支持外键,比myisam慢。
修改mysql存储引擎alter table tablename type = innodb;

16. MYSQL数据库服务器性能分析的方法命令有哪些?

  正确回答通过率:54.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 中级

Show status
一些值得监控的变量值:
Bytes_received和Bytes_sent
和服务器之间来往的流量。
Com_*服务器正在执行的命令。
Created_*在查询执行期限间创建的临时表和文件。
Handler_*存储引擎操作。
Select_*不同类型的联接执行计划。
Sort_*几种排序信息。
Show session status like ‘Select’;
Show profiles
SET profiling=1;
Show profilesG
Show profile;

17. MySQL里记录货币用什么字段类型好?

  正确回答通过率:85.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

NUMERIC和DECIMAL类型被MySQL实现为同样的类型,这在SQL92标准允许。他们被用于保存值,该值的准确精度是极其重要的值,例如与金钱有关的数据。当声明一个类是这些类型之一时,精度和规模的能被(并且通常是)指定;例如:
salary DECIMAL(9,2)
在这个例子中,9(precision)代表将被用于存储值的总的小数位数,而2(scale)代表将被用于存储小数点后的位数。因此,在这种情况下,能被存储在salary列中的值的范围是从-9999999.99到9999999.99。在ANSI/ISO SQL92中,句法DECIMAL§等价于DECIMAL(p,0)。同样,句法DECIMAL等价于DECIMAL(p,0),这里实现被允许决定值p。MySQL当前不支持DECIMAL/NUMERIC数据类型的这些变种形式的任一种。这一般说来不是一个严重的问题,因为这些类型的主要益处得自于明显地控制精度和规模的能力。
DECIMAL和NUMERIC值作为字符串存储,而不是作为二进制浮点数,以便保存那些值的小数精度。一个字符用于值的每一位、小数点(如果scale>0)和“-”符号(对于负值)。如果scale是0,DECIMAL和NUMERIC值不包含小数点或小数部分。

DECIMAL和NUMERIC值得最大的范围与DOUBLE一样,但是对于一个给定的DECIMAL或NUMERIC列,实际的范围可由制由给定列的precision或scale限制。当这样的列赋给了小数点后面的位超过指定scale所允许的位的值,该值根据scale四舍五入。当一个DECIMAL或NUMERIC列被赋给了其大小超过指定(或缺省的)precision和scale隐含的范围的值,MySQL存储表示那个范围的相应的端点值。

18. MYISAM和INNODB的不同?

  正确回答通过率:94.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

主要有以下几点区别:
a)构造上的区别
MyISAM在磁盘上存储成三个文件,其中.frm文件存储表定义;.MYD (MYData)为数据文件;.MYI (MYIndex)为索引文件。
而innodb是由.frm文件、表空间(分为独立表空间或者共享表空间)和日志文件(redo log)组成。
b)事务上的区别
myisam不支持事务;而innodb支持事务。
c)锁上的区别
myisam使用的是表锁;而innodb使用的行锁(当然innodb也支持表锁)。
表级锁:直接锁定整张表,在锁定期间,其他进程无法对该表进行写操作,如果设置的是写锁,那么其他进程读也不允许,因此myisam支持的并发量低,但myisam不会出现死锁;
行级锁:只对指定的行进行锁定,其他进程还是可以对表中的其他行进行操作的。因此行锁能大大的减少数据库操作的冲突,但有时会导致死锁。
d)是否支持外键的区别
myisam不支持外键,innodb支持外键
e) select count()的区别
对于没有where的count(
)使用MyISAM要比InnoDB快得多。因为MyISAM内置了一个计数器,count(*)时它直接从计数器中读,而InnoDB必须扫描全表。
f)myisam只把索引都load到内存中,而innodb存储引擎是把数据和索引都load到内存中

19. 如何提高MySQL insert的性能?

  正确回答通过率:48.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

有如下方法:
a)合并多条 insert 为一条,即: insert into t values(a,b,c), (d,e,f) ,
原因分析:主要原因是多条insert合并后日志量(MySQL的binlog和innodb的事务让日志) 减少了,降低日志刷盘的数据量和频率,从而提高效率。通过合并SQL语句,同时也能减少SQL语句解析的次数,减少网络传输的IO。
b)修改参数 bulk_insert_buffer_size, 调大批量插入的缓存;
c)设置 innodb_flush_log_at_trx_commit = 0 ,相对于 innodb_flush_log_at_trx_commit = 1 可以十分明显的提升导入速度;
(备注:innodb_flush_log_at_trx_commit 参数对 InnoDB Log 的写入性能有非常关键的影响。该参数可以设置为0,1,2,解释如下:
   0:log buffer中的数据将以每秒一次的频率写入到log file中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file 的刷新或者文件系统到磁盘的刷新操作;
   1:在每次事务提交的时候将log buffer 中的数据都会写入到log file,同时也会触发文件系统到磁盘的同步;
   2:事务提交会触发log buffer 到log file的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。

d)手动使用事务
因为mysql默认是autocommit的,这样每插入一条数据,都会进行一次commit;所以,为了减少创建事务的消耗,我们可用手工使用事务,即START TRANSACTION;insert 。。,insert。。 commit;即执行多个insert后再一起提交;一般1000条insert 提交一次。

20. 如果insert等dml语句的性能有问题的话,或者其他问题的存在,可能造成同步延迟,所以如何有效避免同步延迟的出现?

 正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

MySQL主从同步延迟的最主要原因就是主库是多线程写,而从库只有一个线程(即slave_sql_running)来同步,所以在主库中如果有一个ddl或dml操作执行10分钟,那么这个操作在从库上同样需要执行10分钟。有人可能会问:“主库上那个相同的DDL、DML也需要执行10分,为什么slave会延时?”,答案是master可以并发,Slave_SQL_Running线程却不可以。
所以,为了减少从库的延时,我们需要平时做好以下维护:
a)尽量让主库的dml或者ddl快速执行,如提高insert的效率(方法见上);
b) 为了安全,有人可能会将主库的sync_binlog设置为1,innodb_flush_log_at_trx_commit也设置为1之类的,而slave则不需要这么高的数据安全,完全可以讲sync_binlog设置为0或者关闭binlog,innodb_flushlog也可以设置为0,来提高从库sql的执行效率。
(备注:sync_binlog是控制binlog_cache刷新到磁盘binlog频率的,而innodb_flush_log_at_trx_commit是控制redo log buffer刷新到磁盘redolog频率的。sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。如果sync_binlog>0,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1了,表示每次事务提交,MySQL都会把binlog刷下去。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。所以sync_binlog=1保证了数据安全,但是性能最差。)
c)使用比主库更好的硬件设备作为slave
d) 使用mysql 5.6新参数 slave_parallel_workers ,使从库多线程,不过,slave_parallel_workers只能支持一个实例下多个 database 间的并发复制,并不能真正做到多表并发复制。因此在较大并发负载时,slave还是没有办法及时追上master,需要想办法进行优化。
e)升级Mysql到5.7,因为mysql 5.7支持真正意义的从库多线程了,即主库多少线程,从库也多少线程。mysql 5.7号称主从复制永不丢数据(一直没时间试用过)。

21. 简述MySQ GTID的理解 ?

  正确回答通过率:65.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

GTID是mysql 5.6的新东西,用事务提交号替换binlog的位置号。不过GTID这个东西在5.6还是有很多局限性的,个人不建议用。
GTID的全称为 global transaction identifier , 可以翻译为全局事务标示符。
GTID由两部分组成:GTID = source_id:transaction_id
source_id用于标示源服务器,用server_uuid来表示,这个值在第一次启动时生成,并写入到配置文件data/auto.cnf中
transaction_id则是根据在源服务器上第几个提交的事务来确定。

22. Innodb是行锁,那什么时候会产生行锁,什么情况下会变成表锁?

 正确回答通过率:72.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

一般情况下,innodb只对指定的行进行锁定,其他进程还是可以对表中的其他行进行操作的,因此,这时候innodb加的就是行锁;
但是,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”。

23. 新创建的MySQL数据库,需要调整哪些参数?

  正确回答通过率:51.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

调整两方面的参数,即调整操作系统的和数据库my.cnf的:
a)操作系统的参数
linux参数系统的默认参数很多都是很保守的,所以需要根据服务器性能将一些参数进行加大,如我会调整nofile(最大文件句柄数)和nproc(最大线程数),将其放到最大;我会将vm.swappiness设置为0,表示最大限度使用物理内存,然后才是 swap空间;我会将net.ipv4.tcp_tw_reuse 设置为1,表示将netstat中出现的TIME-WAIT状态的sockets重用到新的TCP连接上…等等

b)数据库的参数
对于mysql来说,my.cnf的参数调整非常重要,如果采用默认值,那么是很难发挥mysql性能的。一般我会特别关注innodb_buffer_pool这个值,该值一般设置为物理内存的70%,这样就可以把mysql的表和索引最大限度的load到内存中,从而使mysql数据库性能得到大的提升;另外,我还特别关注sync_binlog和innodb_flush_log_at_trx_commit这两个值的设置,具体含义见上;还有max_user_connections ,我一般将该值设置为2000;还有innodb_lock_wait_timeout,看程序是长连接还是短连接,一般我会设置为60秒;还有innodb_log_file_size ,这个值也设置的大一点,我一般设置的为500M或1G。

24. MYSQL 如果发现CPU,或者IO压力很大,怎么定位问题?

  正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

1、首先我会用top命令和iostat命令,定位是什么进程在占用cpu和磁盘io;
2、如果是mysql的问题,我会登录到数据库,通过show full processlist命令,看现在数据库在执行什么sql语句,是否有语句长时间执行使数据库卡住;
3、执行show innodb engine status命令,查看数据库是否有锁资源争用;
4、查看mysql慢查询日志,看是否有慢sql;
5、找到引起数据库占用资源高的语句,进行优化,该建索引的建索引,索引不合适的删索引,或者根据情况kill掉耗费资源的sql语句等

25. 描述MySQL中,索引,主键,唯一索引,联合索引的区别?

  正确回答通过率:50.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

(1)索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
(2)普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。
(3)普通索引允许被索引的数据列包含重复的值,如果能确定某个数据列只包含彼此各不相同的值,在为这个数据索引创建索引的时候就应该用关键字UNIQE把它定义为一个唯一所以,唯一索引可以保证数据记录的唯一性。
(4)主键,一种特殊的唯一索引,在一张表中只能定义一个主键索引,逐渐用于唯一标识一条记录,是用关键字PRIMARY KEY来创建。
(5)索引可以覆盖多个数据列,如像INDEX索引,这就是联合索引。
(6)索引可以极大的提高数据的查询速度,但是会降低插入删除更新表的速度,因为在执行这些写操作时,还要操作索引文件。

26. mysql_fetch_row()和mysql_fetch_array()的区别 ?

 正确回答通过率:79.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

这两个函数,返回的都是一个数组,区别就是第一个函数返回的数组是只包含值,我们只能row[0],row[1],这样以数组下标来读取数据,

mysql_fetch_array()返回的数组既包含第一种,也包含键值对的形式,我们可以这样读取数据,(假如数据库的字段是 username,passwd):row[‘username‘],row[‘passwd‘。

27. MySQL 如何使用SELECT语句找到你正在运行的服务器的版本并打印出当前数据库的名称?

 正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

mysql> SELECT VERSION(), DATABASE();

±------------------------±-----------+
| VERSION() | DATABASE() |
±------------------------±-----------+
| 5.5.34-0ubuntu0.13.10.1 | NULL |
±------------------------±-----------+
1 row in set (0.06 sec)

28. 使用非运算符(!)从表”Tecmint”中列出除了”SAM”以外的所有user记录?

 正确回答通过率:83.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

mysql> SELECT * FROM Tecmint WHERE user !=SAM;

±--------------------±--------±--------±--------±--------±------+
| date | user | host | root | local | size |
±--------------------±--------±--------±--------±--------±------+
| 2001-05-14 14:42:21 | Anthony | venus | barb | venus | 98151 |
| 2001-05-15 08:50:57 | TIM | venus | phil | venus | 978 |
±--------------------±--------±--------±--------±--------±------+

29. MySQL_pconnect是什么? MySQL_connect有什么区别?

 正确回答通过率:83.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

MySQL_pconnect()打开一个持久的数据库连接,这意味着数据库不是在每次页面加载的时候被打开一个新连接,因此我们不能使用MySQL_close()来关闭一个持久的连接。
MySQL_pconnect和MySQL_connect最简要的区别是:
与MySQL_pconnect不同,MySQL_connect在每次页面被加载的时候打开连接,这个连接可以使用MySQL_close()语句来关闭。

30. 查看MySQL数据库版本及当前登录用户是什么?

 正确回答通过率:91.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

mysql -V

31. 简述什么是MySQL多实例,如何配置MySQL多实例?

 正确回答通过率:89.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

MySQL的多实例有两种方式可以实现,两种方式各有利弊。
第一种是使用多个配置文件启动不同的进程来实现多实例,这种方式的优势逻辑简单,配置简单,缺点是管理起来不太方便。
第二种是通过官方自带的mysqld_multi使用单独的配置文件来实现多实例,这种方式定制每个实例的配置不太方面,优点是管理起来很方便,集中管理。

32. MySQL 中 wait_timeout和interactive_timeout总结?

  正确回答通过率:57.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

(1)interactive_timeout:
参数含义:服务器关闭交互式连接前等待活动的秒数。交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端。
参数默认值:28800秒(8小时)

(2)wait_timeout:
参数含义:服务器关闭非交互连接之前等待活动的秒数。
在线程启动时,根据全局wait_timeout值或全局interactive_timeout值初始化会话wait_timeout值,取决于客户端类型(由mysql_real_connect()的连接选项CLIENT_INTERACTIVE定义)。

参数默认值:28800秒(8小时)

问题1:这里为什么要同时设置interactive_timeout,wait_timeout的设置才会生效?
答: 不设置interactive_timeout,wait_timeout也会生效。
问题2:interactive的值如果设置的和wait_timeout不同,为什么Interactive_timeout会覆盖wait_timeout?
答:在交互模式下(CLIENT_INTERACTIVE),interactive_timeout才生效,非交互模式下,不生效。

问题3:在进行MySQL优化时,因为interactive_timeout决定的是交互连接的时间长短,而wait_timeout决定的是非交互连接的时间长短。如果在进行连接配置时mysql_real_connect()最后一个参数client_flag不设置为CLIENT_INTERACTIVE,是不是interactive_timeout的值不会覆盖wait_timeout?
答:可以做实验试试。

问题4:为了减少长连接的数量,在设置优化时是不是可以将interactive_timeout的值设置的大些,而wait_timeout的值设置的小些?但是问题2的描述好像又不允许这样。。。

答:如2所述,在交互模式下,interactive_timeout取代wait_timeout。这样,如果有的客户端是交互模式方式连接mysql server。那么客户端的timeout受制于interactive_timeout。如果有的客户端是非交互模式,长连接mysql server。那么客户端的timeout受制于wait_timeout。(是否是交互模式的连接,由客户端决定)

33. MySQL binlog的工作模式有哪些?

  正确回答通过率:78.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

一,模式1 Row Level:日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改。
优点:
row level模式下,bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录那一条记录被修改了,修改成什么样了。所以row level的日志内容会非常清楚的记录下每一行数据修改的细节。且不会出现某些特定情况下的存储过程,或function,以及 trigger的调用和触发无法被正确复制的问题。
缺点:
row level模式下,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如有这样一条update语句:update product set owner_member_id = ‘b’ where owner_member_id = ‘a’,执行之后,日志中记录的不是这条update语句所对应额事件(MySQL以事件的形式来记录bin-log日志),而是这条语句所更新的每一条记录的变化情况,这样就记录成很多条记录被更新的很多个事件。自然,bin-log日志的量就会很大。尤其是当执行alter table之类的语句的时候,产生的日志量是惊人的。因为MySQL对于alter table之类的表结构变更语句的处理方式是整个表的每一条记录都需要变动,实际上就是重建了整个表。那么该表的每一条记录都会被记录到日志中。
二,模式2 Statement Level:每一条会修改数据的sql都会记录到 master的bin-log中。slave在复制的时候sql进程会解析成和原来master端执行过的相同的sql来再次执行。
优点:
statement level下的优点首先就是解决了row level下的缺点,不需要记录每一行数据的变化,减少bin-log日志量,节约IO,提高性能。因为他只需要记录在Master上所执行的语句的细节,以及执行语句时候的上下文的信息。
缺点:
由于他是记录的执行语句,所以,为了让这些语句在slave端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在slave端杯执行的时候能够得到和在master端执行时候相同的结果。另外就是,由于MySQL现在发展比较快,很多的新功能不断的加入,使MySQL得复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug也就越容易出现。在statement level下,目前已经发现的就有不少情况会造成MySQL的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,比如:sleep()函数在有些版本中就不能真确复制,在存储过程中使用了last_insert_id()函数,可能会使slave和master上得到不一致的id等等。由于row level是基于每一行来记录的变化,所以不会出现类似的问题。
三,模式3 Mixed
Mixed模式,可以理解为是前两种模式的结合。
Mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。
新版本中的Statment level还是和以前一样,仅仅记录执行的语句。而新版本的MySQL中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录,如果sql语句确实就是update或者delete等修改数据的语句,那么还是会记录所有行的变更

在配置文件中的参数:

复制代码 代码示例:
log-bin=mysql-bin
#binlog_format=”STATEMENT”
#binlog_format=”ROW”
binlog_format=”MIXED”
运行时在线修改参数也是可以的:

复制代码 代码示例:
mysql> SET SESSION binlog_format = ‘STATEMENT’;
mysql> SET SESSION binlog_format = ‘ROW’;
mysql> SET SESSION binlog_format = ‘MIXED’;
mysql> SET GLOBAL binlog_format = ‘STATEMENT’;
mysql> SET GLOBAL binlog_format = ‘ROW’;
mysql> SET GLOBAL binlog_format = ‘MIXED’;

34. 如何用MySQL命令进行备份和恢复?

 正确回答通过率:85.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

mysqldump -u root -p test > test.sql
mysql -u root -p test < test.sql

35. 简述MYSQL数据库锁 ?

 正确回答通过率:78.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

MySQL有三种级别的锁:表级、行级、页面级

1 表级锁
开销小,加锁快,不会发生死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低

2 行级锁
开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率最低,并发度最高

3 页面级锁
开销和加锁时间介于表级锁和行级锁之间,会出现死锁,锁定粒度和并发度一般

36. 详细阐述MySQL联合索引?

  正确回答通过率:51.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

1、联合索引是两个或更多个列上的索引。
对于联合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。
例如索引是key index (a,b,c). 可以支持a 、 a,b 、 a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。

2、利用索引中的附加列,您可以缩小搜索的范围,但使用一个具有两列的索引不同于使用两个单独的索引。
复合索引的结构与电话簿类似,人名由姓和名构成,电话簿首先按姓氏对进行排序,然后按名字对有相同姓氏的人进行排序。
如果您知道姓,电话簿将非常有用;如果您知道姓和名,电话簿则更为有用,但如果您只知道名不知道姓,电话簿将没有用处。

37. 如何判断当前MySQL是否支持分区?

 正确回答通过率:92.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

命令:show variables like ‘%partition%’ 运行结果:

mysql> show variables like ‘%partition%’;
±------------------±------+| Variable_name | Value |±------------------±------+| have_partitioning |

38. MySQL支持的分区类型有哪些?

  正确回答通过率:79.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

RANGE分区:这种模式允许将数据划分不同范围。例如可以将一个表通过年份划分成若干个分区
LIST分区:这种模式允许系统通过预定义的列表的值来对数据进行分割。按照List中的值分区,与RANGE的区别是,range分区的区间范围值是连续的。
HASH分区 :这中模式允许通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区。例如可以建立一个对表主键进行分区的表。
KEY分区 :上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的

39. MySQL查询优化的方案简述 ?

  正确回答通过率:58.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

1 开启查询缓存,优化查询
2 explain你的select查询,这可以帮你分析你的查询语句或是表结构的性能瓶颈。EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的
3 当只要一行数据时使用limit 1,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据
4 为搜索字段建索引
5 使用 ENUM 而不是 VARCHAR。如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是VARCHAR
6 Prepared StatementsPrepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。
Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击
7 垂直分表
8 选择正确的存储引擎

40. MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)的区别?

 正确回答通过率:70.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

两种存储引擎的大致区别表现在:

1.InnoDB支持事务,MyISAM不支持, 这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而MyISAM就不可以了。
2.MyISAM适合查询以及插入为主的应用。
3.InnoDB适合频繁修改以及涉及到安全性较高的应用。
4.InnoDB支持外键,MyISAM不支持。
5.从MySQL5.5.5以后,InnoDB是默认引擎。
6.InnoDB不支持FULLTEXT类型的索引。
7.InnoDB中不保存表的行数,如select count() from table时,InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含where条件时MyISAM也需要扫描整个表。
8.对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立联合索引。
9.DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的 删除,效率非常慢。MyISAM则会重建表。
10.InnoDB支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like ‘%lee%’。

41. MySQL存储引擎MyISAM与InnoDB如何选择?

  正确回答通过率:66.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

MySQL有多种存储引擎,每种存储引擎有各自的优缺点,可以择优选择使用:MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCHIVE、CSV、BLACKHOLE。

虽然MySQL里的存储引擎不只是MyISAM与InnoDB这两个,但常用的就是两个。
关于MySQL数据库提供的两种存储引擎,MyISAM与InnoDB选择使用:

INNODB会支持一些关系数据库的高级功能,如事务功能和行级锁,MyISAM不支持。

MyISAM的性能更优,占用的存储空间少,所以,选择何种存储引擎,视具体应用而定。

如果你的应用程序一定要使用事务,毫无疑问你要选择INNODB引擎。但要注意,INNODB的行级锁是有条件的。在where条件没有使用主键时,照样会锁全表。比如DELETE FROM mytable这样的删除语句。
如果你的应用程序对查询性能要求较高,就要使用MyISAM了。MyISAM索引和数据是分开的,而且其索引是压缩的,可以更好地利用内存。所以它的查询性能明显优于INNODB。压缩后的索引也能节约一些磁盘空间。MyISAM拥有全文索引的功能,这可以极大地优化LIKE查询的效率。
有人说MyISAM只能用于小型应用,其实这只是一种偏见。如果数据量比较大,这是需要通过升级架构来解决,比如分表分库,而不是单纯地依赖存储引擎。
现在一般都是选用innodb了,主要是MyISAM的全表锁,读写串行问题,并发效率锁表,效率低,MyISAM对于读写密集型应用一般是不会去选用的。

MEMORY存储引擎
MEMORY是MySQL中一类特殊的存储引擎。它使用存储在内存中的内容来创建表,而且数据全部放在内存中。这些特性与前面的两个很不同。

每个基于MEMORY存储引擎的表实际对应一个磁盘文件。该文件的文件名与表名相同,类型为frm类型。该文件中只存储表的结构。而其数据文件,都是存储在内存中,这样有利于数据的快速处理,提高整个表的效率。
值得注意的是,服务器需要有足够的内存来维持MEMORY存储引擎的表的使用。如果不需要了,可以释放内存,甚至删除不需要的表。
MEMORY默认使用哈希索引。速度比使用B型树索引快。当然如果你想用B型树索引,可以在创建索引时指定。

注意,MEMORY用到的很少,因为它是把数据存到内存中,如果内存出现异常就会影响数据。如果重启或者关机,所有数据都会消失。因此,基于MEMORY的表的生命周期很短,一般是一次性的。

42. MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景?

 正确回答通过率:50.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 中级

事务处理上方面
MyISAM:强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。
InnoDB:提供事务支持事务,外部键等高级数据库功能。具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。

锁级别
MyISAM:只支持表级锁,用户在操作MyISAM表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。
InnoDB:支持事务和行级锁,是innodb的最大特色。行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。

43. MySQL如何使用Explain优化SQL和索引?

  正确回答通过率:54.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

对于复杂、效率低的sql语句,我们通常是使用explain sql 来分析sql语句,这个语句可以打印出,语句的执行。这样方便我们分析,进行优化

table:显示这一行的数据是关于哪张表的
type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL
all:full table scan ;MySQL将遍历全表以找到匹配的行;
index: index scan; index 和 all的区别在于index类型只遍历索引;
range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值的行,常见与between ,等查询;
ref:非唯一性索引扫描,返回匹配某个单独值的所有行,常见于使用非唯一索引即唯一索引的非唯一前缀进行查找;
eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常用于主键或者唯一索引扫描;
const,system:当MySQL对某查询某部分进行优化,并转为一个常量时,使用这些访问类型。如果将主键置于where列表中,MySQL就能将该查询转化为一个常量。
possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key:实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MySQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MySQL忽略索引
key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
rows:MySQL认为必须检查的用来返回请求数据的行数
Extra:关于MySQL如何解析查询的额外信息。

44. MySQL慢查询怎么解决?

 正确回答通过率:76.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

slow_query_log 慢查询开启状态。
slow_query_log_file 慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)。
long_query_time 查询超过多少秒才记录

45. MySQL 死锁机制 ? 死锁判定原理和具体场景,死锁怎么解决?

  正确回答通过率:37.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

什么是死锁?
死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等竺的进程称为死锁进程。
表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。
死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。
那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。
死锁的解决办法?
1.查出的线程杀死 kill
SELECT trx_MySQL_thread_id FROM information_schema.INNODB_TRX;
2.设置锁的超时时间
Innodb 行锁的等待时间,单位秒。可在会话级别设置,RDS 实例该参数的默认值为 50(秒)。
生产环境不推荐使用过大的 innodb_lock_wait_timeout参数值
该参数支持在会话级别修改,方便应用在会话级别单独设置某些特殊操作的行锁等待超时时间,如下:
set innodb_lock_wait_timeout=1000;
—设置当前会话 Innodb 行锁等待超时时间,单位秒。
3.指定获取锁的顺序

46. MySQL数据库的主从复制机制简述 ?

  正确回答通过率:55.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

主从复制的几种方式:

1 同步复制:
所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,…,slave-n完成后才能返回。这样,显然不可取,也不是MySQL复制的默认设置。比如,在WEB前端页面上,用户增加了条记录,需要等待很长时间。

2 异步复制:
如同AJAX请求一样。master只需要完成自己的数据库操作即可。至于slaves是否收到二进制日志,是否完成操作,不用关心,MySQL的默认设置。

3 半同步复制:
master只保证slaves中的一个操作成功,就返回,其他slave不管。这个功能,是由google为MySQL引入的。

47. 详细描述数据库崩溃时事务的恢复机制(REDO日志和UNDO日志)?

 正确回答通过率:47.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

Undo Log:

Undo Log是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用了Undo Log来实现多版本并发控制(简称:MVCC)。
事务的原子性(Atomicity)事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在执行的过程中发生了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过。
原理Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为UndoLog)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。
之所以能同时保证原子性和持久化,是因为以下特点:
更新数据前记录Undo log。
为了保证持久性,必须将数据在事务提交前写到磁盘。只要事务成功提交,数据必然已经持久化。
Undo log必须先于数据持久化到磁盘。如果在G,H之间系统崩溃,undo log是完整的, 可以用来回滚事务。
如果在A-F之间系统崩溃,因为数据没有持久化到磁盘。所以磁盘上的数据还是保持在事务开始前的状态。

缺陷:
每个事务提交前将数据和Undo Log写入磁盘,这样会导致大量的磁盘IO,因此性能很低。
如果能够将数据缓存一段时间,就能减少IO提高性能。但是这样就会丧失事务的持久性。因此引入了另外一种机制来实现持久化,即Redo Log。

1 Undo Log:

Undo Log是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用了Undo Log来实现多版本并发控制(简称:MVCC)。
事务的原子性(Atomicity)事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在执行的过程中发生了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过。
原理Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为UndoLog)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。
之所以能同时保证原子性和持久化,是因为以下特点:
更新数据前记录Undo log。
为了保证持久性,必须将数据在事务提交前写到磁盘。只要事务成功提交,数据必然已经持久化。
Undo log必须先于数据持久化到磁盘。如果在G,H之间系统崩溃,undo log是完整的, 可以用来回滚事务。
如果在A-F之间系统崩溃,因为数据没有持久化到磁盘。所以磁盘上的数据还是保持在事务开始前的状态。

缺陷:
每个事务提交前将数据和Undo Log写入磁盘,这样会导致大量的磁盘IO,因此性能很低。
如果能够将数据缓存一段时间,就能减少IO提高性能。但是这样就会丧失事务的持久性。因此引入了另外一种机制来实现持久化,即Redo Log。

2 Redo Log:

原理和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交前,只要将Redo Log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是Redo Log已经持久化。系统可以根据Redo Log的内容,将所有数据恢复到最新的状态。

原理和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交前,只要将Redo Log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是Redo Log已经持久化。系统可以根据Redo Log的内容,将所有数据恢复到最新的状态。

48. MySQL master的写操作,slaves被动的进行一样的操作,保持数据一致性,那么slave是否可以主动的进行写操作?

  正确回答通过率:85.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

假设slave可以主动的进行写操作,slave又无法通知master,这样就导致了master和slave数据不一致了。因此slave不应该进行写操作,至少是slave上涉及到复制的数据库不可以写。实际上,这里已经揭示了读写分离的概念。

49. MySQL 主从复制中,可以有N个slave,可是这些slave又不能进行写操作,要他们干嘛?

  正确回答通过率:32.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

实现数据备份:

类似于高可用的功能,一旦master挂了,可以让slave顶上去,同时slave提升为master。

异地容灾:

比如master在北京,地震挂了,那么在上海的slave还可以继续。
主要用于实现scale out,分担负载,可以将读的任务分散到slaves上。

【很可能的情况是,一个系统的读操作远远多于写操作,因此写操作发向master,读操作发向slaves进行操作】

50. MySQL 主从复制中有master,slave1,slave2,…等等这么多MySQL数据库,那比如一个JAVA WEB应用到底应该连接哪个数据库?

 正确回答通过率:73.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

我们在应用程序中可以这样,insert/delete/update这些更新数据库的操作,用connection(for master)进行操作,

select用connection(for slaves)进行操作。那我们的应用程序还要完成怎么从slaves选择一个来执行select,例如使用简单的轮循算法。

这样的话,相当于应用程序完成了SQL语句的路由,而且与MySQL的主从复制架构非常关联,一旦master挂了,某些slave挂了,那么应用程序就要修改了。能不能让应用程序与MySQL的主从复制架构没有什么太多关系呢?

找一个组件,application program只需要与它打交道,用它来完成MySQL的代理,实现SQL语句的路由。

MySQL proxy并不负责,怎么从众多的slaves挑一个?可以交给另一个组件(比如haproxy)来完成。

这就是所谓的MySQL READ WRITE SPLITE,MySQL的读写分离。

51. 简述MySQL 和 MariaDB 的区别 ?

 正确回答通过率:72.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

1、开发公司不同

MySQL 最初由瑞典 MySQL AB 公司开发,后来被 Sun Microsystems 收购,再由 Oracle 公司收购。而 MariaDB 是由 MySQL 的创始人 Michael Widenius 开发的,后来成立了 MariaDB 基金会。现在,MariaDB 由 MariaDB 基金会和社区开发和支持,而 MySQL 由 Oracle 公司开发和支持。

2、协议不同

MariaDB 使用了 GPLv2 许可证,这意味着任何使用 MariaDB 的应用程序必须是自由和开放源代码的。而 MySQL 使用了 GPL 许可证和商业许可证。这意味着 MySQL 有一个商业版本,该版本的许可证要求付费才能使用。

3、存储引擎不同

MariaDB 支持多种存储引擎,包括 InnoDB、MyISAM、Aria、XtraDB、PBXT 等,而 MySQL 也支持这些存储引擎,但它们是作为插件的形式出现的。MariaDB 还添加了一些新的存储引擎,这些存储引擎为用户提供了更多的灵活性和选择性。

4、功能不同

MariaDB 比 MySQL 提供了更多的功能。例如,MariaDB 支持更多的数据类型、多源复制、并行复制、表空间管理、虚拟列等。此外,MariaDB 还包括更好的查询优化器、并发性能、查询缓存等,这些功能为用户提供了更好的性能和扩展性。

5、性能不同

MariaDB 比 MySQL 提供了更好的性能和扩展性。例如,MariaDB 在查询优化器方面进行了许多改进,可以更好地优化查询,提高查询性能。此外,MariaDB 还具有更好的并发性能和查询缓存,可以更好地处理高并发负载。

总之,虽然 MariaDB 和 MySQL 非常相似,但是 MariaDB 为用户提供了更好的功能和性能,因此 MariaDB 是 MySQL 的一个更好的替代品。对于那些希望使用一个自由、开源、高性能、稳定的数据库管理系统的人来说,MariaDB 绝对是一个不错的选择。

52. 如何查看 MySQL 当前版本号?

 正确回答通过率:82.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

在系统命令行下:mysql -V
连接上MySQL命令行输入:

status;
Server: MySQL
Serverversion: 5.5.45
Protocolversion: 10
或 select version();
±-----------------------+
| version() |
±-----------------------+
| 5.5.45-xxxxx |
±-----------------------+

53. 简述MySQL 有哪些数据类型?

 正确回答通过率:83.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

MySQL 数据类型非常丰富,常用类型简单介绍如下:

整数类型:BIT、BOOL、TINY INT、SMALL INT、MEDIUM INT、 INT、 BIG INT。

浮点数类型:FLOAT、DOUBLE、DECIMAL。

字符串类型:CHAR、VARCHAR、TINY TEXT、TEXT、MEDIUM TEXT、LONGTEXT、TINY BLOB、BLOB、MEDIUM BLOB、LONG BLOB。

日期类型:Date、DateTime、TimeStamp、Time、Year。

其他数据类型:BINARY、VARBINARY、ENUM、SET…

54. MySQL CHAR 和 VARCHAR的区别?

 正确回答通过率:84.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

CHAR 是固定长度的字符类型,VARCHAR 则是可变长度的字符类型,下面讨论基于在 MySQL5.0 以上版本中。

共同点

CHAR(M) 和 VARCHAR(M) 都表示该列能存储 M 个字符,注意不是字节!!

CHAR类型特点

CHAR 最多可以存储 255 个字符 (注意不是字节),字符有不同的编码集,比如 UTF8 编码 (3字节)、GBK 编码 (2字节) 等。
对于 CHAR(M) 如果实际存储的数据长度小于M,则 MySQL 会自动会在它的右边用空格字符补足,但是在检索操作中那些填补出来的空格字符会被去掉。
VARCHAR类型特点

VARCHAR 的最大长度为 65535 个字节。
VARCHAR 存储的是实际的字符串加1或2个字节用来记录字符串实际长度,字符串长度小于255字节用1字节记录,超过255就需要2字节记录。

55. VARCHAR(50) 能存放几个 UTF8 编码的汉字?

 正确回答通过率:78.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

存放的汉字个数与版本相关。

mysql 4.0 以下版本,varchar(50) 指的是 50 字节,如果存放 UTF8 格式编码的汉字时(每个汉字3字节),只能存放16 个。

mysql 5.0 以上版本,varchar(50) 指的是 50 字符,无论存放的是数字、字母还是 UTF8 编码的汉字,都可以存放 50 个。

56. 解释int(10) 和 bigint(10) 能存储的数据大小一样吗?

 正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

不一样,具体原因如下:

int 能存储四字节有符号整数。
bigint 能存储八字节有符号整数。
所以能存储的数据大小不一样,其中的数字 10 代表的只是数据的显示宽度。[^13]

显示宽度指明 Mysql 最大可能显示的数字个数,数值的位数小于指定的宽度时数字左边会用空格填充,空格不容易看出。
如果插入了大于显示宽度的值,只要该值不超过该类型的取值范围,数值依然可以插入且能够显示出来。
建表的时候指定 zerofill 选项,则不足显示宽度的部分用 0 填充,如果是 1 会显示成 0000000001。
如果没指定显示宽度, bigint 默认宽度是 20 ,int 默认宽度 11。

57. 简述InnoDB 存储引擎应用场景是什么?

 正确回答通过率:72.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

InnoDB 是 MySQL 的默认「事务引擎」,被设置用来处理大量短期(short-lived)事务,短期事务大部分情况是正常提交的,很少会回滚。

InnoDB存储引擎特性有哪些?

采用多版本并发控制(MVCC,MultiVersion Concurrency Control)来支持高并发。并且实现了四个标准的隔离级别,通过间隙锁 next-key locking 策略防止幻读的出现。

引擎的表基于聚簇索引建立,聚簇索引对主键查询有很高的性能。不过它的二级索引 secondary index 非主键索引中必须包含主键列,所以如果主键列很大的话,其他的所有索引都会很大。因此,若表上的索引较多的话,主键应当尽可能的小。另外 InnoDB 的存储格式是平台独立。

InnoDB 做了很多优化,比如:磁盘读取数据方式采用的可预测性预读、自动在内存中创建 hash 索引以加速读操作的自适应哈希索引(adaptive hash index),以及能够加速插入操作的插入缓冲区(insert buffer)等。

InnoDB 通过一些机制和工具支持真正的热备份,MySQL 的其他存储引擎不支持热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能也意味着停止读取。

58. MySQL的InnoDB 引擎的四大特性是什么?

  正确回答通过率:60.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

插入缓冲(Insert buffer)
Insert Buffer 用于非聚集索引的插入和更新操作。先判断插入的非聚集索引是否在缓存池中,如果在则直接插入,否则插入到 Insert Buffer 对象里。再以一定的频率进行 Insert Buffer 和辅助索引叶子节点的 merge 操作,将多次插入合并到一个操作中,提高对非聚集索引的插入性能。

二次写 (Double write)
Double Write 由两部分组成,一部分是内存中的 double write buffer,大小为 2MB,另一部分是物理磁盘上共享表空间连续的 128 个页,大小也为 2MB。在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是通过 memcpy 函数将脏页先复制到内存中的该区域,之后通过 doublewrite buffer 再分两次,每次 1MB 顺序地写入共享表空间的物理磁盘上,然后马上调用 fsync 函数,同步磁盘,避免操作系统缓冲写带来的问题。

自适应哈希索引 (Adaptive Hash Index)
InnoDB 会根据访问的频率和模式,为热点页建立哈希索引,来提高查询效率。索引通过缓存池的 B+ 树页构造而来,因此建立速度很快,InnoDB 存储引擎会监控对表上各个索引页的查询,如果观察到建立哈希索引可以带来速度上的提升,则建立哈希索引,所以叫做自适应哈希索引。

缓存池
为了提高数据库的性能,引入缓存池的概念,通过参数 innodb_buffer_pool_size 可以设置缓存池的大小,参数 innodb_buffer_pool_instances 可以设置缓存池的实例个数。缓存池主要用于存储以下内容:
缓冲池中缓存的数据页类型有:索引页、数据页、undo页、插入缓冲 (insert buffer)、自适应哈希索引(adaptive hash index)、InnoDB存储的锁信息 (lock info)和数据字典信息 (data dictionary)。

59. MyISAM存储引擎应用场景有哪些?

 正确回答通过率:86.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MyISAM 是 MySQL 5.1 及之前的版本的默认的存储引擎。MyISAM 提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM 不「支持事务和行级锁」,对于只读数据,或者表比较小、可以容忍修复操作,依然可以使用它。

60. 简述MyISAM存储引擎特性有哪些?

 正确回答通过率:83.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MyISAM「不支持行级锁而是对整张表加锁」。读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。但在表有读取操作的同时,也可以往表中插入新的记录,这被称为并发插入。

MyISAM 表可以手工或者自动执行检查和修复操作。但是和事务恢复以及崩溃恢复不同,可能导致一些「数据丢失」,而且修复操作是非常慢的。

对于 MyISAM 表,即使是 BLOB 和 TEXT 等长字段,也可以基于其前 500 个字符创建索引,MyISAM 也支持「全文索引」,这是一种基于分词创建的索引,可以支持复杂的查询。

如果指定了 DELAY_KEY_WRITE 选项,在每次修改执行完成时,不会立即将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区,只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写入磁盘。这种方式可以极大的提升写入性能,但是在数据库或者主机崩溃时会造成「索引损坏」,需要执行修复操作。

61. 简述 SQL 语句有哪些分类?

 正确回答通过率:92.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

DDL:数据定义语言(create alter drop)
DML:数据操作语句(insert update delete)
DTL:数据事务语句(commit collback savapoint)
DCL:数据控制语句(grant revoke)

62. 简述什么是 MySQL 视图?

 正确回答通过率:90.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

视图是虚拟表,并不储存数据,只包含定义时的语句的动态数据。

创建视图语法:

CREATE
[ORREPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = user]
[SQLSECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECKOPTION]

参数说明:

OR REPLACE:如果视图存在,则替换已有视图。
ALGORITHM:视图选择算法,默认算法是 UNDEFINED(未定义的)由 MySQL 自动选择要使用的算法。
DEFINER:指定视图创建者或定义者,如果不指定该选项,则创建视图的用户就是定义者。
SQL SECURITY:SQL 安全性,默认为 DEFINER。
select_statement:创建视图的 SELECT 语句,可以从基表或其他视图中选择数据。
WITH CHECK OPTION:表示视图在更新时保证约束,默认是 CASCADED。
使用 MySQL 视图有何优点?

操作简单方便。视图用户完全不需要关心视图对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
数据更加安全。视图用户只能访问视图中的结果集,通过视图可以把对表的访问权限限制在某些行和列上面。
数据隔离。屏蔽了源表结构变化对用户带来的影响,源表结构变化视图结构不变。

63. MySql 服务默认端口号是多少 ?

 正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

默认端口是 3306

查看端口命令:> show variables like ‘port’;

64. 简述MySQL存储过程的机制 ?

  正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

存储过程是一组为了完成特定功能的 SQL 语句集合。使用存储过程的目的是将常用或复杂的工作预先用 SQL 语句写好并用一个指定名称存储起来,这个过程经编译和优化后存储在数据库服务器中,因此称为存储过程。当以后需要数据库提供与已定义好的存储过程的功能相同的服务时,只需调用“CALL存储过程名字”即可自动完成。

常用操作数据库的 SQL 语句在执行的时候需要先编译,然后执行。存储过程则采用另一种方式来执行 SQL 语句。

一个存储过程是一个可编程的函数,它在数据库中创建并保存,一般由 SQL 语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的特定功能时,存储过程尤为合适。

MySQL 5.0 版本以前并不支持存储过程,这使 MySQL 在应用上大打折扣。MySQL 从 5.0 版本开始支持存储过程,既提高了数据库的处理速度,同时也提高了数据库编程的灵活性

存储过程是数据库中的一个重要功能,存储过程可以用来转换数据、数据迁移、制作报表,它类似于编程语言,一次执行成功,就可以随时被调用,完成指定的功能操作。

使用存储过程不仅可以提高数据库的访问效率,同时也可以提高数据库使用的安全性。

对于调用者来说,存储过程封装了 SQL 语句,调用者无需考虑逻辑功能的具体实现过程。只是简单调用即可,它可以被 Java 和 C#等编程语言调用。

编写存储过程对开发者要求稍微高一些,但这并不影响存储过程的普遍使用,因为存储过程有如下优点:

  1. 封装性
    通常完成一个逻辑功能需要多条 SQL 语句,而且各个语句之间很可能传递参数,所以,编写逻辑功能相对来说稍微复杂些,而存储过程可以把这些 SQL 语句包含到一个独立的单元中,使外界看不到复杂的 SQL 语句,只需要简单调用即可达到目的。并且数据库专业人员可以随时对存储过程进行修改,而不会影响到调用它的应用程序源代码。
  2. 可增强 SQL 语句的功能和灵活性
    存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
  3. 可减少网络流量
    由于存储过程是在服务器端运行的,且执行速度快,因此当客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而可降低网络负载。
  4. 高性能
    当存储过程被成功编译后,就存储在数据库服务器里了,以后客户端可以直接调用,这样所有的 SQL 语句将从服务器执行,从而提高性能。但需要说明的是,存储过程不是越多越好,过多的使用存储过程反而影响系统性能。
  5. 提高数据库的安全性和数据的完整性
    存储过程提高安全性的一个方案就是把它作为中间组件,存储过程里可以对某些表做相关操作,然后存储过程作为接口提供给外部程序。这样,外部程序无法直接操作数据库表,只能通过存储过程来操作对应的表,因此在一定程度上,安全性是可以得到提高的。
  6. 使数据独立
    数据的独立可以达到解耦的效果,也就是说,程序可以调用存储过程,来替代执行多条的 SQL 语句。这种情况下,存储过程把数据同用户隔离开来,优点就是当数据表的结构改变时,调用表不用修改程序,只需要数据库管理者重新编写存储过程即可。

65. MySQL的存储过程常见命令 ?

  正确回答通过率:73.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

创建存储过程

关键字:CREATE、PROCEDURE
语法格式:
CREATE PROCEDURE 存储过程名(参数1, 参数2, … ) COMMENT ‘描述文字’
BEGIN
SELECT语句;
END;
分隔符: MySQL命令行客户机的分隔符为:‘;’,而MySQL语句分隔符也是:‘;’,所以如果使用MySQL命令行实用程序创建或执行存储过程,则需要临时更改MySQL命令行实用程序的语句分隔符,来保证存储过程中的SQL语句作为其成分而且不出现句法错误。具体步骤如下:

1)临时修改命令行实用程序的语句分隔符:DELIMITER //
2)同时,标志存储过程结束的END定义为END //而不是END ;
3)存储过程执行完成后,恢复命令行实用程序的语句分隔符:DELIMITER ; 。
注意:除\符号外,任何字符都可以用作语句分隔符。
完整代码:
DELIMITER //
CREATE PROCEDURE 存储过程名(参数1, 参数2, … ) COMMENT ‘描述文字’
BEGIN
SELECT语句;
END //
DELIMITER ;
举例:
#创建存储过程:
DELIMITER //
CREATE PROCEDURE productpricing()
BEGIN
SELECT Avg(prod_price) AS priceaverage FROM products;
END //
DELIMITER ;
#执行存储过程:
CALL productpricing();
参数类型:

每个参数必须具有指定的类型
MySQL支持的参数类型:
IN(传递给存储过程)
OUT(从存储过程传出,关键字OUT指出相应的参数用来从存储过程传出一个值(返回给调用者)
INOUT(对存储过程传入和传出)
参数定义格式:
基本格式:IN/OUT/INOUT 变量名 变量的数据类型
变量(variable)内存中一个特定的位置,用来临时存储数据。所有MySQL变量都必须以@开始。
参数变量也需要指定其数据类型。参数变量的数据类型:存储过程的参数允许的数据类型与表中使用的数据类型相同。
常用数据类型:INT、DECIMAL、DOUBLE、FLOAT、BOOLEAN、CHAR、VARCHAR、TEXT、DATE、TIME、DATETIME、YEAR
多个参数用英文逗号,分隔,最后一个参数后不需要逗号
参数使用: 存储过程的代码位于BEGIN和END语句内,它们是一系列SELECT语句,用来检索值,一般存储过程并不显示结果,而是把结果保存到相应的变量(通过指定INTO关键字),然后再通过SELECT @参数变量名; 来显示结果数据或者将其用于其他处理程序中。

执行有参数的存储过程:

在创建存储过程时指定了n个参数,则在调用此存储过程时就必须传递n个参数,不能多也不能少。
在执行时并不会显示任何数据。它通过SELECT @参数变量名; 来显示变量的值或者用在其他处理程序中。
例1:
‘’‘创建存储过程:此存储过程接受3个参数:pl存储产品最低价格,ph存储产品最高价格,pa存储产品平均价格。
每个参数必须具有指定的类型,这里使用十进制值。关键字OUT指出相应的参数用来从存储过程传出一个值(返回给调用者)。’‘’
CREATE PROCEDURE productpricing(OUT pl DECIMAL(8, 2), OUT ph DECIMAL(8, 2), OUT pa DECIMAL(8, 2))
BEGIN
SELECT Min(prod_price) INTO pl FROM products;
SELECT Max(prod_price) INTO ph FROM products;
SELECT Avg(prod_price) INTO pa FROM products;
END;
#执行存储过程(这条语句并不显示任何数据):
CALL productpricing(@pricelow, @pricehigh, @priceaverage);
#显示检索出的产品平均价:*
SELECT @priceaverage;
#显示检索出的产品最低价、最高价和平均价:
SELECT @pricelow, @pricehigh, @priceaverage;
例2:
‘’‘创建存储过程:此存储过程使用IN和OUT参数。ordertotal接受订单号并返回该订单的合计。
onumber定义为IN,因为订单号被传入存储过程。ototal定义为OUT,因为要从存储过程返回合计。
SELECT语句使用这两个参数,WHERE子句使用onumber选择正确的行,INTO使用ototal存储计算出来的合计:’‘’
CREATE PROCEDURE ordertotal(IN onumber INT, OUT ototal DECIMAL(8, 2))
BEGIN
SELECT Sum(item_price* quantity) FROM orderitems WHERE order_num = onumber INTO ototal;
END;
#执行存储过程(调用这个新存储过程):必须给ordertotal传递两个参数;第一个参数为订单号,第二个参数为包含计算出来的合计的变量名:
CALL ordertotal(20005, @total);
#显示此合计(@total已由ordertotal的CALL语句填写,SELECT显示它包含的值):
SELECT @total;
#显示另一个订单的合计:再次调用存储过程,然后重新显示变量:
CALL ordertotal(20009, @total);
SELECT @total;
执行存储过程:

关键字:CALL
语法格式:CALL 存储过程名(@参数1, @参数2, … )
注意:因为存储过程实际上是一种函数,所以存储过程名后需要有()符号(即使不传递参数也需要)。
举例:
#创建ordertotal存储过程:
CREATE PROCEDURE ordertotal()
BEGIN
SELECT语句;
END;
#执行ordertotal存储过程:
CALL ordertotal();
删除存储过程:

关键字:DROP、PROCEDURE
语法格式一:DROP PROCEDURE 存储过程名;
语法格式二:DROP PROCEDURE IF EXISTS 存储过程名;
仅当存在时删除,当过程存在则删除,如果过程不存在也不产生错误。
举例:
#创建ordertotal存储过程:
CREATE PROCEDURE ordertotal()
BEGIN
SELECT语句;
END;
#删除ordertotal存储过程:
DROP PROCEDURE ordertotal;
DROP PROCEDURE IF EXISTS ordertotal;
检查存储过程:

关键字:SHOW
语法格式一:SHOW CREATE PROCEDURE 存储过程名;
显示用来创建一个存储过程的CREATE语句
语法格式二:SHOW CREATE PROCEDURE STATUS;
显示包括何时、由谁创建等详细信息的存储过程列表
语法格式三:SHOW CREATE PROCEDURE STATUS LIKE ‘存储过程名’;
显示某个存储过程的详细信息
举例:
#创建ordertotal存储过程:
CREATE PROCEDURE ordertotal()
BEGIN
SELECT语句;
END;
#检查存储过程:
SHOW CREATE PROCEDURE ordertotal;
SHOW CREATE PROCEDURE STATUS LIKE ‘ordertotal’;
建立智能存储过程: 存储过程内包含业务规则和智能处理

应用场景:你需要获得与以前一样的订单合计,但需要对合计增加营业税,不过只针对某些顾客(或许是你所在州中那些顾客)。那么,你需要做下面几件事情:获得合计(与以前一样);把营业税有条件地添加到合计;返回合计(带或不带税)。

66. 简述MySQL游标 ?

 正确回答通过率:89.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

定义:游标(cursor)是一个存储在MySQL服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。

游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改。

注意:MySQL游标只能用于存储过程(和函数)。存储过程处理完成后,游标就消失(因为它局限于存储过程)。

67. 简述MySQL游标常见执行命令 ?

  正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

创建游标:

关键字:DECLARE
语法格式:DECLARE 游标名 CURSOR FOR SELECT语句;
DECLARE语句的次序:DECLARE语句的发布存在特定的次序。用DECLARE语句定义的局部变量必须在定义任意游标或句柄之前定义,而句柄必须在游标之后定义。不遵守此顺序将产生错误消息。即:DECLARE 局部变量,DECLARE 游标,DECLARE 句柄
举例:
CREATE PROCEDURE processorders()
BEGIN
DECLARE ordernumbers CURSOR
FOR SELECT order_num FROM orders;
END;
打开/关闭游标:

打开游标:OPEN 游标名;
关闭游标:CLOSE 游标名;
隐含关闭:MySQL将会在到达END语句时自动关闭它。
注意:
在处理OPEN语句时执行查询,存储检索出的数据以供浏览和滚动。
CLOSE释放游标使用的所有内部内存和资源,因此在每个游标不再需要时都应该关闭。
在一个游标关闭后,再次使用游标需要再用OPEN语句打开它,但使用声明过的游标不需要再次声明。
举例:
CREATE PROCEDURE processorders()
BEGIN
#Declare the cursor
DECLARE ordernumbers CURSOR
FOR SELECT order_num FROM orders;
#Open the cursor
OPEN ordernumbers;
#Close the cursor
CLOSE ordernumbers;
END;
解析: 这个存储过程只是声明、打开和关闭一个游标,并未对检索出的数据做其他操作。
使用游标数据:

关键字:FETCH
FETCH指定检索什么数据(所需的列),检索出来的数据存储在什么地方。它还向前移动游标中的内部行指针,使下一条FETCH语句检索下一行(不重复读取同一行)。
步骤:
1)在能够使用游标前,必须声明(定义)它。这个过程实际上没有检索数据,它只是定义要使用的SELECT语句。在声明游标后,可根据需要频繁地打开和关闭游标。
2)一旦声明后,必须打开游标以供使用。这个过程用前面定义的SELECT语句把数据实际检索出来。在游标打开后,可根据需要频繁地执行取操作。
3)对于填有数据的游标,根据需要取出(检索)各行。
4)在结束游标使用时,必须关闭游标。
例1:从游标中检索单个行(第一行)
CREATE PROCEDURE processorders()
BEGIN
#Declare local variables
DECLARE o INT;
#Declare the cursor
DECLARE ordernumbers CURSOR
FOR SELECT order_num FROM orders;
#Open the cursor
OPEN ordernumbers;
#Get order number
FETCH ordernumbers INTO o;
#Close the cursor
CLOSE ordernumbers;
END;
解析:FETCH用来检索当前行的order_num列(将自动从第一行开始)到一个名为o的局部声明的变量中。对检索出的数据不做任何处理。
例2:循环检索数据,从第一行到最后一行
CREATE PROCEDURE processorders()
BEGIN
#Declare local variables
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
#Declare the cursor
DECLARE ordernumbers CURSOR
FOR SELECT order_num FROM orders;
#Declare continue handler
DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000’ SET done = 1;
#Open the cursor
OPEN ordernumbers;
#Loop through all rows
REPEAT
#Get order number
FETCH ordernumbers INTO o;
#End of loop
UNTIL done END REPEAT;
#Get order number
FETCH ordernumbers INTO o;
#Close the cursor
CLOSE ordernumbers;
END;
解析:
1)用一个DEFAULT 0(假,不结束)定义变量done(DECLARE done BOOLEAN DEFAULT 0;)。
2)定义一个CONTINUE HANDLER(DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000’ SET done = 1;),它是在条件出现时被执行的代码。这里,它指出当SQLSTATE '02000’出现时,SET done=1。SQLSTATE’02000’是一个未找到条件,当REPEAT由于没有更多的行供循环而不能继续时,出现这个条件。出现这个未找到的条件后就将done设置为真。
3)在REPEAT内,反复执行FETCH检索当前order_num到声明的名为o的变量中,直到done为真(由UNTIL done END REPEAR; 规定)。
4)如果调用这个存储过程,它将定义几个变量和一个CONTINUE HANDLER,定义并打开一个游标,重复读取所有行,然后关闭游标。如果一切正常,你可以在循环内放入任意需要的处理(在FETCH语句之后,循环结束之前)。
5)MySQL还支持循环语句,它可用来重复执行代码,直到使用LEAVE语句手动退出为止。通常REPEAT语句的语法使它更适合于对游标进行循环。
例3:对循环取出的数据进行某种实际的处理
CREATE PROCEDURE processorders()
BEGIN
#Declare local variables
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8,2);
#Declare the cursor
DECLARE ordernumbers CURSOR
FOR SELECT order_num FROM orders;
#Declare continue handler
DECLARE CONTINUE HANDLER
FOR SQLSTATE ‘02000’ SET done = 1;
#Create a table to store the results
CREATE TABLE IF NOT EXISTS ordertotals(
order_num INT,
total DECIMAL(8, 2));
#Open the cursor
OPEN ordernumbers;
#Loop through all rows
REPEAT
#Get order number
FETCH ordernumbers INTO o;
#Get the total for this order
CALL ordertotal(o, 1, t);
#Insert order and total into ordertotals
INSERT INTO ordertotals(order_num, total)
VALUES(o, t);
#End of loop
UNTIL done END REPEAT;
#Close the cursor
CLOSE ordernumbers;
END;
解析:
1)增加了另一个名为t的变量(存储每个订单的合计)
2)此存储过程还在运行中创建了一个新表(如果它不存在的话),名为ordertotals。这个表将保存存储过程生成的结果。
3)FETCH像以前一样取每个order_num,然后用CALL执行另一个存储过程ordertotal(在介绍存储过程的内容中创建)来计算每个订单的带税的合计(结果存储到t)。
4)最后,用INSERT保存每个订单的订单号和合计。
5)此存储过程不返回数据,但它能够创建和填充另一个表,可以用一条简单的SELECT语句查看该表:SELECT * FROM ordertotals;
6)这是一个集存储过程、游标、逐行处理以及存储过程调用其他存储过程的一个完整的工作样例。

68. 简述MySQL触发器 ?

 正确回答通过率:92.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

定义:触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句):DELETE、INSERT、UPDATE;其他MySQL语句不支持触发器。

69. 简述MySQL触发器常见执行命令 ?

  正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

创建触发器:

基本信息:
唯一的触发器名。为了保持每个数据库的触发器名唯一,在MySQL 5中,最好是在数据库范围内使用唯一的触发器名。虽然触发器名在每个数据库中可以不唯一但最好命名时保证每个数据库范围内的触发器名唯一。
触发器关联的表;
触发器应该响应的活动(DELETE、INSERT或UPDATE);
触发器何时执行(处理之前或之后)。
关键字:CREATE、TRIGGER
语法格式:CREATE TRIGGER 触发器名 BEFORE/AFTER DELETE/INSERT/UPDATE ON 表名 FOR EACH ROW … ;
INSERT触发器: INSERT触发器在INSERT语句执行之前或之后执行。

注意:
在INSERT触发器代码内,可引用一个名为NEW的虚拟表,访问被插入的行;
在BEFORE INSERT触发器中,NEW中的值也可以被更新(允许更改被插入的值);
对于AUTO_INCREMENT列,NEW在INSERT执行之前包含0,在INSERT执行之后包含新的自动生成值。
举例:
CREATE TRIGGER neworder
AFTER INSERT ON orders
FOR EACH ROW SELECT NEW.order_num;
解析: 此代码创建一个名为neworder的触发器,它按照AFTER INSERT ON orders执行。此触发器必须按照AFTER INSERT执行,因为在BEFORE INSERT语句执行之前,新order_num还没有生成。对于orders的每次插入使用这个触发器将总是返回新的订单号。在插入一个新订单到orders表时,MySQL生成一个新订单号并保存到order_num中。触发器从NEW.order_num取得这个值并返回它。
测试此触发器:
INSERT INTO orders(order_date, cust_id) VALUES(Now(), 10001);
解析:orders包含3个列。order_date和cust_id必须给出,order_num由MySQL自动生成,而现在order_num还自动被返回。
注意:BEFORE或AFTER,BEFORE多用于数据验证和净化(目的是保证插入表中的数据确实是需要的数据)。
DELETE触发器: DELETE触发器在DELETE语句执行之前或之后执行。在DELETE触发器代码内,你可以引用一个名为OLD的虚拟表,访问被删除的行;OLD中的值全都是只读的,不能更新。

举例:
CREATE TRIGGER deleteorder
BEFORE DELETE ON orders FOR EACH RAW
BEGIN
INSERT INTO archive_orders(
order_num,
order_date,
cust_id)
VALUES(
OLD.order_num,
OLD.order_date,
OLD.cust_id);
END;
解析: 在任意订单被删除前将执行此触发器。它使用一条INSERT语句将OLD中的值(要被删除的订单)保存到一个名为archive_orders的存档表中(为实际使用这个例子,你需要用与orders相同的列创建一个名为archive_orders的表)。
使用BEFORE DELETE触发器的优点(相对于AFTER DELETE触发器来说)为,如果由于某种原因,订单不能存档,DELETE本身将被放弃。
多语句触发器:触发器deleteorder使用BEGIN和END语句标记触发器体。使用BEGIN END块的好处是触发器能容纳多条SQL语句(在BEGIN END块中一条挨着一条)。
UPDATE触发器: UPDATE触发器在UPDATE语句执行之前或之后执行。

在UPDATE触发器代码中,你可以引用一个名为OLD的虚拟表访问以前(UPDATE语句前)的值,引用一个名为NEW的虚拟表访问新更新的值;
在BEFORE UPDATE触发器中,NEW中的值可能也被更新(允许更改将要用于UPDATE语句中的值);
OLD中的值全都是只读的,不能更新。
举例:
CREATE TRIGGER updatevendor
BEFORE UPDATE vendors
FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state);
解析: 任何数据净化都需要在UPDATE语句之前进行,就像这个例子中一样。每次更新一个行时,NEW.vend_state中的值(将用来更新表行的值)都用Upper(NEW.vend_state)替换。
删除触发器:

关键字:DROP
语法格式:DROP TRIGGER 触发器名;
举例:DROP TRIGGER newproduct;
注意:触发器不能更新或覆盖。为了修改一个触发器,必须先删除它,然后再重新创建。
应用场景:
每当增加一个顾客到某个数据库表时,都检查其电话号码格式是否正确,州的缩写是否为大写;
每当订购一个产品时,都从库存数量中减去订购的数量;
无论何时删除一行,都在某个存档表中保留一个副本。
以上三个共同之处在于需要在某个表发生更改时自动处理。
注意:
与其他DBMS相比,MySQL 5中支持的触发器相当初级。
创建触发器可能需要特殊的安全访问权限,但是,触发器的执行是自动的。如果INSERT、UPDATE或DELETE语句能够执行,则相关的触发器也能执行。
应该用触发器来保证数据的一致性(大小写、格式等)。在触发器中执行这种类型的处理的优点是它总是进行这种处理,而且是透明地进行,与客户机应用无关。
触发器的一种非常有意义的使用是创建审计跟踪。使用触发器,把更改(如果需要,甚至还有之前和之后的状态)记录到另一个表非常容易。
MySQL触发器中不支持CALL语句。这表示不能从触发器内调用存储过程。所需的存储过程代码需要复制到触发器内

70. 简述MySQL的事务处理机制 ?

 正确回答通过率:82.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

一: 事务(Transaction)就是用户定义的一系列数据库操作,这些操作可以视为一个完成的逻辑处理工作单元,要么全部执行,要么全部不执行,是不可分割的工作单元。

二:事务的使用
(a)begin transaction表示事务的开启标记。
(b)commit表示事务的提交操作,表示该事务的结束,此时将事务中处理的数据刷到磁盘中(物理数据库磁盘中去)。
©rollback表示事务的回滚操作,表示事务异常结束,此时将事务中已经执行的操撤销回原来的状态。

三:事务产生的过程:
DBMS系统必须对这种并发操作提供一种相应的处理机制来保证,访问彼此之间不受任何干扰,从而保证数据库的正确性不受到破坏,为了避免数据库的不一致性,这种处理机制称之为“并发控制”,其中事务就是为了保证数据的一致性而产生的一种概念和手段(事务不是唯一手段)。

71. MySQL事务的特征 ?

  正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

为了保证数据库的正确性与一致性事物具有四个特征

1、原子性(Atomicity)
事务的原子性保证事务中包含的一组更新操作是原子的,不可分割的,不可分割是事务最小的工作单位,所包含的操作被视为一个整体,执行过程中遵循“要么全部执行,要不都不执行”,不存在一半执行,一半未执行的情况。

2、一致性(Consistency)
事务的一致性要求事务必须满足数据库的完整性约束,且事务执行完毕后会将数据库由一个一致性的状态变为另一个一致性的状态。事务的一致性与原子性是密不可分的。

3、隔离性(lsolation)
事务的隔离性要求事务之间是彼此独立的,隔离的。及一个事务的执行不可以被其他事务干扰。具体到操作是指一个事务的操作必须在一个事务commit之后才可以进行操作。多事务并发执行时,相当于将并发事务变成串行事务,顺序执行,如同串行调度般的执行事务。

4、持续性(Durability)
事物的持续性也称持久性,是指一个事务一旦提交,它对数据库的改变将是永久性的,因为数据刷进了物理磁盘了,其他操作将不会对它产生任何影响。

72. MySQL并发事务可能产生的问题 ?

 正确回答通过率:83.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

并发事务可能引起的事情:

1.脏读:
对于两个事务T1 和T2 , T1 读取了已经被T2 更新但还没有被提交的字段。之后,若T2 进行回滚,T1读取的内容就是临时且无效的

2.不可重复读:
对于两个事务T1 和T2 , T1 读取了一个字段,然后T2 更新了该字段。之后,T1再次读取同一个字段,值就不同了

3.幻读:
对于两个事务T1,T2,T1从表中都去了一个字段,然后T2在该表中插入了一些新的行,之后,如果T1再次读取同一个表,就会多出几行

73. MySQL的事务的隔离级别 ?

  正确回答通过率:81.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

常用的事务隔离级别类型:

类型一:RU(READ-UNCOMMITTED 表示读未提交)
可以读取到事务未提交的数据,隔离性差,会出现脏读(当前内存读),不可重复读,幻读问题;

类型二:RC(READ-COMMITTED 表示读已提交)可用可以读取到事务已提交的数据,隔离性一般,不会出现脏读问题,但是会出现不可重复读,幻读问题;

类型三:RR(REPEATABLE-READ 表示可重复读)默认可以防止脏读(当前内存读),防止不可重复读问题,防止会出现的幻读问题,但是并发能力较差;
会使用next lock锁进制,来防止幻读问题,但是引入锁进制后,锁的代价会比较高,比较耗费CPU资源,占用系统性能;

类型四:SR(SERIALIZABLE 可串行化)
隔离性比较高,可以实现串行化读取数据,但是事务的并发度就没有了;这是事务的最高级别,在每条读的数据上,加上锁,使之不可能相互冲突

设置隔离级别
set session transaction isolation level read committed;
set session|global transaction isolation level 隔离级别;

74. MySQL 主键使用自增ID还是UUID?

  正确回答通过率:68.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

推荐使用自增ID,不要使用UUID。

因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说, 主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序), 如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID, 由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。

总之,在数据量大一些的情况下,用自增主键性能会好一些。

关于主键是聚簇索引,如果没有主键,InnoDB会选择一个唯一键来作为聚簇索引,如果没有唯一键,会生成一个隐式的主键。

75. MySQL数据库CPU飙升到100%的话怎么处理?

  正确回答通过率:63.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

当 cpu 飙升到 100%时,先用操作系统命令 top 命令观察是不是 mysqld 占用导致的。

如果不是,找出占用高的进程,并进行相关处理。

如果是 mysqld 造成的, show processlist,看看里面跑的 session 情况,是不是有消耗资源的 sql 在运行。找出消耗高的 sql,看看执行计划是否准确,index 是否缺失,或者实在是数据量太大造成。

一般来说,肯定要 kill 掉这些线程(同时观察 cpu 使用率是否下降), 等进行相应的调整(比如说加索引、改 sql、改内存参数)之后,再重新跑这些 SQL。

也有可能是每个 sql 消耗资源并不多,但是突然之间,有大量的 session 连进来导致 cpu 飙升, 这种情况就需要跟应用一起来分析为何连接数会激增, 再做出相应的调整,比如说限制连接数等。

76. 简述MySQL的GTID?

 正确回答通过率:93.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

TID(Global Transaction ID,全局事务ID)是全局事务标识符, 是一个已提交事务的编号,并且是一个全局唯一的编号。
GTID是从MySQL 5.6版本开始在主从复制方面推出的重量级特性。
GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识。
GTID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。

GTID有如下几点作用:

1 根据GTID可以知道事务最初是在哪个实例上提交的。
2 GTID的存在方便了Replication的Failover。 因为不用像传统模式复制那样去找master_log_file和master_log_pos。
3 基于GTID搭建主从复制更加简单, 确保每个事务只会被执行一次。

77. 简述MySQL备份计划如何制定 ?

 正确回答通过率:91.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

视库的大小来定,一般来说 100G 内的库,可以考虑使用 mysqldump 来做, 因为 mysqldump更加轻巧灵活,备份时间选在业务低峰期, 可以每天进行都进行全量备份(mysqldump 备份出来的文件比较小,压缩之后更小)。
100G 以上的库,可以考虑用 xtranbackup 来做,备份速度明显要比 mysqldump 要快。
一般是选择一周一个全备,其余每天进行增量备份,备份时间为业务低峰期。

78. Innodb为什么要用自增id作为主键?

 正确回答通过率:51.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置, 频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE(optimize table)来重建表并优化填充页面

79. Hash 索引和 B+ 树索引有什么区别 ?

  正确回答通过率:33.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

首先要知道 Hash 索引和 B+ 树索引的底层实现原理:

hash 索引底层就是 hash 表,进行查找时,调用一次 hash 函数就可以获取到相应的键值,之后进行回表查询获得实际数据。B+ 树底层实现是多路平衡查找树。对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据。

那么可以看出他们有以下的不同:

hash 索引进行等值查询更快(一般情况下),但是却无法进行范围查询。
因为在 hash 索引中经过 hash 函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询。而 B+ 树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围。
hash 索引不支持使用索引进行排序,原理同上。
hash 索引不支持模糊查询以及多列索引的最左前缀匹配。原理也是因为 hash 函数的不可预测。
hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询
hash 索引虽然在等值查询上较快,但是不稳定。性能不可预测,当某个键值存在大量重复的时候,发生 hash 碰撞,此时效率可能极差。而 B+ 树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低。
因此,在大多数情况下,直接选择 B+ 树索引可以获得稳定且较好的查询速度。而不需要使用 hash 索引

80. MyISAM和InnoDB实现B+树索引方式的区别是什么?

 正确回答通过率:36.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

MyISAM,B+Tree叶节点的data域存放的是数据记录的地址,在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的key存在,则取出其data域的值,然后以data域的值为地址读取相应的数据记录,这被称为“非聚簇索引”

InnoDB,其数据文件本身就是索引文件,相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按B+Tree组织的一个索引结构,树的节点data域保存了完整的数据记录,这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引,这被称为“聚簇索引”或者聚集索引,而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是和MyISAM不同的地方

在根据主键索引搜索时,直接找到key所在的节点即可取出数据;根据辅助索引查找时,则需要先取出主键的值,再走一遍主索引。 因此,在设计表的时候,不建议使用过长的字段为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。

总结:InnoDB 主键索引使用的是聚簇索引,MyISAM 不管是主键索引,还是二级索引使用的都是非聚簇索引。

81. 简述MySQL中有几种索引类型?

  正确回答通过率:75.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

FULLTEXT :即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。

HASH :由于HASH的唯一(几乎100%的唯一)及类似键值对的形式,很适合作为索引。HASH索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。

BTREE :BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。

RTREE :RTREE在MySQL很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。相对于BTREE,RTREE的优势在于范围查找。

82. 简述MySQL 聚簇索引和非聚簇索引的区别 ?

  正确回答通过率:74.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

聚簇索引的叶子节点存放的是主键值和数据行,支持覆盖索引
非聚簇索引的叶子节点存放的是主键值或数据记录的地址(InnoDB辅助索引的data域存储相应记录主键的值,MyISAM辅助索引的data域保存数据记录的地址)

83. 简述非聚簇索引一定会回表查询吗?

 正确回答通过率:81.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。

举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询

84. MySQL中为什么要有事务回滚机制?

  正确回答通过率:86.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

MySQL 中,恢复机制是通过回滚日志(undo log)实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后在对数据库中的对应行进行写入。当事务已经被提交之后,就无法再次回滚了。

回滚日志作用:

能够在发生错误或者用户执行 ROLLBACK 时提供回滚相关的信息
在整个系统发生崩溃、数据库进程直接被杀死后,当用户再次启动数据库进程时,还能够立刻通过查询回滚日志将之前未完成的事务进行回滚,这也就需要回滚日志必须先于数据持久化到磁盘上,是我们需要先写日志后写数据库的主要原因

85. Innodb使用的是哪种隔离级别 ?

 正确回答通过率:93.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重复读)

原因: 与 SQL 标准不同的地方在于InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别 下使用的是 Next-Key Lock 锁算法 ,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以 说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要 求,即达到了 SQL标准的SERIALIZABLE(可串行化)隔离级别。

InnoDB 存储引擎在分布式事务 的情况下一般会用到SERIALIZABLE(可串行化)隔离级别。

86. MySQL 不可重复读和幻读区别 ?

  正确回答通过率:80.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

不可重复读的重点是修改,幻读的重点在于新增或者删除。

例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导致A再读自己的工资时工资变为 2000;这就是不可重复读。

例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记 录就变为了5条,这样就导致了幻读。

87. MySQL 行级锁、表级锁、页级锁的描述与特点 ?

  正确回答通过率:79.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

行级锁:
描述:行级锁是mysql中锁定粒度最细的一种锁。表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁
特点:开销大,加锁慢,会出现死锁。发生锁冲突的概率最低,并发度也最高。

表级锁:
描述:表级锁是mysql中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分mysql引擎支持。最常使用的MyISAM与InnoDB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)
特点: 开销小,加锁快,不会出现死锁。发生锁冲突的概率最高,并发度也最低。

页级锁:
描述:页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折衷的页级锁,一次锁定相邻的一组记录。BDB 支持页级锁。
特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

88. 简述MySQL共享锁 、 排他锁 ?

  正确回答通过率:62.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

共享锁:
描述:
共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。
如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。
用法:
SELECT … LOCK IN SHARE MODE;
在查询语句后面增加LOCK IN SHARE MODE,MySQL 就会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。

排他锁:
描述:
排他锁又称写锁、独占锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。
用法:
SELECT … FOR UPDATE;
在查询语句后面增加FOR UPDATE,MySQL 就会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞

89. 简述MySQL 悲观锁与乐观锁 ?

  正确回答通过率:85.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

乐观锁(Optimistic Lock):假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。 乐观锁不能解决脏读的问题。
乐观锁, 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

悲观锁(Pessimistic Lock):假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
悲观锁,顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

90. 简述MySQL常用存储引擎的锁机制?

 正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

MyISAM和MEMORY采用表级锁(table-level locking)
BDB采用页面锁(page-level locking)或表级锁,默认为页面锁
InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁

91. 简述InnoDB 存储引擎有几种锁算法?

 正确回答通过率:74.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

Record Lock — 单个行记录上的锁;
Gap Lock — 间隙锁,锁定一个范围,不包括记录本身;
Next-Key Lock — 锁定一个范围,包括记录本身

92. Innodb默认是如何对待死锁的?

 正确回答通过率:32.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 高难

innodb默认是使用设置死锁时间来让死锁超时的策略,默认innodblockwait_timeout设置的时长是50s

93. MySQL如何开启死锁检测?

 正确回答通过率:74.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

设置innodbdeadlockdetect设置为on可以主动检测死锁,在innodb中这个值默认就是on开启的状态

94. 简述什么是全局锁?它的应用场景有哪些?

  正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 中级

全局锁就是对整个数据库实例加锁,它的典型使用场景就是做全库逻辑备份,这个命令可以使用整个库处于只读状态,使用该命令之后,数据更新语句,数据定义语句,更新类事务的提交语句等操作都会被阻塞。

95. MySQL 使用全局锁会导致的问题?

  正确回答通过率:79.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

如果在主库备份,在备份期间不能更新,业务停止,所以更新业务会处于等待状态
如果在从库备份,在备份期间不能执行主库同步的binlog,导致主从延迟

96. 简述MySQL优化锁方面你有什么建议?

 正确回答通过率:39.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

尽量使用较低的隔离级别。
精心设计索引, 并尽量使用索引访问数据, 使加锁更精确, 从而减少锁冲突的机会。
选择合理的事务大小,小事务发生锁冲突的几率也更小。
给记录集显示加锁时,最好一次性请求足够级别的锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁。
不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大大减少死锁的机会。
尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响。
不要申请超过实际需要的锁级别。
除非必须,查询时不要显示加锁。 MySQL 的 MVCC 可以实现事务中的查询不用加锁,优化事务性能;MVCC 只在 COMMITTED READ(读提交)和 REPEATABLE READ(可重复读)两种隔离级别下工作。
对于一些特定的事务,可以使用表锁来提高处理速度或减少死锁的可能。

97. MySQL字段为什么要求定义为not null ?

  正确回答通过率:70.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

null 值会占用更多的字节,且会在程序中造成很多与预期不符的情况。

98. 简述如果要存储用户的密码散列,应该使用什么字段进行存储?

 正确回答通过率:93.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

密码散列,用户身份证号等固定长度的字符串应该使用 char 而不是 varchar 来存储,这样可以节省空间且提高检索效率。

99. MySQL 数据库中的主键、超键、候选键、外键是什么?

 正确回答通过率:73.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

超键(super key): 在关系中能唯一标识元组的属性集称为关系模式的超键

候选键(candidate key): 不含有多余属性的超键称为候选键。也就是在候选键中,若再删除属性,就不是键了!

主键(primary key): 用户选作元组标识的一个候选键程序主键

外键(foreign key):如果关系模式R中属性K是其它模式的主键,那么k在模式R中称为外键。

100. MySQL的binlog有有几种录入格式分别有什么区别 ?

 正确回答通过率:81.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

有三种格式:statement、row和mixed.

statement模式下,记录单元为语句.即每一个sql造成的影响会记录.由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制.
row级别下,记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大.
mixed. 一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row.

101. 简述MySQL 超大分页怎么处理 ?

  正确回答通过率:40.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

超大的分页一般从两个方向上来解决.:

数据库层面,这也是我们主要集中关注的(虽然收效没那么大),类似于select * from table where age > 20 limit 1000000,10这种查询其实也是有可以优化的余地的. 这条语句需要load1000000数据然后基本上全部丢弃,只取10条当然比较慢. 当时我们可以修改为select * from table where id in (select id from table where age > 20 limit 1000000,10).这样虽然也load了一百万的数据,但是由于索引覆盖,要查询的所有字段都在索引中,所以速度会很快. 同时如果ID连续的好,我们还可以select * from table where id > 1000000 limit 10,效率也是不错的,优化的可能性有许多种,但是核心思想都一样,就是减少load的数据.

从需求的角度减少这种请求…主要是不做类似的需求(直接跳转到几百万页之后的具体某一页.只允许逐页查看或者按照给定的路线走,这样可预测,可缓存)以及防止ID泄漏且连续被人恶意攻击.

102. MySQL left join、right join以及inner join的区别 ?

 正确回答通过率:93.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

left join:左关联,主表在左边,右边为从表。如果左侧的主表中没有关联字段,会用null 填满
right join:右关联 主表在右边和letf join相反
inner join: 内关联只会显示主表和从表相关联的字段,不会出现null

103. 简述什么是MySQL 数据库约束,常见的约束有哪几种 ?

 正确回答通过率:92.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

数据库约束用于保证数据库、表数据的完整性(正确性和一致性)。
可以通过定义约束索引触发器来保证数据的完整性。总体来讲,约束可以分为:

主键约束:primary key;
外键约束:foreign key;
唯一约束:unique;
检查约束:check;
空值约束:not null;
默认值约束:default;

104. 简述数据库的读写分离?

 正确回答通过率:63.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

读写分离为了确保数据库产品的稳数据定性,很多数据库拥有双机热备功能。也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进行读的操作

105. 简述count(1)、count(*)与count(列名)的执行区别 ?

  正确回答通过率:74.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

count(*):包括了所有的列,相当于行数,在统计结果的时候, 不会忽略列值为NULL
count(1):包括了忽略所有列,用1代表代码行,在统计结果的时候, 不会忽略列值为NULL
count(列名):只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数, 即某个字段值为NULL时,不统计。
执行效率上:

列名为主键,count(列名)会比count(1)快
列名不为主键,count(1)会比count(列名)快
如果表多个列并且没有主键,则 count(1) 的执行效率优于 count(
如果有主键,则 select count(主键)的执行效率是最优的
如果表只有一个字段,则 select count(
)最优。

106. MySQL中null与空值的区别 ?

  正确回答通过率:58.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

1.占用空间区别:空值(’’)的长度是0,是不占用空间的;而的NULL长度是NULL,是占用空间的
2.插入/查询方式区别:NULL值查询使用is null/is not null查询,而空值(’’)可以使用=或者!=、<、>等算术运算符。
3.COUNT 和 IFNULL函数:使用 COUNT(字段) 统计会过滤掉 NULL 值,但是不会过滤掉空值。
4.索引字段说明:在有NULL值的字段上使用常用的索引,如普通索引、复合索引、全文索引等不会使索引失效。在官网查看在空间索引的情况下,说明了 索引列必须为NOT NULL

107. 简述MySQL是如何执行SQL ?

 正确回答通过率:56.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

1.客户端请求->
2.连接器(验证用户身份,给予权限) ->
3.查询缓存(存在缓存则直接返回,不存在则执行后续操作)->
4.分析器(对SQL进行词法分析和语法分析操作) ->
5.优化器(主要对执行的sql优化选择最优的执行方案方法) ->
6.执行器(执行时会先看用户是否有执行权限,有才去使用这个引擎提供的接口)->
7.去引擎层获取数据返回(如果开启查询缓存则会缓存查询结果)

简单概括:

连接器:管理连接、权限验证;
查询缓存:命中缓存则直接返回结果;
分析器:对SQL进行词法分析、语法分析;(判断查询的SQL字段是否存在也是在这步)
优化器:执行计划生成、选择索引;
执行器:操作引擎、返回结果;
存储引擎:存储数据、提供读写接口。

108. MSQL设计索引的时候,我们一般需要考虑哪些因素?

  正确回答通过率:55.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

1.数据量超过三百,理论上应创建索引
2.经常与其他表链接的表,在链接字段应创建索引 on 两边的字段,都要建立索引
3.经常出现在where子句中的字段,尤其是大表,应创建索引
4.索引应创建在选择性高,重复度低的字段上,如员工表,姓名和性别都作为查询条件,姓名更适合建立索引。如果两个同时建立了索引,MySQL也会自动选择以姓名作为索引查询
5.索引应该建立在小字段上,对于大的文本甚至超长字段,尽量不建立索引
6.复合索引
① 正确选择复合索引中的主列字段,一般是选择性较好的字段
② 复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有? 如果是,则可以建立复合索引;否则考虑单字段索引
③ 如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引
④ 如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引
7.索引维护也需要成本,频繁增删的数据表,谨慎选择索引
查询中排序的字段,应该创建索引( B + tree 有顺序)
统计或者分组字段,应该创建索引

109. 简述什么是堆表?

  正确回答通过率:83.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

HEAP 表存在于内存中,它们用于临时的高速存储基础。
• 不允许使用 BLOB 或 TEXT 字段
• 只能使用比较运算符 =、<、>、= >、=<
• HEAP 表不支持 AUTO_INCREMENT
• 索引不应为空

110. Oracle相比,MySQL的优势是什么?

 正确回答通过率:88.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MySQL 是开源软件,随时可用且不涉及任何费用。
MySQL 是可移植的
带有命令提示符的 GUI。
使用 MySQL 查询浏览器支持管理

111. 如何区分 FLOAT 和 DOUBLE?

 正确回答通过率:89.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

以下是 FLOAT 和 DOUBLE 的区别:
• 浮点数以八位精度存储在 FLOAT 中,它有四个字节。
• 浮点数以18 位精度存储在DOUBLE 中,它有8 个字节。

112. 如何区分 CHAR_LENGTH 和 LENGTH?

 正确回答通过率:79.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

CHAR_LENGTH 是字符数,而 LENGTH 是字节数。拉丁字符的数字相同,但 Unicode 和其他编码的数字不同

113. MySQL 中 ENUM 的用途是什么?

  正确回答通过率:61.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

MySQL中的enum类型是一种特殊的数据类型,它可以存储一组预定义的值,这些值必须是已知的、固定的、有限的值集合。

1 enum类型的用途
enum类型可用于存储应用程序中的一组有限的选项。例如,当您在电子商务网站上创建订单时,您可能需要将订单状态存储为一组确定的选项,如“待付款”,“已付款”,“待发货”和“已发货”等。

2 enum类型的优点
enum类型的主要优点是它可以保护数据库免受无效或错误数据的影响,因为只有可接受的值才能存储在数据库中。此外,枚举类型在某些情况下可以减少存储空间,因为它们只需要存储enum值而不是整个字符串。

3 enum类型的局限性

enum类型并非适用于所有情况。最大的局限性是当您需要更改数据库中的选项时,枚举类型可能会变得更难处理。如果您需要添加或删除一项,您将需要更改枚举类型的定义,这可能会导致需要更新整个数据库。

4 使用enum类型的最佳实践
在使用enum类型之前,请仔细思考您的需求,并确保它们适用于预定义选项。如果您需要经常更改选项,您可能要考虑使用其他方法,如创建单独的表来存储选项。

总之,enum类型是MySQL中一个非常有用的数据类型,可以保护数据库免受无效或错误数据的影响,并可以减少存储空间,但还有一些局限性需要考虑。在使用之前,请仔细思考您的需求,以确保它们适用于预定义选项

114. 简述TIMESTAMP 对 UPDATE CURRENT_TIMESTAMP 数据类型有什么作用?

 正确回答通过率:48.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

创建表时,TIMESTAMP 列将更新为零。只要表的其他字段发生更改,UPDATE CURRENT_TIMESTAMP 修饰符就会将时间戳字段更新为当前时间

115. 简述myisamchk 命令的作用 ?

 正确回答通过率:86.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

压缩 MyISAM 表,从而减少它们的磁盘或内存使用。

116. 如何控制 HEAP 表的最大大小?

 正确回答通过率:72.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

Heal 表的最大大小可以由 MySQL 配置变量 max_heap_table_size 控制

117. MyISAM 静态和 MyISAM 动态有什么区别?

  正确回答通过率:69.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

在 MyISAM 静态中,所有字段都将具有固定宽度。动态 MyISAM 表将包含 TEXT、BLOB 等字段,以适应各种长度的数据类型。
MyISAM Static 在损坏的情况下更容易恢复

118. 当列设置为 AUTO INCREMENT 并且在表中达到最大值时会发生什么?

  正确回答通过率:63.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

auto_increment 是用于主键自动增长的,从1开始增长,当你把第一条记录删除时,再插入第二条数据时,主键值是2,不是1。

当达到最大值时,它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。

在使用 AUTO_INCREMENT 时,应注意以下几点:

AUTO_INCREMENT 是数据列的一种属性,只适用于整数类型数据列。
设置AUTO_INCREMENT 属性的数据列应该是一个正数序列,所以应该把该数据列声明为 UNSIGNED,这样序列的编号个可增加一倍。
AUTO_INCREMENT 数据列必须有唯一索引,以避免序号重复(即是主键或者主键的一部分)。
AUTO_INCREMENT 数据列必须具备NOT NULL属性。
AUTO_INCREMENT 数据列序号的最大值受该列的数据类型约束,如 TINYINT 数据列的最大编号是127,如加上UNSIGNED,则最大为 255。一旦达到上限,AUTO_INCREMENT 就会失效。
当进行全表删除时,MySQL AUTO_INCREMENT 会从1重新开始编号。
这是因为进行全表操作时,MySQL(和 PHP 搭配之最佳组合)实际是做了这样的优化操作:先把数据表里的所有数据和索引删除,然后重建数据表。

如果想删除所有的数据行又想保留序列编号信息,可这样用一个带 where 的 delete 命令以抑制 MySQL(和 PHP 搭配之最佳组合)的优化: delete from table_name where 1;,可用 last_insert_id() 获取刚刚自增过的值

119. 如何找出最后插入时分配了哪个自动增量?

 正确回答通过率:37.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

LAST_INSERT_ID 将返回 Auto_increment 分配的最后一个值,不需要指定表名

120. MySQL 如何查看为表定义的所有索引?

 正确回答通过率:95.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

通过以下方式为表定义索引:
SHOW INDEX FROM

121. 解释LIKE 语句中的 % 和 _ 是什么意思?

  正确回答通过率:92.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

% 对应 0 个或多个字符,_ 恰好是 LIKE 语句中的一个字符

122. 如何在 Unix 和 MySQL 时间戳之间进行转换?

 正确回答通过率:76.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

UNIX_TIMESTAMP 是将 MySQL 时间戳转换为 Unix 时间戳的命令

FROM_UNIXTIME 是将 Unix 时间戳转换为 MySQL 时间戳的命令

123. MySQL 查询是否区分大小写?

 正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

不区分
SELECT VERSION(), CURRENT_DATE;
SeLect version(), current_date;
seleCt vErSiOn(), current_DATE;
所有这些例子都是一样的。它不区分大小写。

124. MySQL LIKE 和 REGEXP 运算符有什么区别?

  正确回答通过率:70.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

LIKE 和 REGEXP 运算符用于用 ^ 和 % 表示。
SELECT * FROM employee WHERE emp_name REGEXP “^b”;
SELECT * FROM employee WHERE emp_name LIKE “%b”;

125. MySQL 中BLOB 和 TEXT 有什么区别?

  正确回答通过率:62.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

BLOB 是一个二进制大对象,可以保存可变数量的数据。有四种类型的 BLOB

小斑点
斑点
MEDIUMBLOB 和
长块
它们的不同之处仅在于它们可以保存的值的最大长度。

TEXT 是不区分大小写的 BLOB。四种 TEXT 类型

小文本
文本
中文本和
长文
它们都对应于四种 BLOB 类型,并且具有相同的最大长度和存储要求。

BLOB 和 TEXT 类型之间的唯一区别是排序和比较对 BLOB 值区分大小写,对 TEXT 值不区分大小写

126. 请问mysql_fetch_array 和 mysql_fetch_object 有什么区别?

 正确回答通过率:89.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

以下是 mysql_fetch_array 和 mysql_fetch_object 之间的区别:
mysql_fetch_array() - 将结果行作为关联数组或数据库中的常规数组返回。
mysql_fetch_object – 从数据库中返回一个结果行作为对象。

127. 如何在 MySQL 中运行批处理模式?

 正确回答通过率:75.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

1.使用Statement批量插入数据:
2.使用PreparedStatement批量插入数据:
3.在2的基础上添加Batch缓存:
4.在3的基础上增加取消自动提交数据的功能

128. 简述MyISAM 表将存储在哪里,并给出它们的存储格式?

 正确回答通过率:79.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

每个 MyISAM 表都以三种格式存储在磁盘上:
“.frm”文件存储表定义
数据文件具有“.MYD”(MYData)扩展名
索引文件具有“.MYI”(MYIndex)扩展名

129. 简述什么是 ISAM ?

 正确回答通过率:78.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

ISAM简称为索引顺序访问方法。它是由IBM开发的,用于在磁带等辅助存储系统上存储和检索数据。

130. MySQL 如何优化 DISTINCT?

  正确回答通过率:62.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

DISTINCT 在所有列上都转换为 GROUP BY,并将与 ORDER BY 子句结合使用。
SELECT DISTINCT t1.a FROM t1,t2 where t1.a=t2.a;

131. MySQL 如何将字符输入为 HEX 数字?

 正确回答通过率:39.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 高难

如果您想输入字符作为 HEX 数字,您可以输入带单引号和前缀 (X) 的 HEX 数字,或者只在 HEX 数字前面加上 (Ox)。

如果表达式上下文是字符串,HEX 数字字符串将自动转换为字符串

132. MySQL 创建索引可以使用多少列?

 正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

可以为任何标准表创建最多 16 个索引列。

133. MySQL函数NOW() 和 CURRENT_DATE() 有什么区别?

 正确回答通过率:76.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

NOW () 命令用于以小时、分钟和秒显示当前年、月、日。
CURRENT_DATE() 仅显示当前年、月和日期。

134. MySQL表中允许有多少个 TRIGGERS(触发器)?

 正确回答通过率:69.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

MySql 表中允许有六个触发器。它们如下:

插入前
插入后
更新前
更新后
删除前和
删除后

135. MySQL 什么是非标准字符串类型?

 正确回答通过率:81.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

以下是非标准字符串类型:

小文本
文本
中文本
长文

136. 请列举常见的 SQL 函数有哪些?

  正确回答通过率:92.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

CONCAT(A, B) – 连接两个字符串值以创建单个字符串输出。通常用于将两个或多个字段组合成一个字段。
FORMAT(X, D) – 将数字 X 格式化为 D 有效数字。
CURRDATE(), CURRTIME() – 返回当前日期或时间。
NOW() – 将当前日期和时间作为一个值返回。
MONTH(), DAY(), YEAR(), WEEK(), WEEKDAY() – 从日期值中提取给定数据。
HOUR(), MINUTE(), SECOND() – 从时间值中提取给定数据。
DATEDIFF(A, B) - 确定两个日期之间的差异,通常用于计算年龄
SUBTIMES(A, B) – 确定两次之间的差异。
FROMDAYS(INT) – 将整数天数转换为日期值。

137. 简述访问控制列表ACL ?

 正确回答通过率:61.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 中级

ACL(Access Control List)访问控制列表的简称,是一个规则列表,用于指定允许或拒绝哪些用户或系统访问特定对象或系统资源,访问控制列表也安装在路由器或交换机中,它们充当过滤器,管理哪些流量可以访问网络。

ACL 一般有两种类型:
文件系统 ACL:一般是过滤对文件和 / 或目录的访问。
网络 ACL:过滤对网络的访问,一般用于网络设备,比如路由器、交换机等。

ACL 目的:
提供安全访问:企业重要服务器资源被随意访问,企业机密信息容易泄露,造成安全隐患。使用 ACL 可以指定用户访问特定的服务器、网络与服务,从而避免随意访问的情况。
防止网络攻击:Internet 病毒肆意侵略企业内网,内网环境的安全性堪忧。使用 ACL 可以封堵高危端口,从而达成为外网流量的阻塞。
提高网络带宽利用率:网络带宽被各类业务随意挤占,服务质量要求最高的语音、视频业务的带宽得不到保障,造成用户体验差。使用 ACL 实现对网络流量的精确识别和控制,限制部分网络流量从而保障主要业务的质量。

ACL 的使用场景:
ACL 可以应用于诸多业务模块,其中最基本的 ACL 应用,就是在简化流策略 / 流策略中应用 ACL,使设备能够基于全局、VLAN 或接口下发 ACL,实现对转发报文的过滤。此外,ACL 还可以应用在 Telnet、FTP、路由等模块。

138. 简述MySQL 架构中的三层服务?

 正确回答通过率:80.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

第一层是服务器层,主要提供连接处理、授权认证、安全等功能。

第二层实现了 MySQL 核心服务功能,包括查询解析、分析、优化、缓存以及日期和时间等内置函数。

第三层是存储引擎层,负责数据的存储和提取。服务器通过 API 与存储引擎通信,这些接口屏蔽了不同存储引擎的差异。除了会解析外键定义的 InnoDB 外,存储引擎不会解析 SQL,不同存储引擎之间也不会相互通信,只是简单响应服务器请求

139. 简述MySQL数据库并发场景 ?

  正确回答通过率:58.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

所有系统的并发场景都是三种,对于数据库而言为:

读-读:不存在任何问题,也不需要并发控制。
读-写:有线程安全问题,可能会造成事务隔离性问题,也就是脏读,不可重复读,幻读。
写-写:有线程安全问题,会存在更新丢失问题:第一类更新丢失(回滚丢失),第二类更新丢失(覆盖丢失)。

MVCC是一种用来解决读写冲突的无锁并发控制,也就是为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照,所以MVCC可以为数据库解决一下问题:
​ 1、在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
​ 2、解决脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失问题

140. 简述MySQL主从复制原理和机制 ?

  正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

1、什么是主从复制?
概念 主从复制是用来建立一个和 主数据库完全一样的数据库环境称为从数据库;主数据库一般是准实时的业务数据库。
2、主从复制作用
我们来思考如果在企业网站中,后端MYSQL数据库只有一台时候,会有以下问题:
1、单点故障服务不可用
2、无法处理大量的并发数据请求
3、数据丢失
所以通过主从复制后,它的优点就很明显
1、如果主节点出现故障,那么我们就直接将服务切到从节点,来保证服务立马可用。
2、如果并发请求特别大的时候,我们可用进行读写分离操作,让主库负责写,从库负责读。
3、如果主库数据丢失,但从库还保存一份,减少数据丢失的风险

【主从复制的原理】
上面主要分成了三步,下面会详细说明。
(1) Master的更新事件(update、insert、delete)会按照顺序写入bin-log中。当Slave连接到Master的后,Master机器会为Slave开启
binlog dump线程,该线程会去读取bin-log日志
(2) Slave连接到Master后,Slave库有一个I/O线程 通过请求binlog dump thread读取bin-log日志,然后写入从库的relay log日志中。
(3) Slave还有一个 SQL线程,实时监控 relay-log日志内容是否有更新,解析文件中的SQL语句,在Slave数据库中去执行。
总结
(1) 既然是要把事件记录到bin-log日志,那么对于Master就必须开启bin-log功能。
(2) 整个Mysql主从复制一共开启了3个线程。Master开启 IO线程,Slave开启 IO线程 和 SQL线程。
(3) 这点也很重要那就是Master和Slave交互的时候,记住这里是Slave去请求Master,而不是Master主动推给Slave。Slave通过IO线程
连接Master后发起请求,Master服务器收到Slave IO线程发来的日志请求信息,io线程去将bin-log内容返回给slave IO线程。

141. 阐述MySQL主从复制同步方式 ?

  正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

(1)异步复制
MySQL主从同步 默认是异步复制的。就是上面三步中,只有第一步是同步的(也就是Mater写入bin log日志),就是主库写入binlog日志后即可成功返回客户端,无须等待binlog
日志传递给从库的过程。Master 不关心 Slave 的数据有没有写入成功。因此如果Master和Slave之间有网络延迟,就会造成暂时的数据不一致的现象;如果Master出故障,而数据
还没有复制过去,则会造成数据丢失;但也有好处,效率较其他两种复制方式最高。
(2)同步复制
对于同步复制而言,Master主机将事件发送给Slave主机后会触发一个等待,直到所有Slave节点(如果有多个Slave)返回数据复制成功的信息给Master。这种复制方式最安
全,但是同时,效率也是最差的。
(3)半同步复制
对于半同步复制而言,Master主机将事件发送给Slave主机后会触发一个等待,直到其中一个Slave节点(如果有多个Slave)返回数据复制成功的信息给Master。由此增强了
数据的一致性,但是因为Master主机的确认开销,会损耗一部分的性能;另外,半同步复制除了不需要等待所有Slave主机确认事件的接收外,半同步数据复制并不要求那些事件
完全地执行,因此,仍有可能看到在Slave主机上数据复制延迟的发生,如果因为网络延迟等原因造成Slave迟迟没有返回复制成功的信息,超过了Master设置的超时时长,半同步
复制就降级为异步复制方式,而后继续数据复制。

142. 简述MySQL主从同步延时 ?

  正确回答通过率:61.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

Mysql默认采用的异步操作,因为它的效率明显是最高的。因为只要写入bin log后事物就结束返回成功了。但由于从库从主库异步拷贝日志 以及
串行执行 SQL 的特点,所以从库的数据一定会比主库慢一些,是有延时的。所以经常出现,刚写入主库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能
读取到。这就是主从同步延时问题。
1、如何查看主从延迟时间
通过监控 show slave status 命令输出的Seconds_Behind_Master参数的值来判断:
mysql> show slave status\G;
// 状态一
Seconds_Behind_Master: NULL
// 状态二
Seconds_Behind_Master: 0
// 状态三
Seconds_Behind_Master: 79
Seconds_Behind_Master=0: 表示主从复制良好;
Seconds_Behind_Master=NULL: 表示io_thread或是sql_thread有任何一个发生故障;
Seconds_Behind_Master=79: 数字越大表示从库延迟越严重。
2、影响延迟因素
这里整理了影响主从复制延迟大致有以下几个原因:
1)主节点如果执行一个很大的事务,那么就会对主从延迟产生较大的影响
2)网络延迟,日志较大,slave数量过多
3)主上多线程写入,从节点只有单线程同步
4)机器性能问题,从节点是否使用了“烂机器”
5)锁冲突问题也可能导致从机的SQL线程执行慢
3、优化主从复制延迟
这个没有说去完全解决,要想解决那么就只能采用同步复制策略。不过,一般不建议使用这种同步模式。显而易见,如果写操作必须等待更新同步完成,肯定会
极大地影响性能,除非你不在乎性能。
1)大事务:将大事务分为小事务,分批更新数据
2)减少Slave的数量,不要超过5个,减少单次事务的大小
3)MySQL 5.7之后,可以使用多线程复制,使用MGR复制架构
4)在磁盘、raid卡、调度策略有问题的情况下可能会出现单个IO延迟很高的情况,可用iostat命令查看DB数据盘的IO情况,再进一步判断
5)针对锁问题可以通过抓去processlist以及查看information_schema下面和锁以及事务相关的表来查看
总结
主机与从机之间的物理延迟是无法避免的,既然无法避免就可以考虑尝试通过缓存等方式,降低新修改数据被立即读取的概率。

143. MySQL数据库是否支持emoji表情存储,如果不支持,如何操作?

 正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

更换字符集utf8–>utf8mb4

144. 简述什么是最左前缀原则?什么是最左匹配原则?

  正确回答通过率:75.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

最左前缀原则,就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。

当我们创建一个组合索引的时候,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则

145. 简述MySQL分库与分表的设计思路( 重要 ) ?

  正确回答通过率:41.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

「分库分表方案:」
**1、**水平分库:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。
**2、**水平分表:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。
**3、**垂直分库:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。
**4、**垂直分表:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。
「常用的分库分表中间件:」
**1、**sharding-jdbc(当当)
**2、**Mycat
**3、**TDDL(淘宝)
**4、**Oceanus(58同城数据库中间件)
**5、**vitess(谷歌开发的数据库中间件)
**6、**Atlas(Qihoo 360)
「分库分表可能遇到的问题」
**1、**事务问题:需要用分布式事务啦
**2、**跨节点Join的问题:解决这一问题可以分两次查询实现
**3、**跨节点的count,order by,group by以及聚合函数问题:分别在各个节点上得到结果后在应用程序端进行合并。
**4、**数据迁移,容量规划,扩容等问题
**5、**ID问题:数据库被切分后,不能再依赖数据库自身的主键生成机制啦,最简单可以考虑UUID
**6、**跨分片的排序分页问题(后台加大pagesize处理?)

146. 简述什么情况下设置了索引但无法使用?

 正确回答通过率:53.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

索引哪些情况会失效

查询条件包含or,可能导致索引失效
如何字段类型是字符串,where时一定用引号括起来,否则索引失效
like通配符可能导致索引失效。
联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。
在索引列上使用mysql的内置函数,索引失效。
对索引列运算(如,+、-、*、/),索引失效。
索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效。
索引字段上使用is null, is not null,可能导致索引失效。
左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效。
mysql估计使用全表扫描要比使用索引快,则不使用索引。

147. MySQL如何删除索引 ?

 正确回答通过率:95.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

根据索引名删除普通索引、唯一索引、全文索引:alter table 表名 drop KEY 索引名

alter table user_index drop KEY name; alter table user_index drop KEY id_card; alter table user_index drop KEY information;

删除主键索引:alter table 表名 drop primary key(因为主键只有一个)。这里值得注意的是,如果主键自增长,那么不能直接执行此操作(自增长依赖于主键索引):

需要取消自增长再行删除:

alter table user_index – 重新定义字段 MODIFY id int, drop PRIMARY KEY

但通常不会删除主键,因为设计主键一定与业务逻辑无关

148. 简述数据库连接池?为什么需要数据库连接池呢?

 正确回答通过率:61.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

连接池基本原理:
数据库连接池原理:在内部对象池中,维护一定数量的数据库连接,并对外暴露数据库连接的获取和返回方法。
应用程序和数据库建立连接的过程:
**1、**通过TCP协议的三次握手和数据库服务器建立连接
**2、**发送数据库用户账号密码,等待数据库验证用户身份
**3、**完成身份验证后,系统可以提交SQL语句到数据库执行
**4、**把连接关闭,TCP四次挥手告别。
数据库连接池好处:
**1、**资源重用 (连接复用)
**2、**更快的系统响应速度
**3、**新的资源分配手段
**4、**统一的连接管理,避免数据库连接泄漏

149. 如何定位及优化SQL语句的性能问题 ?

  正确回答通过率:49.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

对于低性能的SQL语句的定位,最重要也是最有效的方法就是使用执行计划,MySQL提供了explain命令来查看语句的执行计划。 我们知道,不管是哪种数据库,或者是哪种数据库引擎,在对一条SQL语句进行执行的过程中都会做很多相关的优化,对于查询语句,最重要的优化方式就是使用索引。 而执行计划,就是显示数据库引擎对于SQL语句的执行的详细情况,其中包含了是否使用索引,使用什么索引,使用的索引的相关信息等
执行计划包含的信息id有一组数字组成。表示一个查询中各个子查询的执行顺序;
**1、**id相同执行顺序由上至下。
**2、**id不同,id值越大优先级越高,越先被执行。
**3、**id为null时表示一个结果集,不需要使用它查询,常出现在包含union等查询语句中。
select_type每个子查询的查询类型,一些常见的查询类型。
table查询的数据表,当从衍生表中查数据时会显示 x 表示对应的执行计划idpartitions表分区、表创建的时候可以指定通过那个列进行表分区。 举个例子:
create table tmp ( id int unsigned not null AUTO_INCREMENT, name varchar(255), PRIMARY KEY (id) ) engine = innodb partition by key (id) partitions 5;
type(非常重要,可以看到有没有走索引) 访问类型
**1、**ALL 扫描全表数据
**2、**index 遍历索引
**3、**range 索引范围查找
**4、**index_subquery 在子查询中使用 ref
**5、**unique_subquery 在子查询中使用 eq_ref
**6、**ref_or_null 对Null进行索引的优化的 ref
**7、**fulltext 使用全文索引
**8、**ref 使用非唯一索引查找数据
**9、**eq_ref 在join查询中使用PRIMARY KEYorUNIQUE NOT NULL索引关联。
10、****possible_keys可能使用的索引,注意不一定会使用。查询涉及到的字段上若存在索引,则该索引将被列出来。当该列为 NULL时就要考虑当前的SQL是否需要优化了。
11、****key显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。
**12、**TIPS:查询中若使用了覆盖索引(覆盖索引:索引的数据覆盖了需要查询的所有数据),则该索引仅出现在key列表中
13、****key_length索引长度
14、****ref表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
15、****rows返回估算的结果集数目,并不是一个准确的值。
16、****extra的信息非常丰富,常见的有:
**17、**Using index 使用覆盖索引
**18、**Using where 使用了用where子句来过滤结果集
**19、**Using filesort 使用文件排序,使用非索引列进行排序时出现,非常消耗性能,尽量优化。
**20、**Using temporary 使用了临时表 sql优化的目标可以参考阿里开发手册
推荐
SQL性能优化的目标:至少要达到 range 级别,要求是ref级别,如果可以是consts最好
说明:
**1、**consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
**2、**ref 指的是使用普通的索引(normal index)。
**3、**range 对索引进行范围检索。

150. MySQL 的binLog是什么?

 正确回答通过率:76.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

binlog是mysql用于数据收集和数据恢复的日志管理工具

151. 如何查询MySQL的binlog日志默认存放在哪儿?

 正确回答通过率:84.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

查看日志文件路径
show master status
在my.ini文件中 查看bin_log文件

152. MySQL自增主键出现不连续的原因?

 正确回答通过率:30.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

mysql自增主键不连续的情况原因有三个:

  1. 唯一键冲突
  2. 事务回滚
  3. insert…select的时候会出现主键id每次双倍分配导致主键id跳过的问题

153. 简述MySQL的慢查询默认时间为多长?

 正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

10 S

154. Delete from 语句与truncate语句的区别?

 正确回答通过率:85.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

delete语句如果不加where那么会全表清空, truncate 直接全表清空,但是如果detele一个非常大的表的时候,用delete语句可能会出现"max_binlog_cache_size" 不足的情况,因为delete操作的语句会记录在binlog里,然而truncate不会记录到binlog里,记录在binlog里的好处是能恢复

155. MySQL limit 1000000 加载很慢的话,怎么解决 ?

  正确回答通过率:55.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

方案一:如果id是连续的,可以这样,返回上次查询的最大记录(偏移量),再往下limit

select id,name from employee where id>1000000 limit 10.

方案二:在业务允许的情况下限制页数:

建议跟业务讨论,有没有必要查这么后的分页啦。因为绝大多数用户都不会往后翻太多页。

方案三:order by + 索引(id为索引)

select id,name from employee order by id limit 1000000,10

方案四:利用延迟关联或者子查询优化超多分页场景。(先快速定位需要获取的id段,然后再关联)

SELECT a.* FROM employee a, (select id from employee where 条件 LIMIT 1000000,10 ) b where a.id=b.id

156. 在高并发情况下,如何做到安全的修改同一行数据?

 正确回答通过率:38.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

要安全的修改同一行数据,就要保证一个线程在修改时其它线程无法更新这行记录。一般有悲观锁和乐观锁两种方案~
使用悲观锁
悲观锁思想就是,当前线程要进来修改数据时,别的线程都得拒之门外~
比如,可以使用select…for update ~
select * from User where name=‘jay’ for update
以上这条sql语句会锁定了User表中所有符合检索条件(name=‘jay’)的记录。本次事务提交之前,别的线程都无法修改这些记录。
使用乐观锁
乐观锁思想就是,有线程过来,先放过去修改,如果看到别的线程没修改过,就可以修改成功,如果别的线程修改过,就修改失败或者重试。实现方式:乐观锁一般会使用版本号机制或CAS算法实现

157. 简述select for update ?

  正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

select for update 是为了在查询时,避免其他用户以该表进行插入,修改或删除等操作,造成表的不一致性。

Select …forupdate语句是我们经常使用手工加锁语句。通常情况下,select语句是不会对数据加锁,妨碍影响其他的DML和DDL操作。同时,在多版本一致读机制的支持下,select语句也不会被其他类型语句所阻碍。借助for update子句,我们可以在应用程序的层面手工实现数据加锁保护操作。

一般FOR UPDATE用在PL/SQL的游标里,它的作用就是一个行级锁(对游标里所有的记录),如果其他进程要更新这个游标行级锁里的记录,就必须等待当前进程的COMMIT或者回滚。

该语句用来锁定特定的行(如果有where子句,就是满足where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被commit语句或rollback语句结束为止。

158. MySQL 如果某个表有近千万数据,CRUD比较慢,如何优化 ?

  正确回答通过率:54.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

分库分表

某个表有近千万数据,可以考虑优化表结构,分表(水平分表,垂直分表),当然,你这样回答,需要准备好面试官问你的分库分表相关问题呀,如

分表方案(水平分表,垂直分表,切分规则hash等)
分库分表中间件(Mycat,sharding-jdbc等)
分库分表一些问题(事务问题?跨节点Join的问题)
解决方案(分布式事务等)
索引优化

除了分库分表,优化表结构,当然还有所以索引优化等方案~

159. MySQL如何写SQL能够有效的使用到复合索引?

 正确回答通过率:40.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

复合索引,也叫组合索引,用户可以在多个列上建立索引,这种索引叫做复合索引。
当我们创建一个组合索引的时候,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则。
select * from table where k1=A AND k2=B AND k3=D
有关于复合索引,我们需要关注查询Sql条件的顺序,确保最左匹配原则有效,同时可以删除不必要的冗余索引

160. MySQL中in 和exists的区别?

  正确回答通过率:52.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

select * from A where id in(select id from B)
有两点区别:
(1) 使用上的区别:exists中放一个子查询有记录返回true,无记录返回false(NULL也算有记录),in中查询结果集只能有一个字段
(2) 性能上的区别:in要把缓存到内存中,exists不需要缓存结果
in()适合B表比A表数据小的情况
exists()适合B表比A表数据大的情况
当A表数据与B表数据一样大时,in与exists效率差不多,可任选一个使用.

161. MySQL数据库自增主键可能遇到什么问题 ?

  正确回答通过率:55.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

使用自增主键对数据库做分库分表,可能出现诸如主键重复等的问题。解决方案的话,简单点的话可以考虑使用UUID哈
自增主键会产生表锁,从而引发问题
自增主键可能用完问题。

162. MYSQL的主从延迟,怎么解决?

  正确回答通过率:58.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

主从复制分了五个步骤进行:

步骤一:主库的更新事件(update、insert、delete)被写到binlog
步骤二:从库发起连接,连接到主库。
步骤三:此时主库创建一个binlog dump thread,把binlog的内容发送到从库。
步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log
步骤五:还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db
主从同步延迟的原因

一个服务器开放N个链接给客户端来连接的,这样有会有大并发的更新操作, 但是从服务器的里面读取binlog的线程仅有一个,当某个SQL在从服务器上执行的时间稍长 或者由于某个SQL要进行锁表就会导致,主服务器的SQL大量积压,未被同步到从服务器里。这就导致了主从不一致, 也就是主从延迟。

主从同步延迟的解决办法

主服务器要负责更新操作,对安全性的要求比从服务器要高,所以有些设置参数可以修改,比如sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之类的设置等。
选择更好的硬件设备作为slave。
把一台从服务器当度作为备份使用, 而不提供查询, 那边他的负载下来了, 执行relay log 里面的SQL效率自然就高了。
增加从服务器喽,这个目的还是分散读的压力,从而降低服务器负载。

163. MySQL数据库存储日期格式时,如何考虑时区转换问题?

 正确回答通过率:78.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 初级

datetime类型适合用来记录数据的原始的创建时间,修改记录中其他字段的值,datetime字段的值不会改变,除非手动修改它。
timestamp类型适合用来记录数据的最后修改时间,只要修改了记录中其他字段的值,timestamp字段的值都会被自动更新。

164. MySQL数据库服务器性能分析的方法命令有哪些?

 正确回答通过率:73.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

Show status, 一些值得监控的变量值:
Bytes_received和Bytes_sent 和服务器之间来往的流量。
Com_*服务器正在执行的命令。
Created_*在查询执行期限间创建的临时表和文件。
Handler_*存储引擎操作。
Select_*不同类型的联接执行计划。
Sort_*几种排序信息。
Show profiles 是MySql用来分析当前会话SQL语句执行的资源消耗情况

165. 百万级别或以上的数据,你是如何删除的?

  正确回答通过率:50.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

我们想要删除百万数据的时候可以先删除索引
然后批量删除其中无用数据
删除完成后重新创建索引

166. B树和B+树的区别,数据库为什么使用B+树而不是B树?

  正确回答通过率:31.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

在B树中,键和值即存放在内部节点又存放在叶子节点;在B+树中,内部节点只存键,叶子节点则同时存放键和值。
B+树的叶子节点有一条链相连,而B树的叶子节点各自独立的。
B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。.

B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。innodb中页的默认大小是16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快.

167. B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据?

 正确回答通过率:45.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

在B+树的索引中,叶子节点可能存储了当前的key值,也可能存储了当前的key值以及整行的数据,这就是聚簇索引和非聚簇索引。 在InnoDB中,只有主键索引是聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引。如果没有唯一键,则隐式的生成一个键来建立聚簇索引。

当查询使用聚簇索引时,在对应的叶子节点,可以获取到整行数据,因此不用再次进行回表查询

168. MySQL列值为NULL时,查询是否会用到索引?

 正确回答通过率:52.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

列值为NULL也是可以走索引的

计划对列进行索引,应尽量避免把它设置为可空,因为这会让 MySQL 难以优化引用了可空列的查询,同时增加了引擎的复杂度

169. 简述MySQL中TEXT数据类型的最大长度

  正确回答通过率:79.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

TINYTEXT:256 bytes
TEXT:65,535 bytes(64kb)
MEDIUMTEXT:16,777,215 bytes(16MB)
LONGTEXT:4,294,967,295 bytes(4GB)

170. MySQL 如何保证缓存-db一致性?

  正确回答通过率:31.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

读的时候先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
更新的时候先更新缓存,再更新数据库。不然的话,数据库更新数据是新数据,而缓存还是旧数据,出现数据不一致。
删除的时候,先删缓存,再删数据库。
原则:缓存先操作,数据库后操作。

171. 阐述数据库分片的两种常见方案 ?

 正确回答通过率:58.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

客户端代理: 分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC层来实现。 当当网的 Sharding-JDBC 、阿里的TDDL是两种比较常用的实现。
中间件代理: 在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。 我们现在谈的 Mycat 、360的Atlas、网易的DDB等等都是这种架构的实现。

172. 简述MySQL5.7 与 MySQL8.0的差异?

 正确回答通过率:60.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

  1. 功能
    NoSQL支持:
    MySQL 从 5.7 版本开始提供 NoSQL 存储功能,在 8.0 版本中这部分功能也得到了更大的改进。

JSON:
MySQL 8 大幅改进了对 JSON 的支持,添加了基于路径查询参数从 JSON 字段中抽取数据的 JSON_EXTRACT() 函数,以及用于将数据分别组合到 JSON 数组和对象中的 JSON_ARRAYAGG() 和 JSON_OBJECTAGG() 聚合函数。

窗口函数:
从 MySQL 8.0 开始,新增了一个叫窗口函数的概念,它可以用来实现若干新的查询方式。
窗口函数与 SUM()、COUNT() 这种集合函数类似,但它不会将多行查询结果合并为一行,而是将结果放回多行当中。即窗口函数不需要 GROUP BY。

隐藏索引:
在 MySQL 8.0 中,索引可以被“隐藏”和“显示”。当对索引进行隐藏时,它不会被查询优化器所使用,我们可以使用这个特性用于性能调试。
在创建完索引后,我们先将其隐藏,然后观察其对数据库的影响。如果数据库性能有所下降,说明这个索引是有用的,然后将其“恢复显示”即可。如果数据库性能看不出变化,说明这个索引是多余的,可以考虑删掉。

降序索引:
MySQL 8.0 为索引提供按降序方式进行排序的支持,在这种索引中的值也会按降序的方式进行排序。

通用表表达式式(Common Table Expressions CTE):
在复杂的查询中使用嵌入式表时,使用 CTE 使得查询语句更清晰。

UTF-8 编码:
从 MySQL 8 开始,使用 utf8mb4 作为 MySQL 的默认字符集。

支持表 DDL 的原子性:
InnoDB 现在支持表 DDL 的原子性,也就是 InnoDB 表上的 DDL 也可以实现事务完整性,要么失败回滚,要么成功提交,不至于出现 DDL 时部分成功的问题,此外还支持 crash-safe 特性,元数据存储在单个事务数据字典中。

支持 crash-safe 特性:
元数据存储在单个事务数据字典中。

高可用性:
InnoDB 集群为数据库提供集成的原生 HA 解决方案。

caching_sha2_password 身份验证插件:
caching_sha2_password是MySQL 8.0中的默认身份验证插件,替换了mysql 5.7的mysql_native_password,身份验证安全性能提升。

授权
与帐户管理相关的授权语法略有差异:
MySQL5.7创建用户和用户授权命令可以同时执行
grant all privileges on . to ‘Gary’@‘%’ identified by ‘Gary@2019’
MySQL8.0创建用户和用户授权的命令需要分开执行

创建用户
create user ‘Gary’@‘%’ identified by ‘Gary@2019’;

用户授权【给予所有权限】
grant all privileges on . to ‘Gary’@‘%’

  1. 性能:
    根据官方说法,MySQL 8 要比 MySQL 5.7 快 2 倍。
    性能提升主要集中在三个领域:

读写工作负载
I/O密集型工作负载
热点竞争问题工作负载。

173. 将MySQL转换到Oracle需要考虑的因素?

 正确回答通过率:90.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

  1. 确定需要转换的MySQL数据库的版本和Oracle数据库的版本
    在进行转换之前,必须确定需要转换的MySQL数据库的版本和Oracle数据库的版本,以此为基础进行后续工作。MySQL和Oracle数据库有很多版本,因此需要保证版本兼容性。

  2. 确定需要转换的数据库对象
    需要确定需要转换的数据库对象,包括表、视图、存储过程、触发器等等。这样可以避免不必要的工作和误解,并确保转换的结果符合预期。

  3. 确定需要转换的数据类型
    MySQL和Oracle数据库有不同的数据类型,需要将MySQL数据库中的数据类型映射到Oracle数据库中的数据类型,以确保转换后数据的完整性。

  4. 确定需要转换的字符集
    MySQL和Oracle数据库有不同的字符集,需要确保在转换过程中保持字符集完整性,以避免数据损失或错误。

  5. 确定需要转换的索引和主键
    需要将MySQL数据库中的索引和主键映射到Oracle数据库中的索引和主键,以确保转换后的结果符合预期。

  6. 确定需要转换的存储过程和触发器
    如果MySQL数据库中有存储过程和触发器,需要将它们转换到Oracle数据库中,并确保它们在Oracle数据库中的运行结果和在MySQL数据库中一致。

  7. 确定需要转换的数据
    需要将MySQL数据库中的数据转换到Oracle数据库中,并确保数据的完整性和准确性。

  8. 使用Oracle SQL Developer进行自动转换
    Oracle SQL Developer是一个免费的工具,可以帮助我们进行MySQL到Oracle数据库的自动转换。这个工具具有易用性和效率,开发人员可以使用它进行快速的转换。

  9. 使用SQL转换工具手动进行转换
    在某些情况下,Oracle SQL Developer自动转换可能无法满足要求,需要使用一些SQL转换工具进行手动转换。

  10. 在Oracle数据库中进行测试
    在转换后,需要对转换后的数据库进行彻底测试,以确保所有的数据库对象和数据的完整性和准确性。

示例1:转换表

首先,我们需要将需要转换的MySQL表的结构导出到一个.sql文件中:

mysqldump -u username -p databasename table_name > table_name.sql
然后,我们需要将这个.sql文件导入到Oracle数据库中:

sqlplus username/password@dbname @table_name.sql
示例2:转换数据

我们可以使用以下命令将MySQL中的数据导出到一个.csv文件中:

SELECT * INTO OUTFILE ‘/path/to/file.csv’
FIELDS TERMINATED BY ‘,’ OPTIONALLY ENCLOSED BY ‘"’
LINES TERMINATED BY ‘\n’
FROM table_name;
然后,我们可以使用Oracle SQL Loader将这个.csv文件导入到Oracle数据库中:

sqlldr username/password control=‘/path/to/control.ctl’
在上面的命令中,'/path/to/control.ctl’指的是控制文件的路径,这个控制文件定义了如何将.csv文件中的数据转换为Oracle数据库中的数据。

174. 简述MySQL Online DDL ?

 正确回答通过率:82.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

Mysql Online DDL是mysql的一个非常重要的特性,允许用户在不停止数据库服务的情况下修改数据库表结构

175. MySQL如何实现字符串长度计算实现代码(gb2312+utf8) ?

 正确回答通过率:54.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

字符集和字符串长度计算规则
MySQL 中的字符串长度计算与字符集有关。在字符集为 ASCII 的情况下,字符串长度计算即为字符串中字符的个数;而在 GB2312 和 UTF8 等多字节字符集下,字符串长度计算需要根据字符的字节数进行计算。例如,一个包含一个汉字的 UTF8 字符串长度计算为 3,因为一个汉字由 3 个字节组成。

gb2312 字符集字符串长度计算
在 gb2312 字符集中,一个汉字占用两个字节,一个非汉字字符占用一个字节。因此,在 gb2312 字符集下,字符串长度计算可以通过使用 LENGTH 函数进行计算。例如,下面的示例中,长度为 6 的字符串由三个汉字和一个字母组成:

SELECT LENGTH(‘你好MySQL’) as len; – 返回 6

utf8 字符集字符串长度计算
在 utf8 字符集中,一个汉字占用三个字节,一个非汉字字符占用一个字节。然而,MySQL 中默认情况下不支持 utf8mb4 字符集,它是一个更广泛支持字符集的 utf8 优化版,它支持 4 个字节的 Unicode 平面 0 和 1。因此,在 utf8mb4 字符集下,字符串长度计算可以通过使用 CHAR_LENGTH 函数进行计算。例如,下面的示例中,长度为 6 的字符串由三个汉字和一个字母组成:

SELECT CHAR_LENGTH(‘你好MySQL’) as len; – 返回 4

176. MySQL如何支持中文排序的实现方法?

  正确回答通过率:55.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

方法一:使用GBK编码
第一种方法是使用GBK编码。我们可以通过设置MySQL的排序规则,将其改为支持GBK编码的方式。在MySQL命令行中输入以下命令:

ALTER TABLE table_name CONVERT TO CHARACTER SET gbk COLLATE gbk_chinese_ci;
其中,table_name是我们想要进行中文排序的表的名称。

执行上述命令之后,MySQL将会将表中所有字符类型的列转换为GBK编码,并且设置GBK编码的中文排序规则。这样,在查询时,MySQL就能够正确地按照中文进行排序了。

方法二:使用UTF8编码
第二种方法是使用UTF8编码。我们可以通过设置MySQL的排序规则,将其改为支持UTF8编码的方式。在MySQL命令行中输入以下命令:

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
其中,table_name是我们想要进行中文排序的表的名称。

执行上述命令之后,MySQL将会将表中所有字符类型的列转换为UTF8编码,并且设置UTF8编码的中文排序规则。这样,在查询时,MySQL就能够正确地按照中文进行排序了。

方法三:使用自定义排序规则
第三种方法是使用自定义排序规则。MySQL提供了一些自定义排序规则,我们可以根据自己的需要进行选择。在MySQL命令行中输入以下命令:

ALTER TABLE table_name MODIFY column_name VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci;
其中,table_name是我们想要进行中文排序的表的名称;column_name是我们想要进行中文排序的列的名称;VARCHAR(100)是我们想要查询的列的类型与长度。

执行上述命令之后,MySQL将会将特定列的排序规则设置为utf8_general_ci自定义排序规则,支持中文排序。

177. 简述MySQL kill 指令的执行原理?

 正确回答通过率:50.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 中级

MySQL kill指令可用于终止正在执行的MySQL进程,本文将详细讲解MySQL kill指令的执行原理。

MySQL kill指令的语法
KILL [CONNECTION | QUERY] thread_id;
其中,thread_id为MySQL进程的线程ID。

使用CONNECTION参数时将中断指定连接进程;
使用QUERY参数时将中断指定查询。
MySQL kill指令的实现原理
MySQL kill指令的实现原理基于MySQL中的进程管理模块。

MySQL通过多线程方式处理客户端请求,每个连接线程分配一个唯一的线程ID。当执行一个查询时,MySQL会为该查询分配一个对应的线程ID,并将该线程ID存储在查询状态的线程变量中。MySQL Server的BP Manager持续处理连接请求,同时,协调着各个线程的执行。BP Manager可以通过检查连接进程和查询进程的状态,实现对进程的停止和重新启动。

使用MySQL kill指令时,MySQL会向指定的进程发送软中断信号(SIGNAL),查询进程将根据收到的信号执行对应的动作,如结束查询。

178. 简述Identity基本定义?

  正确回答通过率:84.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

Identity在Mysql中是一个非常重要的属性,用于表示一列的自增长特性。在创建一个表中的一个列时加上“Auto_Increment”参数,就可以将该列设为自增长列。例:

CREATE TABLE test (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
这里id列就是一个自增长列,每次插入一条新的数据时,该列会自动加1。

179. 简述mysqldump数据库备份参数详解?

  正确回答通过率:69.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

mysqldump [options] [db_name [tbl_name …]]
3. 参数讲解
以下为 mysqldump 常用的参数列表:
a. --opt
–opt 是 mysqldump 的默认选项,它等价于同时指定 --add-drop-table、–add-locks、–create-options、–quick、–extended-insert、–lock-tables。
b. -h, --host
指定要备份数据库的 MySQL 服务器主机地址,默认为 localhost。
c. -u, --user
指定要备份数据库的 MySQL 用户名。
d. -p, --password
指定连接 MySQL 数据库的账号密码。
e. --flush-logs
在每个导出数据的文件完成后,刷新 MySQL 服务器的日志文件。
f. --events
备份 MySQL 的所有事件(Event)。
g. --ignore-table
导出时忽略某个表,多个表之间用逗号分隔

180. 简述MySQL内部临时表 ?

 正确回答通过率:93.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MySQL内部临时表是MySQL服务器在处理查询时所创建的一种特殊表,用于临时存储结果集。它的使用可以提高查询效率,尤其对于大型数据的查询、排序和分组查询非常有效。

MySQL内部临时表在大型数据处理、连接和排序查询中都非常有效,但需要注意的是它只能在当前会话中使用,并且在会话结束时将自动被删除。因此,使用临时表时需要注意数据的备份和恢复。

181. 阐述详解MySQL单列索引和联合索引?

  正确回答通过率:80.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

单列索引
定义
单列索引(也称为单字段索引或简单索引)是对一列或多列中的单个字段创建的索引。单列索引包括唯一索引和普通索引两种类型。

唯一索引:索引字段的值必须唯一,或者允许为NULL(但只允许一个NULL值)。创建唯一索引的语法如下:
CREATE UNIQUE INDEX index_name ON table_name (column_name)
普通索引:索引字段的值可以重复。创建普通索引的语法如下:
CREATE INDEX index_name ON table_name (column_name)
优缺点
优点:单列索引查询速度快,适用于单一查询、排序的场景;
缺点:当索引字段数据重复度很高时,查询性能可能退化,造成表扫描,甚至比不使用索引还慢。
示例说明
以查询学生表中姓“王”的学生信息为例,创建单列索引可用以下两种语法:

使用CREATE INDEX语句创建普通索引:
CREATE INDEX idx_stu_name ON student (name);
使用ALTER TABLE语句添加普通索引:
ALTER TABLE student ADD INDEX idx_stu_name (name);
联合索引
定义
联合索引(也称为组合索引)是多个列上的索引,可加速联合查询和模糊查询的速度。联合索引可以包含多个列,这些列可以使用多种不同的索引类型进行定义。常见的索引类型包括B-Tree索引、哈希索引和全文索引。

B-Tree索引:用于常规查询;
哈希索引:用于精确查询;
全文索引:用于全文查询。
定义
定义联合索引的语法如下:
CREATE INDEX index_name ON table_name (column1, column2, …);
优缺点
优点:联合索引可以加速多个列查询的速度,适用于多条件查询的场景;
缺点:当查询条件不涉及索引起始列时,索引失效,需要进行全表扫描。
示例说明
以查询学生表中姓“王”且年龄在20到25岁之间的学生信息为例,创建联合索引可用以下语句:

CREATE INDEX idx_stu_info ON student (name, age);

ALTER TABLE student ADD INDEX idx_stu_info (name, age);
然后使用以下SQL语句进行查询:

SELECT * FROM student WHERE name = ‘王’ AND age BETWEEN 20 AND 25;
总结
单列索引和联合索引各有优缺点,应根据实际应用场景进行选择。单列索引适用于单一查询、排序的场景,联合索引适用于多条件查询的场景。因此,在表设计时应考虑到数据的读写模式、SQL执行计划等因素,并合理地使用索引以达到优化查询速度的目的。

182. 简述MySQL数据库安全配置的常规设定 ?

  正确回答通过率:30.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

  1. 强密码设置
    MySQL中强密码的设置非常重要,可以有效防止恶意攻击者通过猜测密码或暴力破解攻击进行入侵。

1.1 密码复杂度设置
可以通过修改my.cnf配置文件来设置密码复杂度,如下:

[mysqld]
validate_password_policy=STRONG
validate_password_length=8
其中,validate_password_policy指定使用哪种密码策略,可以设置为LOW(最低级,只要存在密码即可)、MEDIUM(中级,密码必须包含数字和字母)、STRONG(高级,密码必须包含数字、字母和特殊字符);validate_password_length指定密码的最小长度。

1.2 密码复杂度提示
在用户设置密码时,可以通过提示用户密码复杂度,来提醒用户设置更强的密码。

[mysqld]
validate_password_policy=STRONG
validate_password_length=8
validate_password_mixed_case_count=1
validate_password_special_char_count=1
其中,validate_password_mixed_case_count指定密码中必须包含的大小写字母数量,validate_password_special_char_count指定密码中必须包含的特殊字符数量。

  1. 权限控制
    为了防止恶意攻击者通过SQL注入等方式,进而随意操作数据库,需要在MySQL中配置权限控制策略。

2.1 防止Root远程登录
Root用户拥有最高的权限,不应该允许其在远程环境下进行登录。

可以通过修改my.cnf配置文件来禁止Root用户远程登录,如下:

[mysqld]
skip-networking
bind-address = 127.0.0.1
其中,skip-networking表示禁止网络连接,bind-address表示绑定本地地址。

2.2 新建用户及授权
应该为每个应用程序或用户创建独立的MySQL用户,并分配相应的权限,以限制其对数据库的操作范围。

例如,为某个应用程序创建用户:

CREATE USER ‘app_user’@‘localhost’ IDENTIFIED BY ‘password’;
GRANT SELECT, INSERT, UPDATE, DELETE ON database_name.table_name TO ‘app_user’@‘localhost’;
上述例子中,app_user表示新建用户的名称,由’@'localhost’指定了该用户能够从哪个IP地址访问MySQL服务器,SELECT、INSERT、UPDATE、DELETE指定了该用户在相应表格上的操作权限。

  1. 数据库备份与恢复
    定期的备份操作可以保护数据免受不良事件(如硬盘故障、误删除等)的影响,而灾难恢复能够保障遭受某些攻击时能够快速地恢复数据。

3.1 数据库备份
对于备份的数据库,建议采用mysqldump命令或xtrabackup工具进行备份操作。

例如,对某个名为test的database进行备份:

mysqldump -u root -p password test > /backup/test.sql
以上列出了三个部分。第一个部分是命令本身(mysqldump),其后跟随一些命令选项。第二部分(-u root –p password)表示我们需要作为root用户进行连接,并将其加以密码授权。第三部分是操作目标(test database),并表示我们将把备份存储在 /backup/test.sql 文件中。

3.2 数据库恢复
对于已备份好的数据库,可以通过命令行工具或客户端软件进行恢复。

例如,通过mysql命令恢复备份的数据库:

mysql -u root -p test < /backup/test.sql

183. MySQL如何创建并执行事件?

  正确回答通过率:39.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

MySQL事件是可以预定义、独立运行的MySQL代码块。您可以使用MySQL事件来定期执行维护操作,如清除过期数据、备份数据等等。MySQL事件可以在MySQL服务器上创建和执行。

以下是创建和执行MySQL事件的详细步骤:

1.创建一个MySQL事件:

CREATE EVENT my_event
ON SCHEDULE EVERY 1 DAY
DO
BEGIN
– MySQL代码块
END;
上述MySQL事件名为my_event,每天定时运行一次。代码块BEGIN和END之间的语句就是MySQL代码块,可以根据需求编写。

2.修改一个MySQL事件:

ALTER EVENT my_event
ON SCHEDULE EVERY 2 DAY_HOUR
DO
BEGIN
– 修改后的 MySQL代码块
END;
使用ALTER EVENT关键字更新和修改MySQL事件。在上面的示例中,MySQL事件my_event的计划调度方式修改为每两天一次,并且它的MySQL代码块也被修改了。

3.删除一个MySQL事件:

DROP EVENT my_event;
要删除MySQL事件,可以使用DROP EVENT关键字。

4.手动执行MySQL事件:

CALL my_event();
在MySQL服务器上手动执行MySQL事件,只需使用CALL语句并提供事件名称即可。

5.启用MySQL事件调度:

SET GLOBAL event_scheduler = ON;
默认情况下,MySQL事件调度器是处于禁用状态的,即不会执行已创建的MySQL事件。为了启用MySQL事件调度,需要使用SET GLOBAL语句并设置event_scheduler参数为ON。

6.禁用MySQL事件调度:

SET GLOBAL event_scheduler = OFF;
如果需要手动禁用MySQL事件调度器,则可以使用SET GLOBAL语句并设置event_scheduler参数为OFF。

以上是MySQL创建和执行事件的详细步骤。您可以根据自己的需要定期执行MySQL代码块,并且需要注意的是,MySQL事件调度器启用后,一定要及时关闭,否则会影响MySQL服务器的性能。

184. 简述MySQL的join buffer原理?

  正确回答通过率:36.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

MySQL中的join buffer是一种缓存机制,用于优化数据的连接查询。在执行连接查询的过程中,MySQL需要将多个表的数据进行连接匹配,这个过程是比较耗时的。而使用join buffer缓存机制,则可以提高连接查询的效率。

join buffer的原理比较简单,它会将连接操作中的数据缓存在内存中,以便在下一次进行相同的查询时可以直接从缓存中获取数据,而不必访问磁盘或索引。这样可以大大提高查询速度。

join buffer是MySQL重要的优化机制之一,使用它可以大大提升连接查询的效率。但是,join buffer的使用也需要遵循一些原则,比如缓存的数据必须足够小(以避免大量占用内存)、启用join buffer需要根据具体的情况进行配置等。

185. MySQL如何处理无效数据值?

  正确回答通过率:64.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

MySQL会在处理无效数据值时,根据数据类型和使用场景的不同,采取不同的处理方式。主要包括以下几种方式:

数据类型不匹配时,MySQL会自动进行数据类型转换。例如,如果数字类型的字段中存储了字符串类型的数据,MySQL会尝试将其转换为数字类型。如果转换失败,MySQL会将其转换为0或NULL。

字符串类型的字段中存储了超长数据时,MySQL会根据字段的定义,对数据进行截断或报错。一般来说,如果定义了字段的长度,MySQL会对超长数据进行截断。如果没有定义字段长度,MySQL会报错。

若对表中的某个字段定义了非空约束,当插入或更新数据时,如果数据为空或为NULL,MySQL会报错。如果没有定义非空约束,MySQL会将其插入或更新为NULL。

如果插入或更新的数据与表中已有的数据发生冲突(例如,插入或更新数据的主键或唯一约束与已有数据重复),MySQL会采取不同的处理方式。一般来说,MySQL会报错并中止操作,但也可以通过使用ON DUPLICATE KEY UPDATE语句,实现将新数据更新到已有数据中。

186. 简述MySQL InnoDB的3种行锁定方式 ?

 正确回答通过率:57.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

MySQL InnoDB引擎提供了三种行锁定方式:共享锁(S锁)、排它锁(X锁)和意向锁(IS锁和IX锁)。

共享锁(S锁)
共享锁(S锁)是用来保证读取的数据在事务间的一致性。多个事务可以同时获取共享锁定,因为他们都只是读取数据而不做任何修改。但是,一个事务获取了共享锁之后,其他事务便不能再对该行加排它锁。

语法:SELECT … FOR SHARE

例如,假设有一个表t,其中包含字段a和b。两个事务A和B分别执行以下语句:

事务A:SELECT * FROM t WHERE a=1 FOR SHARE;
事务B:SELECT * FROM t WHERE a=1 FOR SHARE;

由于两个事务使用了共享锁定,所以它们都可以查询到字段a=1的行并读取其数据,但是没有一个事务可以对这些行进行修改操作。如果其中一个事务尝试修改这些行,则需要等待另一个事务释放它的共享锁。

  1. 排它锁(X锁)
    排它锁(X锁)是用来在事务中修改数据的。同一时刻只有一个事务可以获取排它锁。其他非当前事务的读写操作都需要等待排它锁释放。也就是说,如果一个事务A想要对一个行进行修改,那么它必须先获取对应的排它锁,否则就需要等待。

语法:SELECT … FOR UPDATE

例如,假设有一个表t,其中包含字段a和b。两个事务A和B分别执行以下语句:

事务A:SELECT * FROM t WHERE a=1 FOR UPDATE;
事务B:SELECT * FROM t WHERE a=1 FOR UPDATE;

由于只有一个事务可以获取排它锁,所以事务B需要等待事务A释放排它锁后才能获取它。

意向锁(IS锁和IX锁)
意向锁(IS锁和IX锁)是用来在表级别上管理行级别锁的。在获取行级别锁之前,必须先获取表级别上的意向锁,在释放行级别锁之后,也需要同样先释放表级别上的意向锁。

意向锁分为两种类型:IS锁和IX锁。

IS锁意味着一个锁定的事务想要在一个表的行上增加共享锁定。IX锁,是一个锁定事务想要在表的行上增加排它锁。

在关于行的锁定之前,在表上增加一个意向锁。如果一个进程想要取出某行的共享锁定,那么MySQL检查表上是否已有一个意向锁,并检查该锁是否为IS。如果是,那么该进程可以在该行上加共享锁定。如果该表有一个IX意向锁,则MySQL允许进程取出排它锁。同样,如果进程想要取出排它锁,那么MySQL会检查该表上是否有一个IX意向锁。

语法:LOCK IN SHARE MODE和FOR UPDATE已经隐含了意向锁。

例如,假设有一个表t,其中包含字段a和b。事务A执行以下语句对表t上锁定:

LOCK TABLE t WRITE;

此时,在事务A释放锁定之前,其他事务T1和T2无法对表t进行任何读写操作,它们会被阻塞。

总之,MySQL InnoDB引擎提供了三种行锁定方式:共享锁(S锁)、排它锁(X锁)和意向锁(IS锁和IX锁)。开发人员可以根据实际需求选择适当的锁定方式以保证数据的一致性和安全性。

187. 简述MySQL日志管理和备份与恢复?

  正确回答通过率:85.0%

[ 详情 ] 推荐指数: ★★ 试题难度: 初级

  1. MySQL日志
    MySQL日志是MySQL服务器为了实现事务的原子性、一致性、隔离性和持久性而进行记录的一些信息。

MySQL日志主要包括:

(1) 二进制日志(Binary Log)
二进制日志记录了所有写操作,以便于备份和恢复。

示例说明
开启二进制日志:

– 修改配置文件,在 [mysqld] 项下添加:
log-bin=mysql-bin
– 重启 MySQL 服务或者使用以下语句:
SET GLOBAL log_bin = ON;
(2) 慢查询日志(Slow Query Log)
慢查询日志记录了在MySQL服务器上执行时间超过设定阈值的SQL语句,便于后续进行性能分析。

示例说明
开启慢查询日志:

– 修改配置文件,在 [mysqld] 项下添加:
slow_query_log_file=/var/log/mysql/mysql-slow.log
long_query_time=2
slow_query_log=ON
– 重启 MySQL 服务或者使用以下语句:
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2; – 设定执行时间超过 2 秒为慢查询
(3) 错误日志(Error Log)
记录了MySQL服务器在运行过程中发生的错误信息。

示例说明
开启错误日志:

– 修改配置文件,在 [mysqld] 项下添加:
log-error=/var/log/mysql/mysql-error.log
– 重启 MySQL 服务或者使用以下语句:
SET GLOBAL log_error = ON;
(4) 查询日志(General Log)
查询日志记录了所有对MySQL服务器执行的SQL语句,包括读操作和写操作

188. 如何MySQL中查询、删除重复记录的方法 ?

 正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

1.1 利用GROUP BY和HAVING子句
SELECT column_name(s) FROM table_name
GROUP BY column_name(s)
HAVING COUNT(*) > 1;
上述代码中,GROUP BY语句根据字段将重复值合并到一起,并统计其数量,HAVING子句过滤掉非重复行。

1.2 利用子查询
SELECT column_name(s) FROM table_name
WHERE column_name IN (
SELECT column_name FROM table_name
GROUP BY column_name HAVING COUNT(*) >1
);
上述代码中,首先用子查询找到重复的记录的字段值,然后在主查询中使用IN语句将其查询出来。

189. 阐述Mysql数据库的QPS和TPS的意义和计算方法?

  正确回答通过率:52.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

MySQL数据库的QPS和TPS是数据库性能评估的两个重要指标,QPS代表每秒查询率,而TPS代表每秒事务处理率。

QPS的计算公式为:Query数/时间,例如,如果在1秒钟内执行了1000次查询,则QPS为1000。QPS可以用来评估系统的查询性能。

TPS的计算方法有三种,分别是Commit、Rollback以及Insert+Update+Delete。其中,Commit+Rollback表示同时并发执行的事务数,Insert+Update+Delete表示每秒钟处理的事务数量。

下面举两个实例说明QPS和TPS的计算方法。

首先,假设有一个Web应用程序,需要从MySQL数据库中每秒查询1000次数据。那么我们可以根据QPS的计算公式,计算出每秒钟需要执行多少次查询。假设在1秒钟内执行了1000次查询,则QPS为1000。

其次,如果一个在线商店需要每秒钟处理100次的订单。在这个场景下,我们可以将TPS计算方法应用到表格数据插入。例如,当一个客户下订单时,需要将数据插入到数据库中,因此我们可以根据Insert+Update+Delete的计算方法,计算其每秒钟处理订单数量的TPS。假设每个订单包含3个条目,因此每个订单将占用3个TPS。因此,在1秒钟内,我们可以计算出每秒钟的TPS为100 * 3 = 300。

综上所述,QPS和TPS是MySQL数据库性能评估的两个重要指标,可以帮助我们了解系统的查询和事务性能。计算方法也相对简单,可以运用到不同的场景中。

190. 主从集群模式下如何为MySQL 增加从库 ?

 正确回答通过率:33.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

在 MYSQL 中,可以通过设置从服务器的方式来实现主服务器的数据复制,以此来提高系统的可用性和容错性。本文将针对 MYSQL 增加从库的方式进行详细介绍。

步骤一:配置主服务器
在主服务器上首先要进行的操作是开启二进制日志。

在 MYSQL 的配置文件 my.cnf 中添加以下配置:

log-bin=mysql-bin
这样可以将所有的 SQL 语句写入到名为 mysql-bin 的二进制日志中。

步骤二:配置从服务器
在从服务器上需要进行的操作包括:

设置主服务器的地址和登录信息
在命令行中执行以下命令:

mysql> CHANGE MASTER TO
-> MASTER_HOST=‘master.host.com’,
-> MASTER_USER=‘slave_user’,
-> MASTER_PASSWORD=‘slave_password’;
将上述命令中的 MASTER_HOST 替换为主服务器的 IP 地址或者域名,MASTER_USER 和 MASTER_PASSWORD 替换为主服务器上的用户名和密码。

配置从服务器的 ID
在命令行中执行以下命令:

mysql> CHANGE MASTER TO
-> MASTER_LOG_FILE=‘mysql-bin.000001’,
-> MASTER_LOG_POS=501;
上述命令中的 MASTER_LOG_FILE 是主服务器上的二进制日志文件名,MASTER_LOG_POS 是该文件的位置。

热门推荐:
PDF电子发票识别软件,一键识别电子发票并导入到Excel中!
10大顶级数据挖掘软件!
人工智能的十大作用!
启动从服务器的复制功能
在命令行中执行以下命令:

mysql> START SLAVE;
验证从服务器的复制状态
在命令行中执行以下命令:

mysql> SHOW SLAVE STATUS;
查看 Slave_IO_Running 和 Slave_SQL_Running 是否均为 Yes,如果是,则说明从服务器已经成功配置。

191. MySQL中如何对Full Text Search全文索引优化?

  正确回答通过率:39.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

创建了全文索引,就可以使用MATCH AGAINST()语法进行全文搜索。
例如,如果我们想要在mytable表中搜索关键词MySQL,则可以使用以下语句:
SELECT * FROM mytable WHERE MATCH(title,content) AGAINST(‘MySQL’);
在进行全文索引优化时,我们可以尝试以下方法:
调整词汇表:MySQL使用自然语言处理库来分析文本,我们可以通过修改MySQL的my.ini文件来调整该库的设置,以便更好地适应我们的环境。
限制搜索范围:如果我们只需要搜索一个特定的列,可以将搜索范围限制在该列上,这样可以提高搜索效率。
调整词汇长度:默认情况下,MySQL会忽略长度少于3个字符的词汇,我们可以将该设置调整为2或1,从而扩大搜索范围。

192. 简述如何对MySQL优化器对索引和JOIN顺序选择 ?

 正确回答通过率:70.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

索引优化的选择过程
MySQL优化器在选择索引时会根据以下因素进行考虑:

索引的可用性:优化器会根据索引的选择性,即索引列中不同值的数量,来评估索引的可用性。选择性越高的索引能够更好地提高查询效率。
索引的覆盖度:在使用覆盖索引时,查询只需要扫描索引而无需访问表中的数据,能够大大提高查询速度。
索引的存储方式:MySQL支持多种类型的索引,如B树索引、全文索引、哈希索引等。优化器会根据查询的条件和数据分布情况,选择最合适的索引类型。
JOIN顺序的选择过程
在SELECT语句中有多个表进行了JOIN操作时,MySQL优化器会根据以下考虑进行JOIN顺序的选择:

表的大小:将较小的表放在JOIN的左侧,能够提高查询效率。这是由于将小表作为驱动表,可以使用快速的嵌套循环算法进行JOIN操作,而避免使用较慢的排序算法。
索引的可用性:当JOIN条件可以使用索引时,优化器会优先选择使用索引的JOIN算法。例如,使用索引嵌套循环算法或索引哈希算法能够快速地完成JOIN操作。
卡片型查询的处理:卡片型查询是指其中一个表的结果集非常小。在这种情况下,优化器会选择使用连接类型为“循环连接(Loop Join)”的算法,有效避免Join导致的内存不足异常。

193. 请复述MySQL缓存的查询和清除命令?

  正确回答通过率:52.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

查询MySQL缓存状态
可以使用以下命令查询MySQL缓存的状态:

SHOW VARIABLES LIKE ‘%query_cache%’;
该命令会返回MySQL缓存的各项参数,其中最重要的参数是query_cache_type和query_cache_size。其中,query_cache_type用于设置MySQL缓存的启用情况,可以是ON、OFF和DEMAND。query_cache_size则是设置MySQL缓存的内存占用大小。

清空MySQL缓存
可以使用以下命令清空MySQL缓存:

FLUSH QUERY CACHE;
该命令会立即清空MySQL缓存。如果缓存中有被修改过的表,则缓存会在被修改后自动清空。

禁用MySQL缓存
可以使用以下命令禁用MySQL缓存:

SET SESSION query_cache_type = OFF;
该命令会关闭MySQL缓存,查询语句将不再被缓存。可以使用以下命令开启MySQL缓存:

SET SESSION query_cache_type = ON;

194. 如何实施SQL性能测试 ?

 正确回答通过率:50.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

我们可以使用Apache JMeter对该查询语句进行并发测试,分析并发访问的响应时间、吞吐量等指标,评判SQL查询语句的性能表现,并通过调整数据库配置和SQL代码,进行性能优化。

195. 综合阐述MySQL性能瓶颈排查定位实例详解?

  正确回答通过率:50.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

MySQL是一款常用的数据库管理系统,如何提升MySQL的性能,是运维工程师面临的重要问题之一。在实际开发及运维工作中,经常遇到MySQL性能瓶颈的问题。解决MySQL性能瓶颈,首先需要了解瓶颈的产生原因。本文将详细讲解MySQL性能瓶颈排查定位实例,并提供两条示例。

一、MySQL性能瓶颈的排查定位实例
1.1 慢查询日志的排查定位
慢查询日志是MySQL提供的用于记录查询时间超过阈值的SQL语句的日志。使用慢查询日志可以方便的找出哪些SQL语句导致了性能问题。

1.1.1 慢查询日志开启
MySQL慢查询日志的开启方法,可以通过修改my.cnf配置文件实现。在[mysqld]下添加以下参数:

slow_query_log=1
slow_query_log_file=/var/log/mysql/slow_query.log
long_query_time=5

说明:

  • slow_query_log:设置是否开启慢查询日志,1为开启,0为关闭,默认为0。
  • slow_query_log_file:设置慢查询日志的保存文件路径。
  • long_query_time:设置慢查询的最大执行时间。单位为秒,默认为10秒。

修改完成后,需要重启MySQL服务。

1.1.2 慢查询日志分析工具
MySQL提供了一个名为mysqldumpslow的工具,可以用于分析慢查询日志。使用mysqldumpslow可以获取慢查询日志中的SQL语句、执行次数和执行时间等信息。

使用示例:

mysqldumpslow /var/log/mysql/slow_query.log
结果示例:

Count: 60 Time=100.01s (6001s) Lock=0.00s (0s) Rows=0.0 (0), example SQL
说明:

  • Count:执行次数。
  • Time:执行时间。
  • Lock:锁等待时间。
  • Rows:所影响的行数。

1.1.3 慢查询日志分析实例
我们可以通过慢查询日志分析工具找到响应最慢的SQL语句。例如,下面是一个执行时间较长的SQL语句:

select t.* from table1 as t inner join table2 as t2 on t.id=t2.id where t.id>1000 order by t.id limit 0,10;
SQL语句的执行时间较长,我们可以尝试优化该SQL语句,例如添加索引或修改查询方式等。

热门推荐:
PDF电子发票识别软件,一键识别电子发票并导入到Excel中!
10大顶级数据挖掘软件!
人工智能的十大作用!
1.2 MySQL死锁的排查定位
MySQL的死锁是指两个或两个以上的事务,由于竞争资源而相互等待的状态。死锁在高并发的场景下经常出现,解决MySQL死锁问题对于提升系统性能至关重要。

1.2.1 查看死锁日志
MySQL提供了查看死锁的工具,可以通过以下SQL语句查看死锁:

show engine innodb status\G;
执行该命令后,可以在输出结果中查看到死锁的信息。例如:


LATEST DETECTED DEADLOCK

YY-MM-DD HH:MM:SS
*** (1) TRANSACTION:
TRANSACTION 170744, ACTIVE 0 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s), undo log entries 1
MySQL thread id 5625, OS thread handle 0x2b094670b700, query id 1891386 localhost root executing
SELECT * FROM xxx WHERE id=xxx lock in share mode
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id xxx page no xxx n bits 80 index PRIMARY of table xxx trx id 170744 lock_mode X locks rec but not gap waiting
Record lock, heap no xxx PHYSICAL RECORD: n_fields xxx; column1 value; column2 value; …
输出结果中提供了死锁的相关信息,包括死锁的时间、事务ID等。

1.2.2 死锁排查实例
如果系统出现了死锁现象,可以通过查看死锁日志的方式解决问题。例如,以下SQL语句在执行时可能出现死锁的情况:

update xxx set value=value+100 where id=xxx;
如果出现死锁的情况,可以尝试将其拆解成两个步骤:

select value from xxx where id=xxx for update;
update xxx set value=xxx+100 where id=xxx;
这样可以避免两个事务同时修改同一条记录导致死锁的情况。

结语
MySQL的性能瓶颈问题往往需要针对具体的业务场景和数据库结构进行排查和定位。在实际工作中,可以参考以上两个示例,快速排查和解决MySQL的性能瓶颈问题。

196. 简述MySQL深度分页(千万级数据量如何快速分页) ?

  正确回答通过率:56.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

在MySQL中,使用OFFSET和LIMIT分页方式的底层实现是一次查询所有行然后返回指定的行数。因此,随着查询结果集的增加,OFFSET值越大,查询时间就会变得越长。

使用覆盖索引优化分页查询
使用覆盖索引可以在不访问磁盘的情况下快速的获取数据,从而能够更快地响应用户的请求。其基本思想是在一个包含所有查询字段的索引上执行查询,并且这个索引是按照相关字段的顺序排列的。这样,就不需要通过索引树访问基础表或者子查询中的符合条件的行了。

示例:

SELECT column1, column2 FROM mytable WHERE id > 10000 LIMIT 10000, 50;
对于上面的SQL语句,可以使用id和包含column1、column2两个列的覆盖索引来查询,这样就可以避免根据id从磁盘加载数据,提高了分页查询的性能。

使用主键分页查询
对于没有合适索引的情况,可以考虑使用主键分页查询来加速查询。这种方式的基本思路是使用主键来分页,参考以下示例:

SELECT column1, column2 FROM mytable WHERE id > 10000 ORDER BY id ASC LIMIT 50;
对于该SQL语句,虽然没有索引,但是可以通过id来进行分页查询,从而提高查询的性能。

避免使用大OFFSET值
在进行MySQL分页查询时,需要避免使用大OFFSET值,比如查询几十万行以后的数据,因为这样做会造成查询效率较低的问题。因此,在进行分页查询时,最好通过其他方法来优化或者进行分页查询后的数据再次进行筛选。

示例:

SELECT column1, column2 FROM mytable WHERE id > 10000 ORDER BY id ASC LIMIT 100, 50;
对于该SQL语句,总共查询出来10050条数据,然后再通过应用程序筛选出所需的数据,以避免使用大OFFSET值的影响。

197. MySQL如何实施Hash索引优化 ?

  正确回答通过率:32.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

Hash是一种非常高效的索引类型,它将索引值与一组固定大小的桶相对应,并且能够快速准确地确定所搜索的记录位置,它将记录散列分散到不同的桶中,通过一个hash函数的计算可以得到对应桶的编号,然后直接查询该桶即可,而不需要遍历整个索引。

【Hash索引的优点和缺点】

优点
Hash索引的查询速度非常快,因为它能够快速定位到对应的记录位置。
适用于等值查询操作,因为Hash索引只支持等值查询。
对于大量数据或者重复数据情况下,Hash索引比较适用,因为Hash索引能够将相同的记录散列到同一个位置上,从而提高索引的效率。

缺点
Hash索引只支持等值查询,不支持范围查询和排序等操作。
Hash索引对查询的记录数有限制,因为Hash散列表的大小有限,当记录过多时,会导致Hash索引失效,因此适用于单表的记录数比较少的情况下。
如何优化Hash索引
在什么情况下使用Hash索引
Hash索引适用于单表的记录数比较少的情况下,例如30万以下的数据量。
对于大量数据或者重复数据情况下,Hash索引比较适用,因为Hash索引能够将相同的记录散列到同一个位置上,从而提高索引的效率。
只适合于等值查询操作。
如何优化Hash索引
风险预测:在建立Hash索引之前,需要对业务数据进行风险预测,判断在当前的数据量和变化曲线下是否适合使用Hash索引。
存储引擎选择:在选择使用Hash索引的存储引擎上,需要尽可能地选择InnoDB引擎,因为InnoDB存储引擎内置Hash索引,能够免去外部维护的成本。
选择合适的Hash函数:选择合适的Hash函数是Hash索引优化的重要一步,因为Hash函数决定了索引的散列方式和影响键值在桶之间分布的程度,进而影响到查询Hash索引的效率。在选择Hash函数时需要考虑业务数据的特点,保证Hash函数的性能指标达到最优。
Hash冲突处理:Hash索引在散列过程中,可能会遇到Hash冲突的问题,这时候需要进行Hash冲突的特殊处理。常见的Hash冲突处理办法有:开放地址法、链接法和二次Hash法等

198. 简述MySQL key_buffer_size参数作用 ?

 正确回答通过率:51.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

在MySQL数据库中,我们经常会遇到大量数据的读取问题。而默认情况下,MySQL使用磁盘来处理读取操作。然而,使用磁盘读取数据的速度相对较慢,因此我们需要一种更快的方法。这就是MySQL的key_buffer_size。

Key_buffer_size是MySQL的一个重要参数,它指定用于缓存索引数据的内存大小。使用key_buffer_size时,MySQL会把尽可能多的索引数据加载到内存中,从而提高读取数据的速度。

如何设置key_buffer_size?
设置key_buffer_size的方法非常简单,只需要在MySQL的配置文件中添加以下行:

[mysqld]
key_buffer_size = 128M
在上述代码中,我们将key_buffer_size设置为128M。可以根据实际情况进行调整。

需要注意的是,在修改完MySQL的配置文件后,需要重启MySQL才能生效。

key_buffer_size设置示例说明
假设我们有一个MySQL数据库,其中包含一个包含100万行数据的表,名为students。这个表的结构如下:

CREATE TABLE students(
id INT PRIMARY KEY,
name VARCHAR(50),
age INT
);
我们希望尽可能快地读取students表中的数据,因此需要使用key_buffer_size。

首先,我们需要判断目前key_buffer_size的大小。可以使用以下命令进行查看:

SHOW VARIABLES LIKE ‘key_buffer_size’;
假设当前的key_buffer_size为32M,我们可以适当增大它的容量,并查看效果:

[mysqld]
key_buffer_size = 256M
修改完配置文件后,重启MySQL,并执行以下查询语句:

SELECT * FROM students;
可以发现,查询速度显著提升了。

199. 简述MySQL COUNT函数的使用与优化 ?

  正确回答通过率:93.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

虽然COUNT函数的使用非常简单,但是当对大规模的数据进行统计时,它也会带来一些性能问题。下面是一些可以优化COUNT函数使用的方法。

使用COUNT(*)代替COUNT(expression)
在一些情况下,我们可以使用COUNT()代替COUNT(expression)来统计符合条件的行数。COUNT()会统计所有行的数量,因此在使用它时不用担心expression是否为NULL。

示例3,在一个订单表(order_record)中统计所有已完成订单的记录数:

SELECT COUNT(*) as finished_order_count FROM order_record WHERE status=‘finished’;
上面这条语句可以这样修改:

SELECT COUNT(*) as finished_order_count FROM order_record WHERE status=‘finished’;
两条语句返回的结果是一样的,但是第二条语句会更快一些,因为它不需要判断status是否为NULL值。

使用COUNT(1)代替COUNT(*)
和COUNT()类似,COUNT(1)也可以用来统计符合条件的行数,因为COUNT(1)会将所有行的1相加,达到相同的效果。由于COUNT(1)比COUNT()更短且更清晰,因此有些优化器会更喜欢使用它。

示例4,在一个学生成绩表(student_scores)中统计所有学生的记录条数:

SELECT COUNT(1) as total_count FROM student_scores;
上面这条语句和示例1中的语句是等价的,但是使用COUNT(1)的语句更短,可能会更快一些

200. MySQL如何快速插入千万级大数据 ?

  正确回答通过率:45.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

1.使用LOAD DATA方式批量导入数据
LOAD DATA是MySQL提供的一个非常快速的方式,可以一次性导入成千上万条记录。语法如下:

LOAD DATA LOCAL INFILE ‘data.txt’ INTO TABLE table_name
FIELDS TERMINATED BY ‘,’
LINES TERMINATED BY ‘\n’
(col1, col2, col3…);
其中,data.txt是你要导入的数据文件,第2行到第6行分别指定了文件的编码方式、字段分隔符、行分隔符和字段列表。需要注意的是,如果文件中的数据列数与FIELDS关键字后的字段数不一致,会导致导入失败。

使用这种方式时,需要在MySQL客户端中设置local-infile=1,才能从本地文件系统读取数据。

示例1:假设有一个包含100万条记录的CSV文件data.csv,文件格式如下:

id,name,age,gender
1,Tom,20,Male
2,Mary,25,Female
3,John,30,Male

我们可以执行以下SQL语句将这些数据批量导入到数据库中:

LOAD DATA LOCAL INFILE ‘data.csv’ INTO TABLE users
FIELDS TERMINATED BY ‘,’
LINES TERMINATED BY ‘\n’
(id, name, age, gender);
在这个例子中,我们将CSV文件中的字段分隔符、行分隔符和字段列表与表的信息一一对应,然后通过LOAD DATA语句将数据直接插入到MySQL表中。

2.使用INSERT INTO SELECT语句插入数据
另一种快速插入数据的方式是使用INSERT INTO SELECT语句,可以将数据从一个表中复制到另一个表中。语法如下:

INSERT INTO table1 (col1, col2, …)
SELECT col1, col2, …
FROM table2;

其中,table1为目标表,table2为源表,要插入的列在括号中列出。这种方式可以用来复制数据、双方表结构完全一致,如果要向目标表中插入新的数据列,需要先对目标表执行ALTER TABLE语句来添加新的列。

201. 简述MySQL query_cache_limit参数 ?

 正确回答通过率:71.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MySQL的query cache可以对频繁执行的SELECT查询进行缓存以提升查询速度,对于数据库查询频率较高的应用场景非常有用。但是,MySQL的query cache不是万能的,如果query cache的参数设置不合理反而会影响查询性能。本文将详细讲解query_cache_limit参数,帮助您更好地优化MySQL的查询性能。

query_cache_limit参数说明
query_cache_limit参数指定查询结果的最大大小,对于超过这个大小的查询结果则不会被缓存。这个参数可以帮助用户在query cache的大小有限的情况下,最大限度地提高缓存的利用率。通常情况下,我们可以将query_cache_limit设置为一个合适的值,以保证高频查询结果得以缓存,而不浪费query cache的空间。

202. MySQL同步问题Slave延迟很大如何排查与解决 ?

  正确回答通过率:43.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

在MySQL主从复制中,Slave延迟很大是一个常见的问题。主要原因是主库写入数据后,需要将数据同步到从库,由于从库的复制是异步的,而且需要一定的时间来完成,所以从库的数据会有一定的延迟。

  1. 使用延迟监控工具
    为了及时了解Slave延迟的情况,我们可以使用一些延迟监控工具,例如pt-heartbeat。这个工具会在主库上生成一个心跳表,然后从库会定期查询这个表的最新时间戳,如果时间戳距离当前时间太远,就说明从库延迟很大。

使用方法如下:

pt-heartbeat --create-heartbeat-table h=主库地址,u=用户名,p=密码
这个命令会在主库上创建一个名为heartbeat的表,从库上运行以下命令:

pt-heartbeat h=主库地址,u=用户名,p=密码
这个命令会查询主库上的heartbeat表,如果从库和主库的时间戳相差太大,就会输出警告信息。

  1. 优化从库性能
    为了降低从库延迟,我们可以对从库进行性能优化,例如:

3.1. 增加从库的硬件配置
如果从库的硬件配置较低,可能会导致复制数据的速度变慢,也会导致延迟问题。可以考虑增加从库的硬件配置,例如增加内存、增加磁盘、升级CPU等。

3.2. 优化从库的MySQL参数
可以根据从库的具体情况,来调整一些MySQL相关的参数,以提高从库的性能,例如:

innodb_buffer_pool_size:调整Innodb缓存池的大小,可以根据实际情况适当增加。
max_connections:调整允许的最大连接数,可以根据实际情况适当调整。
innodb_flush_log_at_trx_commit:调整提交日志的方式,可以根据实际情况选择不同的值来优化性能。

203. 简述MySQL 命名使用规范 ?

 正确回答通过率:50.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

1.1 数据库命名规范
数据库名字只能由下划线、数字和字母组成。
数据库名字应该简短,尽量不超过 30 个字符。
数据库名字应该遵循特定的命名规范。如下:
小写字母和数字用下划线分隔(_)。
在突出单词的形式中,使用大写字母。例如:my_database_name。
1.2 表命名规范
表的名字要符合开头大写的驼峰式命名规范。例如:UserInfo。
名称中只能使用字母和数字,不得使用特殊字符和空格。
名称应简短清晰,尽量不超过 30 个字符。
避免使用 MySQL 关键字作为的表和列名。
1.3 列命名规范
列的名字要符合下划线分隔命名规范。例如:user_name。
名称中只能使用字母和数字,不得使用特殊字符和空格。
名称应简短清晰,尽量不超过 30 个字符。
避免使用 MySQL 关键字作为的表和列名。

204. 简述MySQL query_cache_size 参数作用 ?

 正确回答通过率:89.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

MySQL的高速缓存在处理频繁查询的情况下非常有用。它可以提高查询效率并减少服务器负载。在本攻略中,我们将学习如何启用MySQL高速缓存,并详细介绍其中的参数。

启用MySQL高速缓存
要启用MySQL高速缓存,需要进行以下步骤:

修改MySQL的配置文件my.cnf。在[mysqld]段中加入以下代码:

query_cache_type = 1
query_cache_limit = 1M
query_cache_size = 16M

query_cache_type:设置查询缓存类型。1代表启用查询缓存,0表示禁用查询缓存。
query_cache_limit:设置单个查询结果可以被缓存的最大值。默认为1M。
query_cache_size:设置整个缓存区的大小。默认为0,表示禁用缓存区。建议设置为64M或更大。
重启MySQL服务。

sudo service mysql restart

参数详解
query_cache_type
query_cache_type用于设置查询缓存类型,其值只能为0或1。

0:表示禁用查询缓存;
1:表示启用查询缓存。
query_cache_limit
query_cache_limit用于设置单个查询结果可以被缓存的最大值。如果某个查询结果超过了该值,将不会被缓存。

例如,将query_cache_limit设置为10M:

query_cache_limit = 10M
这样,任何查询结果大小超过10M的查询都不会被缓存。

query_cache_size
query_cache_size用于设置整个缓存区的大小。如果该值为0,表示禁用查询缓存。

例如,将query_cache_size设置为128M,可以将缓存区大小设置为128MB:

query_cache_size = 128M
这样,可以为MySQL的查询缓存分配128MB的内存。

示例说明
以下是两个示例,说明如何设置MySQL的查询缓存。

示例一
假设有一个查询频次非常高的表books,我们可以将该表的查询结果缓存起来。

修改MySQL的配置文件my.cnf。

query_cache_type = 1
query_cache_limit = 1M
query_cache_size = 64M

重启MySQL服务。

sudo service mysql restart

在查询时,使用SQL_CACHE关键字将查询结果缓存起来。

SELECT SQL_CACHE id, title, author FROM books WHERE category = ‘fiction’;

示例二
假设我们不想缓存某个表的查询结果,例如表users。

修改MySQL的配置文件my.cnf。

query_cache_type = 1
query_cache_limit = 1M
query_cache_size = 64M

重启MySQL服务。

sudo service mysql restart

热门推荐:
PDF电子发票识别软件,一键识别电子发票并导入到Excel中!
10大顶级数据挖掘软件!
人工智能的十大作用!
在查询时,使用SQL_NO_CACHE关键字避免将查询结果缓存起来。

SELECT SQL_NO_CACHE id, username, email FROM users WHERE last_login > ‘2020-01-01’;

基于C#实现一个简单的FTP操作工具
c#在sql中存取图片image示例

205. 简述MySQL性能优化配置参数之thread_cache和table_cache?

  正确回答通过率:77.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

thread_cache参数详解
MySQL在处理客户端连接时,需要创建新的线程来处理请求。创建线程需要消耗系统资源,因此如果在高并发情况下频繁地创建和销毁线程,会导致系统负载过重,从而降低系统性能。

thread_cache参数可以缓存创建的线程,避免频繁地创建和销毁线程,从而可以提高系统的性能。该参数表示线程池的大小,设置较大会占用过多的内存,设置过小会导致频繁的线程创建和销毁。

thread_cache参数的默认值为0,表示不启用线程缓存。如果要启用线程缓存,建议将该参数设置为数百或数千。

下面是一个示例,展示如何设置thread_cache参数:

#设置thread_cache参数值为100
set global thread_cache_size=100;
table_cache参数详解
MySQL在读取数据时,需要将数据缓存到内存中。如果MySQL缓存的数据量太小,会导致频繁地从磁盘中读取数据,降低系统的性能。table_cache参数用于设置缓存的表的数量,每个表占用一个文件描述符,因此该参数还可以用于限制与服务器建立的文件描述符数。

table_cache参数的默认值为64,如果要提高系统的性能,建议适当地增大该值。

下面是一个示例,展示如何设置table_cache参数:

#设置table_cache参数值为1000
set global table_open_cache=1000;
总结
thread_cache和table_cache这两个参数是MySQL中用于优化性能的重要参数。thread_cache用于缓存MySQL连接线程,减少线程的创建和销毁,提高系统性能;table_cache用于缓存表数据,避免频繁地从磁盘中读取数据,从而提高查询性能。在实际应用中,可以根据实际情况,适当地调整这两个参数的值,以达到最优的性能优化效果。

206. MySQL性能突然下降,如何思考排除 ?

  正确回答通过率:38.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

在MySQL性能出现突然下降的情况下,我们需要找出具体原因,才能进行有效的调整和解决。其中,常见的性能下降原因有以下几种:

1.1. SQL语句的问题
全表扫描:当表中数据量大的时候,SQL查询语句中如果使用了全表扫描的方式,会导致性能下降。此时需要优化查询语句,尽可能使用索引、分区等方式来加速查询。
join语句问题:当查询中有join语句的时候,也容易出现性能下降的情况。针对这种情况,可以使用子查询、去掉不必要的字段、划分任务等方式进行优化。
临时表或者自定义函数:在SQL语句中使用了临时表或者自定义函数,也容易造成性能下降的情况,需要进行优化。
1.2. 数据库配置问题
参数设置不当:在MySQL配置中,参数设置不当也容易导致性能下降,特别是一些缓存参数和连接参数的设置。可以通过查看日志和参数调整来优化配置。
内存不足:当MySQL所在的服务器内存不足的时候,也容易导致性能下降的情况。需要检查服务器内存情况,增加内存或者减少MySQL占用的内存等方式进行优化。
1.3. 硬件问题
硬盘故障:当MySQL所在的硬盘发生故障的时候,也会导致性能下降。特别是当硬盘的I/O读写速度降低的时候,需要及时对其进行维修或更换。
网络问题:当MySQL所在的服务器与客户端之间的网络出现故障的时候,也会导致性能下降。可以通过检查网络连接和网络传输速度来进行优化。

  1. 解决方法
    在分析出MySQL性能下降的原因之后,接下来就是针对性地解决问题。

2.1. SQL语句优化
索引加速查询:对查询中经常使用的列加索引,能够大大缩短查询时间。
避免子查询:尽量不要使用子查询,如果一定需要使用,可以将其转为内连接或者外连接的方式进行优化。
慢查询日志查看:通过开启MySQL的慢日志,并查看慢查询日志进行SQL语句的优化。
2.2. 配置优化
缓存参数调整:根据实际情况修改MySQL参数(例如:innodb_buffer_pool_size、innodb_log_file_size、key_buffer_size等)。
连接数限制:根据服务器硬件配置,合理调整MySQL的最大连接数。
内存优化:将MySQL所占用的内存与服务器总内存进行协调。
2.3. 硬件优化
硬盘检查和优化:通过检查硬盘状态,调整磁盘分区和使用磁盘缓存等方式进行优化。
网络检查和优化:通过检查网络连接和传输速度,调整网络参数等方式进行优化。

207. 如何使用MySQL Slow Log来解决MySQL CPU占用高的问题 ?

  正确回答通过率:51.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

使用MySQL Slow Log来解决MySQL CPU占用高的问题,可以通过以下步骤实现:

  1. 开启MySQL Slow Log
    在MySQL配置文件(一般为my.cnf或者my.ini)中开启slow_query_log,并且设置slow_query_log_file,如下所示:

slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
设置完毕后,重启MySQL服务即可生效。

此时,MySQL会将执行时间超过long_query_time秒的查询语句记录在slow_query_log_file中。

  1. 分析Slow Log
    通过分析slow_query_log文件,可以了解MySQL中哪些查询语句执行效率过低,从而引起CPU占用高问题。使用mysqldumpslow工具可以对slow_query_log文件进行分析,示例代码如下:

mysqldumpslow -s c -t 10 /var/log/mysql/mysql-slow.log
其中,-s c表示按照执行次数排序,-t 10表示输出前十个查询语句。

通过分析输出结果,可以找出哪些查询语句频繁执行,且执行时间比较长,进而分析原因。

  1. 优化查询语句
    针对分析出来的Slow Log中的查询语句,可以结合实际情况进行相应的优化。

208. 如何调整my.cnf参数配置实现InnoDB引擎性能优化 ?

  正确回答通过率:32.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

步骤一:备份原有my.cnf文件
在修改my.cnf文件前,我们应该先备份原有的my.cnf文件,以便在修改出现问题时可以恢复到原有配置。

cp /etc/mysql/my.cnf /etc/mysql/my.cnf.bak
步骤二:优化my.cnf参数配置
以下是一些通过my.cnf参数配置实现InnoDB引擎性能优化的参数:

#为InnoDB启用调整性能参数
[mysqld]
#缓冲池大小
innodb_buffer_pool_size = 1G
#日志文件大小
innodb_log_file_size = 256M
#线程池大小设置
innodb_thread_concurrency = 8
#自动合并线程空闲时间
innodb_thread_sleep_delay = 10000
#撤销段设置大小
innodb_undo_tablespaces = 2
#稳定的睡眠时间调度是否启用
innodb_adaptive_flushing = 1
#添加外键索引检查
innodb_adaptive_hash_index = 1
innodb_buffer_pool_size:指定InnoDB缓冲池的大小,该值的合理设置对于提升InnoDB性能非常重要。一般建议将innodb_buffer_pool_size设置为物理内存的70%-80%。
innodb_log_file_size:指定InnoDB日志文件的大小,默认为48M,一般建议将其设置为物理内存的1/4,比如如果系统物理内存为4G,则innodb_log_file_size的推荐设置为1G。
innodb_thread_concurrency:指定InnoDB可同时运行的线程数,一般根据CPU核心数量设置,比如CPU为8核,则可以将innodb_thread_concurrency设置为8。
innodb_thread_sleep_delay:指定InnoDB自动合并线程的空闲时间间隔,单位是纳秒。该值默认为10000(10毫秒)。
innodb_undo_tablespaces:指定InnoDB撤销段的个数。建议将其设置为2-3,以便在撤销表时可以并行处理。
innodb_adaptive_flushing:开启InnoDB自适应刷新,可以最大限度地降低InnoDB写入操作的开销。
innodb_adaptive_hash_index:开启外键索引检查,可以提高InnoDB性能。
步骤三:重启MySQL服务使参数生效
修改完成my.cnf文件后,应重启MySQL服务以使修改的参数生效。

209. 思考如何优化MYSQL中binlog ?

  正确回答通过率:58.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

在MYSQL的开发和维护过程中,我们通常会面临 binlog 日志过多导致性能下降的挑战。为了解决这个问题,本文将探讨一些优化 binlog 的思考过程和方法。

一、日志格式
在 MYSQL 中,我们可以通过设置不同的 binlog 日志格式以达到优化性能的目的。常用的日志格式包括 STATEMENT、ROW 和 MIXED。其中,STATEMENT 是默认选项,但在某些场景下会存在一些限制和问题;ROW 格式则以行为单位写入日志,对于大量写操作的应用程序效果尤为明显;而 MIXED 则是 STATEMENT 和 ROW 两种方式的结合体,通常是为了兼顾 STATEMENT 和 ROW 两种方式的优点,同时避免它们各自的缺点,因此是常用的优化方案之一。

二、过滤无关日志事件
MYSQL 的 binlog 日志其实记录了很多与我们的应用程序并无关联的事件,对于这些事件的处理通常只会浪费数据库资源,进而影响 MYSQL 的性能。因此,我们可以通过一些方法过滤掉这些与应用程序无关的日志事件,来缓解 binlog 产生的性能问题。比如:

过滤掉读操作的日志事件;
忽略对较小表的更改;
忽略没有变化的更新操作等。
下面是一个忽略对于 test 表的所有更新、插入和删除的例子:

SET @@session.sql_log_bin = 0; #关闭binlog记录

UPDATE test SET id = 1 WHERE id = 1; – 无效的更新,不会触发binlog

INSERT INTO test(id, name) values (1, ‘test’); – 无效的插入,不会触发binlog

DELETE FROM test WHERE id = 1; – 无效的删除,不会触发binlog

SET @@session.sql_log_bin = 1; #恢复binlog记录
三、批量提交日志
将多个 SQL 语句合并为一个事务后一起提交,可以大幅度减少 binlog 日志的产生量。我们可以通过一下几种方式来实现批量提交:

热门推荐:
PDF电子发票识别软件,一键识别电子发票并导入到Excel中!
10大顶级数据挖掘软件!
人工智能的十大作用!
将多个 SQL 语句合并到一个事务中;
根据应用程序的需求增加事务提交的时间间隔;
对于批量更新、批量插入等大量 SQL 语句的执行,可以将它们分散到不同时间段执行。
下面给出一个批量插入的例子:

SET @@session.sql_log_bin = 0; #关闭binlog记录

START TRANSACTION;

INSERT INTO test(id, name) values (1, ‘test1’);
INSERT INTO test(id, name) values (2, ‘test2’);
INSERT INTO test(id, name) values (3, ‘test3’);

COMMIT;

SET @@session.sql_log_bin = 1; #恢复binlog记录
四、增量备份
在使用 MYSQL 的 binlog 日志时,我们可以根据 binlog 的日志序列号来进行增量备份。与全量备份不同的是,增量备份可以跳过已经备份过的数据,节省备份成本。具体方法可以参考以下例子:

#备份命令
mysqlbinlog --start-position=1234 --stop-position=5678 binlog.0001 > binlog_backup.sql

在这个例子中,binlog.0001 是 MYSQL 的 binlog 日志文件,2134 和 5678 为指定备份的日志起始位置和结束位置。

五、分离日志机制
如果你的 MYSQL 数据库为 Master/Slave 的架构,我们可以将 binlog 日志文件的读写分离到不同机器上,这样可以以降低对 Master 机器的负担,进而提升 MYSQL 的性能。

下面是一个配置 Slave 作为专用 binlog 服务器的例子:

[mysqld]
server-id=1
log-bin
binlog-do-db=test

[mysqldump]
master-data=1

[replica]
log-slave-updates=1
relay-log=relay
relay-log-index=relay.index
slave-net-timeout=5

在这个例子中,Slave 服务器会负责 binlog 文件的写入,从而减轻 Master 服务器的负担。

六、定期清理
最后,我们需要定期清理 binlog 日志文件,以免过多的日志文件占用磁盘空间,影响 MYSQL 的性能。清理方法包括手动删除或定期配置自动删除任务,其中自动删除任务可以通过 MySQL 的参数进行设置。以下是一个手动删除 binlog 日志文件的例子:

#手动清除一周以前的binlog日志
find /path/to/binlog -type f -name “binlog.0*” -mtime +7 | xargs rm -f
在这个例子中,/path/to/binlog 是 MYSQL binlog 日志文件所在的目录,-mtime +7 表示删除一周以前的日志文件。

210. MySQL thread_stack连接线程的优化策略 ?

 正确回答通过率:56.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

MySQL 的 thread_stack 参数用于配置连接线程的最大栈空间大小,是一个影响 MySQL 运行性能的重要参数。在高并发、大数据量场景下,可通过调整该参数来优化 MySQL 的连接线程,提升系统的性能和稳定性。

下面是一个完整的 MySQL thread_stack 连接线程优化攻略,包括调整步骤和示例说明。

步骤一:查看默认 thread_stack 值
在执行任何调优操作之前,先要查询 MySQL 当前的 thread_stack 参数值,并记录下来,以便后续比较分析。

SHOW variables LIKE ‘thread_stack’;
默认情况下,thread_stack 参数值为 262144,即 256 KB。

步骤二:确定合适的 thread_stack 大小
合适的 thread_stack 大小需要结合服务器的硬件配置、数据量、负载情况等因素进行综合考虑。通常情况下,我们建议将 thread_stack 参数设置为 512 KB 或 1024 KB,以便处理大数据查询、复杂查询和连接池等高并发负载,提高系统的稳定性和响应速度。

可以根据当前服务器的硬件资源分配情况,动态调整 thread_stack 参数,以适应 MySQL 运行要求。

步骤三:修改 thread_stack 参数
可以通过下面的 SQL 语句来修改 MySQL 的 thread_stack 参数:

SET GLOBAL thread_stack = 1048576; – 1MB
注意:使用 SET GLOBAL 命令修改全局变量时,可能会影响到系统的稳定性和性能。建议在测试环境中进行验证,或者在繁忙时段操作时备份数据,以确保数据安全和服务质量稳定。

211. 简述Semisync Replication的作用 ?

 正确回答通过率:63.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

MySQL 5.7版本引入了Semisync Replication功能,通过在主从数据库之间实现同步的Semi-Sync机制来提高主从同步的可靠性。但是在高并发并发情况下,Semisync Replication可能会成为瓶颈,影响主库的性能,需要进行优化。

改进方式
以下是针对Semisync Replication的可选改进方式:

提高timeout
Semisync机制需要等待从库确认,如果确认时间过长,会影响主库性能。可以通过提高主库的等待时间来降低从库确认时间,从而提高性能。

可以使用以下参数来控制timeout:

rpl_semi_sync_master_timeout=[timeout in seconds]
rpl_semi_sync_slave_timeout=[timeout in seconds]
指定同步比率
Semisync Replication默认使用的是1:1的同步比率,即需要等待所有从库都确认后才能提交。但是,在高并发情况下,可以通过指定较低的同步比率来提高主库的性能。

可以使用以下参数来控制同步比率:

rpl_semi_sync_master_wait_for_slave_count=[number of slaves]
例如,以下代码将同步比率设置为1:2:

rpl_semi_sync_master_wait_for_slave_count=2
提高并发度
可以增加从库并发处理的能力,从而提高性能。可以使用以下参数来控制并发度:

rpl_semi_sync_slave_threads=[number of threads]
案例分析
以下是两个案例,演示如何使用上述方法优化Semisync Replication性能:

案例1:提高timeout
在高并发环境下,Semisync Replication的timeout可能成为瓶颈,影响性能。我们可以通过提高timeout来解决问题。

例如,以下代码将主库的rpl_semi_sync_master_timeout设置为5秒:

rpl_semi_sync_master_timeout=5
案例2:指定同步比率
在高并发并发情况下,可以通过指定较低的同步比率来提高主库的性能。

例如,以下代码将同步比率设置为1:2:

rpl_semi_sync_master_wait_for_slave_count=2
结论
通过以上优化方法,可以提升Semisync Replication性能,使主从同步更加可靠。在实际应用中,需要根据具体的场景进行优化选择。

212. 简述MySQL 中常见的几种高可用架构部署方案 ?

  正确回答通过率:51.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

一、主从复制架构
主从复制是MySQL常见的一种高可用性架构,通过将主节点上的变更同步到多个从节点上来保证数据的高可用性。以下是主从复制架构的部署步骤:

在主节点上设置server_id;
在主节点上开启binlog并设置binlog_format为row;
在从节点上设置server_id;
在从节点上通过CHANGE MASTER TO命令指定主节点的ip、端口、用户名和密码等信息;
在从节点上通过START SLAVE命令开始同步数据。

二、主从复制+主节点切换
在主从复制架构的基础上,当主节点宕机时,需要手动将从节点切换为主节点来保证数据的可用性。以下是主从复制+主节点切换架构的部署步骤:

在主节点和从节点上执行主从复制架构的部署步骤;
在应用层使用一个VIP作为MySQL服务的入口,并将该VIP指向当前主节点的IP地址;
配置主节点和从节点的监控系统,在主节点宕机时,监控系统会自动切换VIP指向从节点;
进行主节点切换操作,将从节点切换为主节点

三、MySQL Cluster
MySQL Cluster是MySQL的另一种高可用性架构,采用多节点集群方式来提供高可用性和可扩展性

213. 简述什么是两阶段提交 ?

  正确回答通过率:57.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 中级

两阶段提交的过程涉及到协调者和参与者。协调者可以看做成事务的发起者,同时也是事务的一个参与者。对于一个分布式事务来说,一个事务是涉及到多个参与者的。具体的两阶段提交的过程如下:
第一阶段:
首先,协调者在自身节点的日志中写入一条的日志记录,然后所有参与者发送消息prepare T,询问这些参与者(包括自身),是否能够提交这个事务;
参与者在接受到这个prepare T 消息以后,会根据自身的情况,进行事务的预处理,如果参与者能够提交该事务,则会将日志写入磁盘,并返回给协调者一个ready T信息,同时自身进入可提交状态;如果不能提交该事务,则记录日志,并返回一个not commit T信息给协调者,同时撤销在自身上所做的数据库改;
第二阶段:
协调者会收集所有参与者的意见。(1)如果收到参与者发来的not commit T信息,则标识着该事务不能提交,协调者会将Abort T 记录到日志中,并向所有参与者发送一个Abort T 信息,让所有参与者撤销在自身上所有的预操作;(2)如果协调者收到所有参与者发来prepare T信息,那么协调者会将Commit T日志写入磁盘,并向所有参与者发送一个Commit T信息,提交该事务。(3)若协调者迟迟未收到某个参与者发来的信息,则认为该参与者发送了一个VOTE_ABORT信息,从而取消该事务的执行。

214. 简述MySQL是如何保证数据不丢失的 ?

  正确回答通过率:76.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 初级

根据 WAL 机制,只要 ​​redo log​​​ 和 ​​binlog​​ 能保证持久化到磁盘,就能保证数据不丢失

215. MySQL 数据库水平切分方案及问题诠释?

  正确回答通过率:38.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 高难

数据库切分
数据库切分分为水平切分,垂直切分, 垂直切分一般在拆分系统的时候使用,这里不再赘述,下面主要说数据的水平切分。
水平切分方式

  1. 只分表:在一个数据库下面,分成10张表,表名 user_0 ,user_1, user_2…
    数据集中在一台服务器上,当单机性能瓶颈的时候,后续扩展困难。

  2. 只分库,分成10个库,每个库一张表, 表名都是一样的。 db0-user db1-user db2-user…
    出现跨库,没有办法使用事务。不过在分布式系统中,一般不会使用事务,保证数据最终一致性即可

  3. 分表分库,10X10这种方式。 先分10个库, 每个库10张表。
    分表算法
    确定了表切分的方式,接下来就是要根据一定的规则把数据落入到指定表中,这里介绍两种形式,
    取模:即找到某个字段,这个字段通过取模后的值尽可能平均,根据字段取模的方式决定数据落在哪张表,比如,我们订单根据用户Id来决定落在哪张表。
    日期:这种方法在最开始的时候,并没有决定要分多少张表,只是指定日期的数据落到指定的表中,比如用户注册,在2017-5-30日注册,则可以将数据落入user_201705,这张表中。
    这两种分表方法各有优劣,按照取模分,每张表的数据可以尽可能的平均,但是如果后面表扩展则比较麻烦,按照日期来分,虽然可以解决表扩展问题,但是数据有可能不平均,比如在5月,举办了促销,结果那个月注册的人很多。
    Id
    当数据开始写数据库,Id就是要考虑的,这里有几个解决方案:

  4. Id自增,步进=分表数。比如分了3张表,每张表的起始Id不一样,并且自增的幅度=表数量,这样Id就是1,4,7 2,5,8 3,6,9 ,但是如果以后分表数增加,Id的步进还要变。

  5. 单独的表,用于记录自增,可以单独一张表,里面有一列,记录的是当前的id, 可以获取下一个Id, 只是这样每次都要访问这张表,会有性能瓶颈。

  6. Guid

  7. snowflake算法
    关于Id有几个注意的地方,如果你的Id有可能出现在页面上, 比如订单Id, 用户Id ,尽量不要使用自增的,因为别人可以根据这些Id,看出你现在的用户规模,订单量。通过在两天中相同时间下单,可以看出你的交易量,如果权限没有控制好,通过遍历可以查出所有的信息。
    我们这里以用户表为例,看把用户信息写入数据库的一些方法,以及这些方法的一些问题。
    当一个新用户注册,并没有Id,可以通过分布式Id获取到一个Id ,并对这个Id取模,得到具体的表,然后将Id连同用户信息写入表。 后面如果要根据Id得到用户信息,只要对Id采用相同的方法,即可查到对应的信息。
    但是上面的方法没有覆盖到一个场景,用户登录都是通过用户名登录的,怎么查呢,这个时候,一般的方法就是并行查所有的表,好一点的方法就是,在注册的时候,额外建立一个映射,是username->表名的映射,当用户登录的时候,可以根据这个映射找到对应的表名,然后根据表名,再插到具体的用户,这个映射可以放到数据库中,也可以放到redis/mongodb中。
    上面的方法可以解决问题,但是需要引入映射,如果不想要映射, 这个时候可以采用复合Id , 我们使用用户名进行取模,算出具体的表索引,然后通过分布式Id+表索引作为新的Id(NewId)插入到表中,这样我们对用户名进行计算可以得到表索引,通过对NewId进行计算也可以得到表索引(NewId包含了分布式Id和表索引,通过分离,可以得到表索引)。
    我们上面没有考虑到扩展,比如现在我们有10张表,过段时间,发现10张表的存储也快满了, 这个时候就要再扩展10张表,变成20张表,那取模算法也要改,这个时候再对以前的NewId进行计算可能就得不到准备的表了,所以在NewId中,我们还要包含一个算法版本号。
    事务
    当所有的操作都在一个数据库的时候, 可以很方便的使用事务,比如Java下spring的声明式事务,但是当出现跨库操作,事务的使用就不怎么方便了,对于互联网公司,大多数系统都是分布式的,会选择柔性事物。
    扩容方式
    随着业务的发展,数据量增多,我们需要再次对表进行扩展,扩展方式如下:

  8. 需要迁移数据

  9. 首次扩展:假如我们要开始分库分表,原来有一个库一张表,现在要扩展为10个,可以新建9个slave库,等9个slave库数据都和主库都同步了,然后修改路由算法。

  10. 扩容后再扩容:比如现在3个表,要改为5个表,采用Hash算法,当数据扩容,则整体数据都要做迁移。 新增和删除都要做。 技巧:选择2个倍数,可以只做新表新增和删除,这个可能需要用到双写。

  11. 划分树形组,比如,之前一个数据库,不需要Hash,现在新增9个,同步数据,完成后,修改路由算法(321%10),再删除数据,如果10个数据库不够,则再次扩容,原来的10个库,每个库各自再扩展9个库(可根据实际需要扩展),同步数据,方法和上面第一种类似,然后通过 321%10 321/10%10, 算出具体的数据库。如果不够,可以用同样的方式扩容。

  12. 不迁移数据

  13. 根据时间定义,比如一个月一张表。

  14. 定义mapping关系,可以放入到分布式缓存中,写入的时候,写入缓存,读取的时候读取缓存, 如果缓存失效,全量读取。

  15. 增量和Hash同时使用,定义策略,1-1000W一张组,1000-3000W一张组,组内,根据Hash避免热点数据。 新数据都会到新的数据库中。这里注意,这个组不要和机器绑定,比如1-1000W,在DB0机器,1000-3000W在DB1机器,虽然数据Hash, 热点数据不会在同一个表中,但是还是在通一台机器。 要考虑如下的方式,热点数据还是会分布在老机器上。

  16. 生成的ID具有自描述性。 ID+DBIndex,比如Id为321,Hash命中到第一张表,变为32101,最后两位表示具体的数据库索引,老的数据库也会写数据,如果我们的表增多,则修改hash算法,只命中到新表。
    分库分表解决方案
    目前分库分表的解决方案主要集中在这几层:

  17. dao层,在dao层根据指定的分表键决定要操作那个数据库。

  18. ORM层

  19. JDBC层,比较有名的是sharding-jdbc.

  20. 代理层,比如mycat.
    总结
      分库分表是一个大工程, 如何分, ID怎么取, 事物怎么做都是要考虑 的。另外大家不要用操作单表的思维去操作多表,有些人一接触分表就去考虑gourp by 怎么做, join怎么做。 从我接触的一些分表来看,如果牵扯到分表,操作都比较简单,基本在执行sql前都已经确定了要操作哪张表。 当然如果真的遇到要join的操作或者没有办法确定数据在哪个表中,像sharding-jdbc,mycat这种透明分表分库的都会帮你处理。

216. MYSQL如何启用日志和查看日志?

 正确回答通过率:78.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 初级

mysql有以下几种日志: 错误日志: -log-err 查询日志: -log 慢查询日志: -log-slow-queries 更新日志: -log-update 二进制日志: -log-bin 是否启用了日志 mysqlshow variables like ‘log_%’;
怎样知道当前的日志 mysql show master status;
顯示二進制日
  mysql有以下几种日志:
  错误日志: -log-err
  查询日志: -log
  慢查询日志: -log-slow-queries
  更新日志: -log-update
  二进制日志: -log-bin
  是否启用了日志
  mysql>show variables like ‘log_%’;
怎样知道当前的日志
  mysql> show master status;
顯示二進制日志數目
  mysql> show master logs;
看二进制日志文件用mysqlbinlog
  shell>mysqlbinlog mail-bin.000001
  或者shell>mysqlbinlog mail-bin.000001 | tail
  在配置文件中指定log的輸出位置.
  Windows:Windows 的配置文件为 my.ini,,一般在 MySQL 的安装目录下或者 c:/Windows 下。
  Linux:Linux 的配置文件为 my.cnf ,一般在 /etc 下。
  在linux下:
  Sql代码
  #在[mysqld] 中輸入
  #log
  log-error=/usr/local/mysql/log/error.log
  log=/usr/local/mysql/log/mysql.log
  long_query_time=2
  log-slow-queries= /usr/local/mysql/log/slowquery.log
  [sql]
  #在[mysqld] 中輸入
  #log
  log-error=/usr/local/mysql/log/error.log
  log=/usr/local/mysql/log/mysql.log
  long_query_time=2
  log-slow-queries= /usr/local/mysql/log/slowquery.log
  windows下:
  Sql代码
  #在[mysqld] 中輸入
  #log
  log-error=“E:/PROGRA1/EASYPH1.0B1/mysql/logs/error.log”
  log=“E:/PROGRA1/EASYPH1.0B1/mysql/logs/mysql.log”
  long_query_time=2
  log-slow-queries= “E:/PROGRA1/EASYPH1.0B1/mysql/logs/slowquery.log”
  [sql]
  #在[mysqld] 中輸入
  #log
  log-error=“E:/PROGRA1/EASYPH1.0B1/mysql/logs/error.log”
  log=“E:/PROGRA1/EASYPH1.0B1/mysql/logs/mysql.log”
  long_query_time=2
  log-slow-queries= “E:/PROGRA1/EASYPH1.0B1/mysql/logs/slowquery.log”
  开启慢查询
  long_query_time =2 --是指执行超过多久的sql会被log下来,这里是2秒
  log-slow-queries= /usr/local/mysql/log/slowquery.log --将查询返回较慢的语句进行记录
  log-queries-not-using-indexes = nouseindex.log --就是字面意思,log下来没有使用索引的query

217. Linux下如何为MySQL开启更新日志 ?

  正确回答通过率:60.0%

[ 详情 ] 推荐指数: ★★★ 试题难度: 中级

查看方法,在windows下需要修改mysql安装目录到my.ini文件,在linux下需要修改etc/my.cnf文件,找到my.cnf文件,用vi打开,里面有一个注释了的log-update ,在其下面加上一行,为其配置路径,然后保存。然后到mysql到安装目录的bin目录下执行两个命令,就是重启mysql,,我的mysql是源文件安装的,要是用rpm安装的还是百度下其对应到重启命令吧。
#mysqladmin -u root -p shutdown 然后输入mysql的密码
#mysqld_safe --user=root &然后直接运行个update语句,看看设置到那个路径下是不是有日志文件了呢
查看日志文件的命令是
mysqlbinlog update.000001

218. MySQL日志文件详解 ?

 正确回答通过率:62.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

日志文件是MySQL数据库的重要组成部分。MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志,慢查询日志,等等。这些日志可以帮助我们定位mysqld内部发生的事件,数据库性能故障,记录数据的变更历史,用户恢复数据库等等。本文主要描述MySQL的各种日志文件。

MySQL日志文件分类

1.错误日志(Error Log)
2.二进制日志(Binary Log & Binary Log Index)
3.通用查询日志(query log)
4.慢查询日志(slow query log)
5.Innodb的在线 redo 日志(innodb redo log)
6.更新日志(update log)

错误日志

错误日志记录了MyQL Server运行过程中所有较为严重的警告和错误信息,以及MySQL
Server 每次启动和关闭的详细信息。在默认情况下,系统记录错误日志的功能是关闭的, 错误信息被输出到标准错误输出(stderr) ,如果要开启系统记录错误日志的功能,需要在启动时开启-log-error 选项。错误日志的默认存放位置在数据目录下,以hostname.err 命 名。但是可以使用命令:—log-error[=file_name],修改其存放目录和文件名。
为了方便维护需要, 有时候会希望将错误日志中的内容做备份并重新开始记录, 这候时 就可以利用 MySQL 的 FLUSH LOGS 命令来告诉 MySQL 备份旧日志文件并生成新的日志文件。 备份文件名以“.old”结尾。

二进制日志

二进制日志,也就是我们常说的 binlog,也是 MySQL Server 中最为重要的日志之一。
当我们通过“—log-bin[=file_name]”打开了记录的功能之后,MySQL 会将所有修改数据 库数据的 query 以二进制形式记录到日志文件中。 当然, 日志中并不仅限于query 语句这么 简单, 还包括每一条query 所执行的时间, 所消耗的资源, 以及相关的事务信息,bi所nl以og 是事务安全的。
和错误日志一样,binlog 记录功能同样需要“—log-bin[=file_name]”参数的显式指 定才能开启, 如果未指定file_name, 则会在数据目录下记录为mysql-bin.** (*代表0~ 9 之间的某一个数字,来表示该日志的序号)。
binlog 还有其他一些附加选项参数:
“—max_binlog_size”设置 binlog 的最大存储上限,当日志达到该上限时,MySQL 会 重新创建一个日志开始继续记录。不过偶尔也有超出该设置的binlog 产生,一般都是因为 在即将达到上限时,产生了一个较大的事务,为了保证事务安全,MySQL 不会将同一个事务 分开记录到两个 binlog 中。
“—binlog-do-db=db_name”参数明确告诉 MySQL,需要对某个(db_name)数据库记 录 binlog,如果有了“—binlog-do-db=db_name”参数的显式指定,MySQL 会忽略针对其他 数据库执行的 query,而仅仅记录针对指定数据库执行的query。
“—binlog-ignore-db=db_name”与“—binlog-do-db=db_name”完全相反, 它显式指 定忽略某个(db_name)数据库的binlog 记录,当指定了这个参数之后,MySQL 会记录指定 数据库以外所有的数据库的 binlog。
“—binlog-ignore-db=db_name”与“—binlog-do-db=db_name”两个参数有一个共同 的概念需要大家理解清楚,参数中的db_name 不是指 query 语句更新的数据所在的数据库, 而是执行 query 的时候当前所处的数据库。 不论更新哪个数据库的数据,MySQL 仅仅比较当 前连接所处的数据库(通过use db_name切换后所在的数据库)与参数设置的数据库名,而 不会分析 query 语句所更新数据所在的数据库。
mysql-bin.index 文件(binary log index)的功能是记录所有Binary Log的绝对路 径,保证 MySQL 各种线程能够顺利的根据它找到所有需要的Binary Log 文件。

通用查询日志

查询日志记录 MySQL 中所有的 query,通过“—log[=fina_name]”来打开该功能。由
于记录了所有的 query,包括所有的 select,体积比较大,开启后对性能也有较大的影响, 所以请大家慎用该功能。 一般只用于跟踪某些特殊的sql 性能问题才会短暂打开该功能。默认的查询日志文件名为 hostname.log。

慢查询日志

顾名思义,慢查询日志中记录的是执行时间较长的 query,也就是我们常说的 slow
query,通过设 —log-slow-queries[=file_name]来打开该功能并设置记录位置和文件名, 默认文件名为 hostname-slow.log,默认目录也是数据目录。
慢查询日志采用的是简单的文本格式, 可以通过各种文本编辑器查看其中的内容。中其 记录了语句执行的时刻,执行所消耗的时间,执行用户,连接主机等相关信息。MySQL 还提 供了专门用来分析满查询日志的工具程序mysqlslowdump, 用来帮助数据库管理人员解决可 能存在的性能问题。

Innodb的在线redo日志

Innodb 是一个事务安全的存储引擎, 其事务安全性主要就是通过在线redo 日志和记录
在表空间中的 undo 信息来保证的。redo 日志中记录了 Innodb 所做的所有物理变更和事务 信息, 通过redo 日志和 undo 信息, Innodb 保证了在任何情况下的事务安全性。Innodb 的redo 日志同样默认存放在数据目录下, 可以通过innodb_log_group_home_dir来更改设置日志的 存放位置,通过 innodb_log_files_in_group 设置日志的数量。

更新日志

更新日志是 MySQL 在较老的版本上使用的,其功能和 binlog 基本类似,只不过不是以
二进制格式来记录而是以简单的文本格式记录内容。自从 MySQL增加了binlog功能之后, 就很少使用更新日志了。从版本5.0 开始,MySQL 已经不再支持更新日志了。

219. 简述 mysqldump 以及 xtranbackup 的实现原理 ?

  正确回答通过率:78.0%

[ 详情 ] 推荐指数: ★★★★ 试题难度: 中级

原理:
mysqldump
mysqldump 属于逻辑备份。加入–single-transaction 选项可以进行一致性备份。后台进程会先设置 session 的事务隔离级别为 RR(SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ),之后显式开启一个事务(START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */),这样就保证了该事务里读到的数据都是事务事务时候的快照。之后再把表的数据读取出来。如果加上–master-data=1 的话,在刚开始的时候还会加一个数据库的读锁(FLUSH TABLES WITH READ LOCK),等开启事务后,再记录下数据库此时 binlog 的位置(show master status),马上解锁,再读取表的数据。等所有的数据都已经导完,就可以结束事务。

Xtrabackup:
xtrabackup 属于物理备份,直接拷贝表空间文件,同时不断扫描产生的 redo 日志并保存下来。最后完成 innodb 的备份后,会做一个 flush engine logs 的操作(老版本在有 bug,在5.6 上不做此操作会丢数据),确保所有的 redo log 都已经落盘(涉及到事务的两阶段提交概念,因为 xtrabackup 并不拷贝 binlog,所以必须保证所有的 redo log 都落盘,否则可能会丢最后一组提交事务的数据)。这个时间点就是 innodb 完成备份的时间点,数据文件虽然不是一致性的,但是有这段时间的 redo 就可以让数据文件达到一致性(恢复的时候做的事情)。然后还需要 flush tables with read lock,把 myisam 等其他引擎的表给备份出来,备份完后解锁。这样就做到了完美的热备。

备份计划:
视库的大小来定,一般来说 100G 内的库,可以考虑使用 mysqldump 来做,因为 mysqldump更加轻巧灵活,备份时间选在业务低峰期,可以每天进行都进行全量备份(mysqldump 备份出来的文件比较小,压缩之后更小)。
100G 以上的库,可以考虑用 xtranbackup 来做,备份速度明显要比 mysqldump 要快。一般是选择一周一个全备,其余每天进行增量备份,备份时间为业务低峰期。

备份恢复时间:
物理备份恢复快,逻辑备份恢复慢
备份恢复失败如何处理:
首先在恢复之前就应该做足准备工作,避免恢复的时候出错。比如说备份之后的有效性检查、
权限检查、空间检查等。如果万一报错,再根据报错的提示来进行相应的调整。

220. 简述MySQL innodb 的读写参数优化 ?

  正确回答通过率:35.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

(1)读取参数,global buffer pool 以及 local buffer
(2)写入参数
(3)与 IO 相关的参数
(4)缓存参数以及缓存的适用场景
(1)读取参数,global buffer pool 以及 local buffer

Global buffer:
Innodb_buffer_pool_size
innodb_log_buffer_size
innodb_additional_mem_pool_size
local buffer(下面的都是 server 层的 session 变量,不是 innodb 的):
Read_buffer_size
Join_buffer_size
Sort_buffer_size
Key_buffer_size
Binlog_cache_size

(2)写入参数
insert_buffer_size
资源由 www.eimhe.com 美河学习在线收集提供
innodb_double_write
innodb_write_io_thread
innodb_flush_method

(3)与 IO 相关的参数
Sync_binlog
Innodb_flush_log_at_trx_commit
Innodb_lru_scan_depth
Innodb_io_capacity
Innodb_io_capacity_max
innodb_log_buffer_size
innodb_max_dirty_pages_pct

(4)缓存参数以及缓存的适用场景
指的是查询缓存吗???使用于读多写少,如分析报表等等
query_cache_size
query_cache_type
query_cache_limit
maximumquery_cache_size

221. 简述遇到Mysql死锁问题,我们应该怎么排查分析呢 ?

 正确回答通过率:60.0%

[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难

#前言
遇到Mysql死锁问题,我们应该怎么排查分析呢?之前线上出现一个insert on duplicate死锁问题,本文将基于这个死锁问题,分享排查分析过程,希望对大家有帮助。
##死锁案发还原
表结构:

CREATE TABLE `song_rank` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`songId` int(11) NOT NULL,
`weight` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `songId_idx` (`songId`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

隔离级别:

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)

数据库版本:

+------------+
| @@version |
+------------+
| 5.7.21-log |
+------------+
1 row in set (0.00 sec)

关闭自动提交:

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)

表中的数据:

mysql> select * from song_rank;
+----+--------+--------+
| id | songId | weight |
+----+--------+--------+
| 1 | 10 | 30 |
| 2 | 20 | 30 |
+----+--------+--------+
2 rows in set (0.01 sec)

死锁案发原因:
并发环境下,执行insert into … on duplicate key update…导致死锁
死锁模拟复现:
事务一执行:

mysql> begin;
//第一步
Query OK, 0 rows affected (0.00 sec)
mysql> insert into song_rank(songId,weight) values(15,100) on duplicate key update weight=weight+1;
//第二步
Query OK, 1 row affected (0.00 sec)
mysql> rollback;
//第七步
Query OK, 0 rows affected (0.00 sec)

事务二执行:

mysql> begin;
//第三步
Query OK, 0 rows affected (0.00 sec)
mysql> insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1;
// 第四步
Query OK, 1 row affected (40.83 sec)

事务三执行:

mysql> begin;
//第五步
Query OK, 0 rows affected (0.00 sec)
mysql> insert into song_rank(songId,weight) values(18,100) on duplicate key update weight=weight+1;
//第六步

事务一,事务二,事务三执行:

步骤事务一事务二事务三
第一步begin;
第二步insert into song_rank(songId,weight) values(15,100) on duplicate key update weight=weight+1;
(Query OK, 1 row affected (0.00 sec) )
第三步begin;
第四步insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1;
//被阻塞
第五步begin;
第六步insert into song_rank(songId,weight) values(18,100) on duplicate key update weight=weight+1;
//被阻塞
第七步rollback;
结果Query OK, 1 row affected (40.83 sec)ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
死锁浮出水面:
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

##死锁破案排查分析
遇到死锁问题时,我们应该怎么处理呢?分一下几个步骤
###1.查看死锁日志
当数据库发生死锁时,可以通过以下命令获取死锁日志:

show engine innodb status;

上面例子insert on duplicate死锁问题的日志如下:

*** (1) TRANSACTION:
TRANSACTION 27540, ACTIVE 19 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 23, OS thread handle 14896, query id 582 localhost ::1 root update
insert into song_rank(songId,weight) values(18,100) on duplicate key update weight=weight+1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 116 page no 4 n bits 72 index songId_idx of table `test2`.`song_rank` trx id 27540 lock_mode X
locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2;
compact format;
info bits 0
0: len 4;
hex 80000014;
asc ;
;
1: len 4;
hex 80000002;
asc ;
;
*** (2) TRANSACTION:
TRANSACTION 27539, ACTIVE 41 sec inserting, thread declared inside InnoDB 1
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1
MySQL thread id 22, OS thread handle 6976, query id 580 localhost ::1 root update
insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 116 page no 4 n bits 72 index songId_idx of table `test2`.`song_rank` trx id 27539 lock_mode X
locks gap before rec
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2;
compact format;
info bits 0
0: len 4;
hex 80000014;
asc ;
;
1: len 4;
hex 80000002;
asc ;
;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 116 page no 4 n bits 72 index songId_idx of table `test2`.`song_rank` trx id 27539 lock_mode X
locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2;
compact format;
info bits 0
0: len 4;
hex 80000014;
asc ;
;
1: len 4;
hex 80000002;
asc ;
;

###2.分析死锁日志
如何分析死锁日志呢? 分享一下我的思路

  • 死锁日志分事务1,事务2拆分
  • 找出发生死锁的SQL
  • 找出事务持有什么锁,都在等待什么锁
  • SQL加锁分析
    ####事务1日志分析
    从日志我们可以看到事务1正在执行的SQL为:
insert into song_rank(songId,weight) values(18,100) on duplicate key update weight=weight+1

该条语句正在等待索引songId_idx的插入意向排他锁:

lock_mode X locks gap before rec insert intention waiting

####事务2日志分析
从日志我们可以看到事务2正在执行的SQL为:

insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1

该语句持有一个索引songId_idx的间隙锁:

lock_mode X locks gap before rec

该条语句正在等待索引songId_idx的插入意向排他锁:

lock_mode X locks gap before rec insert intention waiting

####锁相关概念补充(附):
考虑到有些读者可能对上面insert intention锁等不太熟悉,所以这里这里补一小节锁相关概念。
InnoDB 锁类型思维导图:
我们主要介绍一下兼容性以及锁模式类型的锁
1.共享锁与排他锁:
InnoDB 实现了标准的行级锁,包括两种:共享锁(简称 s 锁)、排它锁(简称 x 锁)。

  • 共享锁(S锁):允许持锁事务读取一行。
  • 排他锁(X锁):允许持锁事务更新或者删除一行。
    如果事务 T1 持有行 r 的 s 锁,那么另一个事务 T2 请求 r 的锁时,会做如下处理:
  • T2 请求 s 锁立即被允许,结果 T1 T2 都持有 r 行的 s 锁
  • T2 请求 x 锁不能被立即允许
    如果 T1 持有 r 的 x 锁,那么 T2 请求 r 的 x、s 锁都不能被立即允许,T2 必须等待T1释放 x 锁才可以,因为X锁与任何的锁都不兼容。
    2.意向锁
  • 意向共享锁( IS 锁):事务想要获得一张表中某几行的共享锁
  • 意向排他锁( IX 锁): 事务想要获得一张表中某几行的排他锁
    比如:事务1在表1上加了S锁后,事务2想要更改某行记录,需要添加IX锁,由于不兼容,所以需要等待S锁释放;如果事务1在表1上加了IS锁,事务2添加的IX锁与IS锁兼容,就可以操作,这就实现了更细粒度的加锁。
    InnoDB存储引擎中锁的兼容性如下表:
    兼容性 | IS | IX| S | X
    -----| -----|----- |----- |-----
    IS | 兼容 | 兼容 | 兼容| 不兼容|
    IX | 兼容| 兼容 | 不兼容 | 不兼容|
    S | 兼容|不兼容|兼容 | 不兼容|
    X | 不兼容| 不兼容 | 不兼容 | 不兼容|
    3.记录锁(Record Locks)
  • 记录锁是最简单的行锁,仅仅锁住一行。如:SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE
  • 记录锁永远都是加在索引上的,即使一个表没有索引,InnoDB也会隐式的创建一个索引,并使用这个索引实施记录锁。
  • 会阻塞其他事务对其插入、更新、删除
    记录锁的事务数据(关键词:lock_mode X locks rec but not gap),记录如下:
RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t`
trx id 10078 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3;
compact format;
info bits 0
0: len 4;
hex 8000000a;
asc ;
;
1: len 6;
hex 00000000274f;
asc 'O;;
2: len 7; hex b60000019d0110; asc ;;

4.间隙锁(Gap Locks)

  • 间隙锁是一种加在两个索引之间的锁,或者加在第一个索引之前,或最后一个索引之后的间隙。
  • 使用间隙锁锁住的是一个区间,而不仅仅是这个区间中的每一条数据。
  • 间隙锁只阻止其他事务插入到间隙中,他们不阻止其他事务在同一个间隙上获得间隙锁,所以 gap x lock 和 gap s lock 有相同的作用。
    5.Next-Key Locks
  • Next-key锁是记录锁和间隙锁的组合,它指的是加在某条记录以及这条记录前面间隙上的锁。
    6.插入意向锁(Insert Intention)
  • 插入意向锁是在插入一行记录操作之前设置的一种间隙锁,这个锁释放了一种插入方式的信号,亦即多个事务在相同的索引间隙插入时如果不是插入间隙中相同的位置就不需要互相等待。
  • 假设有索引值4、7,几个不同的事务准备插入5、6,每个锁都在获得插入行的独占锁之前用插入意向锁各自锁住了4、7之间的间隙,但是不阻塞对方因为插入行不冲突。
    事务数据类似于下面:
RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`
trx id 8731 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 80000066; asc f;;
1: len 6; hex 000000002215; asc " ;;
2: len 7; hex 9000000172011c; asc r ;;...

####SQL加锁分析:
通过分析死锁日志,我们可以找到发生死锁的SQL,以及相关等待的锁,我们再对对应的SQL进行加锁分析,其实问题就迎刃而解了。
OK,我们回到对应的SQL,insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1 执行过程到底加了什么锁呢?加锁机制官方文档
insert加锁策略:
insert语句会对插入的这条记录加排他记录锁,在加记录锁之前还会加一种 GAP 锁,叫做插入意向(insert intention)锁,如果出现唯一键冲突,还会加一个共享记录(S)锁。
(SQL加锁分析非常重要,在这里给大家推荐一篇文章,讲的非常好,解决死锁之路 - 常见 SQL 语句的加锁分析)
insert on duplicate key加锁验证
为了验证一下insert on duplicate key加锁情况,我们拿上面demo的事务1和2在走一下流程。
事务1:

mysql> begin; //第一步
Query OK, 0 rows affected (0.00 sec)
mysql> insert into song_rank(songId,weight) values(15,100) on duplicate key
update weight=weight+1; //第二步
Query OK, 1 row affected (0.00 sec)

事务2(另开窗口):

mysql> begin; //第三步
Query OK, 0 rows affected (0.00 sec)
mysql> insert into song_rank(songId,weight) values(16,100) on duplicate key
update weight=weight+1; // 第四步

使用show engine innodb status查看当前锁请求信息,如图:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
有图可得:
事务2持有:IX锁(表锁),gap x锁,insert intention lock(在等待事务1的gap锁)
所以,insert on duplicate 执行过程会上这三把锁。
####死锁原因分析
回归到本文开头介绍的死锁案发模拟现场(事务1,2,3)以及死锁日志现场,
案发后事务1的锁:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
案发后事务2的锁:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
案发复原路线:
1.首先,执行事务1执行:
begin;
insert into song_rank(songId,weight) values(15,100) on duplicate key update weight=weight+1;
会获得 gap锁(10,20),insert intention lock(插入意向锁)
2.接着,事务2执行:
begin;
insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1;
会获得 gap锁(10,20),同时等待事务1的insert intention lock(插入意向锁)。
3.再然后,事务3执行:
begin;
insert into song_rank(songId,weight) values(18,100) on duplicate key update weight=weight+1;
会获得 gap锁(10,20),同时等待事务1的insert intention lock(插入意向锁)。
4.最后,事务1回滚(rollback),释放插入意向锁,导致事务2,3同时持有gap锁,等待insert intention锁,死锁形成
锁模式兼容矩阵(横向是已持有锁,纵向是正在请求的锁):

兼容性GapInsert IntentionRecordNext-Key
Gap兼容兼容兼容兼容
Insert Intention冲突兼容兼容冲突
Record兼容兼容冲突冲突
Next-Key兼容兼容冲突冲突
这是MySql5.7的一个bug
##如何避免该insert on duplicate死锁问题
###1.把insert on duplicate改为insert
try{
insert();
}catch(DuplicateKeyException e){
update();
}

因为insert不会加gap锁,所以可以避免该问题。
###2.更改MySql版本
既然这是MySql5.7的一个bug,那么可以考虑更改Mysql版本。
###3.尽量减少使用unique index。
gap锁跟索引有关,并且unique key 和foreign key会引起额外的index检查,需要更大的开销,所以我们尽量减少使用不必要的索引。
##本文总结(重要)
本文介绍了MySql5.7死锁的一个bug。我们应该怎样去排查死锁问题呢?

  • 1.show engine innodb status;查看死锁日志
  • 2.找出死锁SQL
  • 3.SQL加锁分析
  • 4.分析死锁日志(持有什么锁,等待什么锁)
  • 5.熟悉锁模式兼容矩阵,InnoDB存储引擎中锁的兼容性矩阵。
;