标签 mysql 下的文章

我们经常看到Mysql的explain语句执行结果Extra字段有using temporary、using filesort,理解这两个短语的含义,有助于进行SQL语句的优化。
什么是临时表(temporary table)
顾名思义,临时表也是一张表,只不过不是持久的,当会话结束,临时表就会被删除掉。

什么是文件排序(filesort)
文件排序是相对于索引排序而言的,当不能使用索引生成排序结果的时候,mysql需要进行文件排序,排序可能是在内存中进行的,也可能需要磁盘文件的辅助。当待排序的数据量小于排序缓冲区(sort buffer)的大小时,排序直接在内存中进行,否则就需要磁盘文件的辅助进行排序,无论是哪种情况,mysql并没有进行区分,统一使用filesort来表示。

mysql的关联查询是如何执行的
mysql对所有的关联查询都是通过循环嵌套来执行的。简单的讲,表1位于外层循环,表2位于内层循环,每次首先从外层循环中取出一条数据,然后在内存循环中进行匹配,匹配到的作为结果进行返回。下面的语句及其伪代码表示了实际的执行过程。

关联查询order by执行的两种情况
关联查询中如果有order by排序语句,排序的过程会分为两种情况。
第一种,order by语句中排序的列全部都出现在表1中,那么mysql在关联处理第一个表时就会进行文件排序,也就是在执行关联查询的外层循环时就进行排序,此时,mysql的explain结果中可以看到extra字段会看到using filesort.
第二种,除了第一种情况之外,mysql都会先将关联查询的结果存放到一张临时表中,然后在所有的关联都结束后,再进行文件排序,此时mysql的explain语句的extra字段就会看到using temporary;using filesort.

一 删除非管理员账号,配置业务账号,合理分配业务账号权限,一般除了增删改查建表删表改表,其它权限一律不给
二 修改默认的mysql管理员帐号root为其它名字
三 使用独立系统用户运行msyql程序,不要使用ROOT用户来运行
四 禁止未授权的远程连接数据库,远程账号禁止使用username@'%'
五 系统目录权限,mysql安装根目录属root用户,存放数据的data目录属mysql用户,必须保证该目录不能让未经授权的用户访问后把数据库打包拷贝走了
六 禁止MySQL对本地文件存取

mysql中,提供对本地文件的读取,使用的是load data local infile命令,默认在5.0版本中,该选项是默认打开的,该操作令会利用MySQL把本地文件读到数据库中,然后用户就可以非法获取敏感信息了,假如你不需要读取本地文件,请务必关闭。

测试:首先在测试数据库下建立sqlfile.txt文件,用逗号隔开各个字段

# vi sqlfile.txt
1,sszng,111
2,sman,222
#mysql> load data local infile 'sqlfile.txt' into table users fields terminated by ','; //读入数据
#mysql> select * from users;
+--------+------------+----------+
| userid  | username   | password |
+--------+------------+----------+
|      1 | sszng    | 111   |
|      2 | sman    | 222  |
+--------+------------+----------+

成功的将本地数据插入数据中,此时应该禁止MySQL中用“LOAD DATA LOCAL INFILE”命令。网络上流传的一些攻击方法中就有用它LOAD DATA LOCAL INFILE的,同时它也是很多新发现的SQL Injection攻击利用的手段!黑客还能通过使用LOAD DATALOCAL INFILE装载“/etc/passwd”进一个数据库表,然后能用SELECT显示它,这个操作对服务器的安全来说,是致命的。可以在my.cnf中添加local-infile=0,或者加参数local-infile=0启动mysql。

七 Mysqld安全相关启动选项

下列mysqld选项影响安全:

   --allow-suspicious-udfs
该选项控制是否可以载入主函数只有xxx符的用户定义函数。默认情况下,该选项被关闭,并且只能载入至少有辅助符的UDF。这样可以防止从未包含合法UDF的共享对象文件载入函数。
    --local-infile[={0|1}]
如果用–local-infile=0启动服务器,则客户端不能使用LOCAL in LOAD DATA语句。
    --old-passwords
强制服务器为新密码生成短(pre-4.1)密码哈希。当服务器必须支持旧版本客户端程序时,为了保证兼容性这很有用。
     (OBSOLETE) --safe-show-database
在以前版本的MySQL中,该选项使SHOW DATABASES语句只显示用户具有部分权限的数据库名。在MySQL 5.1中,该选项不再作为现在的 默认行为使用,有一个SHOW DATABASES权限可以用来控制每个账户对数据库名的访问。
    --safe-user-create
如果启用,用户不能用GRANT语句创建新用户,除非用户有mysql.user表的INSERT权限。如果你想让用户具有授权权限来创建新用户,你应给用户授予下面的权限:
mysql> GRANT INSERT(user) ON mysql.user TO ‘user_name’@’host_name’;
这样确保用户不能直接更改权限列,必须使用GRANT语句给其它用户授予该权限。
    --secure-auth
不允许鉴定有旧(pre-4.1)密码的账户。
    --skip-grant-tables
这个选项导致服务器根本不使用权限系统。这给每个人以完全访问所有的数据库的权力!(通过执行mysqladmin flush-privileges或mysqladmin eload命令,或执行FLUSH PRIVILEGES语句,你能告诉一个正在运行的服务器再次开始使用授权表。)
    --skip-name-resolve
主机名不被解析。所有在授权表的Host的列值必须是IP号或localhost。
    --skip-networking
在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进行。
    --skip-show-database
使用该选项,只允许有SHOW DATABASES权限的用户执行SHOW DATABASES语句,该语句显示所有数据库名。不使用该选项,允许所有用户执行SHOW DATABASES,但只显示用户有SHOW DATABASES权限或部分数据库权限的数据库名。请注意全局权限指数据库的权限。

八 确保数据文件在非系统分区:操作系统上有明确的系统分区和非系统分区。如果数据文件在系统分区,会提高整个系统因为磁盘空间用尽发生拒绝服务的几率。

1)进入数据库执行下列语句

show variables where variable_name = 'datadir'

如果发现结果中存在/ /var /usr 说明数据文件在系统分区建议换区

九 禁止 mysql 链接历史记录:
mysql 会把客户端登陆的交互执行记录保存在.mysql_history 文件中,该记录有可能会暴露登陆过程中的敏感信息,建议删除,检查.mysql_history 文件是否存在(默认在home 下)执行命令 find /home -name ".mysql_history"如果有返回行说明存在建议删除

十 禁止 MYSQL_PWD 的使用:
MYSQL_PWD 是一种用于明文形式存储 mysql 密码的环境变量,检查 MYSQL_PWD 环境变量是否存在于某个进程中执行命令

grep MYSQL_PWD /proc/*/environ

如果有返回行说明那个进程使用了 MYSQL_PWD 环境变量

十一 禁止 MYSQL 操作系统账号登陆:
Mysql 的操作做系统账号在安装完数据库后,不应该有其他用途,建议禁止该账号登陆操作系统,假设 mysql 数据库操作系统账号就是 Mysql 执行下列命令

getent passwd mysql | egrep "^.*[ \ /bin\ / false| \ / sbin \ / nologin]$"

如果没有返回行则说明存在安全隐患。

十二 禁止 MYSQL 使用默认端口:
如果返回是 3306,则说明需要修改端口;执行 sql 确认端口

show global variables like 'port';

二、文件系统权限安全配置

1、确保数据文件最小权限:
执行 sql 定位数据文件地址

show variables where variable_name = 'datadir';

检查路径权限是否符合最小权限原则

ls -l /.. | egrep "^d[r|w|x]{3}------\s*.\s*mysql\s*mysql\s*\d*.*mysql"

2、确保 log_bin_basename 文件最小权限:
执行 sql 定位日志文件地址 show variables like 'log_bin_basename';日志文件的权限是 660 属于 mysql

3、确保 log_error 文件最小权限:
执行 sql 定位日志文件地址

show global variables like 'log_error';

4、 确保 slow_query_log 文件最小权限:

执行 sql 定位日志文件地址

show variables like 'slow_query_log_file';

5 、确保 relay_log_basename 文件最小权限:

执行 sql 定位日志文件地址

show variables like 'relay_log_basename';

6、 确保 general_log_file 文件最小权限:

执行 sql 定位日志文件地址

show variables like 'general_log_file';

7 、确保密钥文件最小权限:

1.执行 sql 定位密钥文件地址

show variables where variable_name = 'ssl_key';

2.检查路径权限是否符合最小权限原则

ls -l | egrep "^-r--------[ \t]*.[ \t]*mysql[ \t]*mysql.*$"

如果没有返回行,则说明存在安全问题

8 、确保插件目录最小权限:

1.执行 sql 定位插件目录地址

show variables where variable_name = 'plugin_dir';

2.检查路径权限是否符合最小权限原则

ls -l /.. | egrep "^drwxr[-w]xr[-w]x[ \t]*[0-9][ \t]*mysql[ \t]*mysql.*plugin.*$"

三、Mysql 基本安全配置

1、 确保使用最新版 mysql 数据库:

执行 sql 检查数据库版本

SHOW VARIABLES WHERE Variable_name LIKE "version";

2、修改 root 用户名:
检查数据库是否有默认用户 root,执行命令:SELECT user from mysql.user where user='root; 如果有返回行则需要修改;

3、确保样例数据库删除:
样例数据库可以被所有数据库用户访问,并且可以用来消耗系统资源删除样例库可以减少攻击面;
检查数据库是否存在样例库执行 sql命令

SHOW DATABASES LIKE 'test';

4、禁用 local_infile:
以阻止黑客利用 sql 注入来读取数据库文件,检查参数状态执行命令:

SHOW VARIABLES WHERE Variable_name = 'local_infile';

如果返回值不是 off,则存在安全问题

5、确保 skip-symbolic-links 开启:
开启 skip-symbolic-links 可以禁止数据库用户删除或重名数据文件目录之外的文件,检查参数状态执行命令:

SHOW variables LIKE 'have_symlink';

6、确保插件 daemon_memcached 被禁用:

任何人可以利用 daemon_memcached 来访问或修改一部分数据,给数据库造成信息泄漏的隐患。

检查参数状态执行命令:

SELECT * FROM information_schema.plugins WHERE PLUGIN_NAME='daemon_memcached';

如果有返回行数说明有插件,需要删除

7、确保 secure_file_priv 不是空:

secure_file_priv 限制客户端可以读取数据文件的路径,secure_file_priv设置合理的值可以有效降低 sql 注入后黑客读取数据库数据的可能性。

检查参数状态执行如下命令:

SHOW GLOBAL VARIABLES WHERE Variable_name ='secure_file_priv' AND Value<>'';

如果有返回内容说明安全,否则需要修复;

8、确保 sql_mode 是 STRICT_ALL_TABLES 模式:

sql_mode 模式有三种,STRICT_TRANS_TABLES 是其中一种模式。STRICT_TRANS_TABLES 模式会检查所有更新的数据
检查参数状态执行命令:

SHOW VARIABLES LIKE 'sql_mode';

如果有返回的是 STRICT_TRANS_TABLES 说明安全,否则需要修复;

9、确保 disconnect_on_expired_password 参数是 ON:

disconnect_on_expired_password 是用来控制客户端用失效密码来访问数据库的,关闭这个参数会给数据库带来安全风险。
检查参数状态执行命令:

SHOW GLOBAL VARIABLES like 'disconnect_on_expired_password';

如果有返回的是 ON 说明安全,否则需要修复

四、Mysql 权限安全配置

1 、确保只有管理员账号有所有数据库的访问权限:

执行命令:

SELECT user, host FROM mysql.user WHERE (Select_priv = 'Y') OR (Insert_priv = 'Y') OR (Update_priv = 'Y') OR (Delete_priv = 'Y') OR (Create_priv = 'Y') OR (Drop_priv = 'Y');

如果返回的都是管理员账号说明安全,否则需要对用户清除权限;

2、非管理员账号 file_priv 不应该设置成 Y

File_priv 权限允许 mysql 用户对磁盘进行读写操作,执行命令:

select user, host from mysql.user where File_priv = 'Y'; 如果返回的都是管理员账号,否则需要对用户清除权限;

3、非管理员账号 process_priv 不应该设置成 Y

process_priv 权限允许委托账号查看当前正在执行的 sql 语句,使用超越

当前用户权限的权利,可以被攻击者所利用。执行命令:

select user, host from mysql.user where Process_priv = 'Y'; 如果返回的都是管理员账号则是安全的,否则需要对用户清除权限;

(同上)非管理员账号 super_priv 不应该设置成 Y,非管理员账号 shutdown_priv 不应该设置成 Y,

非管理员账号 create_user_priv 不应该设置成 Y,非管理员账号 grant_priv 不应该设置成 Y,

非管理员账号 reload_priv 不应该设置成 Y,非管理员账号 repl_slave_priv 不应该设置成 Y;

4、确保 DML/DDL 权限只在特定用户手上:

执行sql命令:

SELECT User,Host,Db FROM mysql.db WHERE Select_priv='Y' OR Insert_priv='Y' OR Update_priv='Y' OR Delete_priv='Y' OR Create_priv='Y' OR Drop_priv='Y' OR Alter_priv='Y';

如果返回的都是管理员账号,否则需要对用户清除权限

五、审计和日志安全配置

1、 确保 log_error 日志启动:

启用错误日志有可能会增加检测到针对 mysql 的恶意攻击行为机会,执行命令:

SHOW variables LIKE 'log_error';

如果返回是空否,则存在安全问题需要修复

2、 确保日志文件在非系统分区:

操作系统上有明确的系统分区和非系统分区,如果日志文件在系统分区,会提高整个系统因为磁盘空间用尽发生拒绝服务的几率;进入数据库执行命令:

SELECT @@global.log_bin_basename;

3、确保 log_warnings 被设置成 2:

log_warnings 适用于决定日志中记录的内容的,默认是 1 随着级别的调整会记录更多信息,调整到 2 有助于通过日志追查安全问题;执行命令:

SHOW GLOBAL VARIABLES LIKE 'log_warnings';

六、身份认证安全配置

1、确保 sql_mode 中含有 NO_AUTO_CREATE_USER:

NO_AUTO_CREATE_USER 是 sql_mode 的一个选项,可以阻止 grant 语句在特定情况下自动创建用户;执行命令:

SELECT @@session.sql_mode;

2、确保没有用户使用空密码

如果密码被设置成空密码,入侵者只要知道密码和主机允许列表,就可以绕

过身份验证随意登录数据库;执行命令:

SELECT User,host FROM mysql.user WHERE authentication_string=''; 

没有行数返回说明安全,否则需要配置;

3、确保 default_password_lifetimes 少于或等于 90 天

密码需要定期更换,才有意义,也才能更有效的防止黑客破解;执行命令:

SHOW VARIABLES LIKE 'default_password_lifetime';

看返回值和 90 的关系如果大于 90 就需要修复

4、 确保用户不允许所有 ip 访问

某一数据库用户支持所有 ip 访问,一旦账号密码泄露,数据库就变得很不安全,执行命令:

SELECT user, host FROM mysql.user WHERE host = '%';

结果集为空说明不存在问题,否则需要修复

5、确保无匿名帐户存在

匿名用户是空的,也没有密码,安全性很差,任意人员都可以利用匿名用户

访问数据库,执行命令:

SELECT user,host FROM mysql.user WHERE user = '';

结果集为空说明不存在问题,否则需要修复;

七、网络安全配置

1、确保 have_ssl 设置成 yes:

所有网络请求必须走 SSL/TLS 访问数据库,执行命令:

SHOW variables WHERE variable_name = 'have_ssl';

返回 yes 不存在问题,否则需要修复;

2 、确保 ssl_type 是 'ANY', 'X509', or 'SPECIFIED':

所有网络请求必须走 SSL/TLS 访问数据库。SSL 提供多种算法,其中一些算法安全性并不高不能帮助用户杜绝网络劫持和网络拦截。建议设置 ssl_type 为高安全类型的加密算法。但这其中有一个隐患,如果客户端使用较低加密算法,会由于算法无法匹配导致链接失败,执行命令:

SELECT user, host, ssl_type FROM mysql.user WHERE NOT HOST IN ('::1', '127.0.0.1', 'localhost');

确保每个用户返回的 ssl_type 等于 ANY, X509, or SPECIFIED;

八、复制数据传输中的安全配置

1 、确保 MASTER_SSL_VERIFY_SERVER_CERT 设置成 yes 或 1:

2、确保 master_info_repository 设置成 table:

master_info_repository 设置成 table.客户端使用的密码存储在表中,相较于文件系

统表中更为安全执行命令:

SHOW GLOBAL VARIABLES LIKE 'master_info_repository';

master_info_repository 返回是 table,否则需要修复,修复建议:打开配置文件

set the master_info_repository value to TABLE;

扩展资料:

secure-file-priv特性
secure-file-priv参数是用来限制LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE()传到哪个指定目录的。

show variables like '%secure%';

如果secure_file_priv如果非空,则只能在对应的目录下读文件,如果是空即可在其他目录写。Linux下默认/tmp目录可写。

当secure_file_priv的值为null ,表示限制mysql 不允许导入|导出
当secure_file_priv的值为/tmp/ ,表示限制mysql 的导入|导出只能发生在/tmp/目录下
当secure_file_priv的值没有具体值时,表示不对mysql 的导入|导出做限制
可以在mysql-ini文件中设置其属性
攻击者可以,编写一句phpinfo文件,例子是windows服务器,这里必须注意要双反斜线,否则会转义

select "<?php phpinfo();?>" INTO OUTFILE  "d:\\phpstudy\\www\\7.php"

最近数据库服务器多事之秋,莫名的批量宕机事件一再发生,搞得压力超大。厂商来了之后也酥手无策。上周路过寺庙,平生第一次感叹道是否要去烧烧香,拜托拜托数据库之神能让我们团队早日度过这个劫难。

上周和William聊到MySQL的参数sql_slave_skip_counter,感叹很多人并没有真正了解这个参数的含义。面试时这是一个很好的问题,相信即使是淘宝P7的level,要准确答对这个问题也是需要平时的细心累积。

01

很多同学的误区在于会把参sql_slave_skip_counter=N理解成跳过N个事务。如果这样的回答,至少在我心中已经扣分不少,要拿高P几乎不可能。首先看看文档中的定义:

SET GLOBAL sql_slave_skip_counter = N

This statement skips the next N events from the master. This is useful for recovering from replication stops caused by a statement.

官方文档中明确指出N表示的是N个event。很多同学把这个参数的单位理解成事务的原因在于他把操作都理解成了由单条语句所组成的事务。这时N的含义两者等价。

然而,更常见的场景却是一个事务可能由多个EVENT组成,例如一个事务可以有多个SQL组成,例如:

BEGIN; INSERT ...;DELETE ...; INSERT; COMMIT;

若这时将N理解成事务,那么结果就会非常不同。当然,答对参数sql_slave_skip_counter的单位是事务,这个答案也仅只有60分。

02

如果细看文档的话,文档最后一段还说道:

When you use SET GLOBAL sql_slave_skip_counter to skip events and the results in the middle of a group, the slave continues to skip events until it reaches the end of the group. Execution then starts with the next event group.

这句非常关键,也就是说可能上面的答案是:以上全错。N可以不表示跳过N个事务,甚至可能是跳过>=N个事务的场景。假设开始时主、从的数据分别为:

Master

Slave
a
1
2
3

+----+ +----+

a
1
3

由于主从数据已然不一致,这时若在主上执行下面的SQL:

BEGIN;

INSERT INTO Z SELECT 4;

DELETE FROM Z WHERE a = 2;

INSERT INTO Z SELECT 5;

COMMIT;

从机显然会报错,提示1032错误,因为记录2这条记录并没有找到。这时的处理方法很多DBA会选择执行SET GLOBAL sql_slave_skip_counter=1。然而,这样的处理会导致INSERT 5这条记录不被执行。因为跳过DELETE 2这个操作后,事务没有结束,会继续跳过接下去的event,这就是文档中说的:the slave continues to skip events until it reaches the end of the group。感兴趣的同学可以自行测试看看最终的结果。

若只想跳过一个EVENT该怎么做呢?其实,只需将参slave_exec_mode设置为IDEMPOTENT即可。

03

出现主从复制出错,最安全的方法还是重建从机。另外,MySQL的复制早就是crash safe的复制机制了。若你的复制环境经常出错,应该好好检查下数据库的配置参数。

对于参数sql_skip_slave_counter来说,这只是一个不得已为之的方法。同时,当开启GTID模式时,也无法通过参数进行跳过出错的EVENT。

原文:https://mp.weixin.qq.com/s/rZZbLmN0Klq0o0bvnijizw

https://www.skyfinder.cc/2020/01/12/database-navicat-premium15/

官网下载主程序
http://download.navicat.com.cn/download/navicat150_premium_cs_x64.exe
下载补丁程序
https://www.skyfinder.cc/wp-content/uploads/2020/01/Navicat-Keygen-Patch-v5.6.0-DFoX.zip
解压密码:www.skyfinder.cc

使用方法
卸载掉早期版本,卸载干净,然后安装最新版navicat

  • 安装Navicat Premium 15
  • 将补丁复制到安装目录下并运行补丁点击patch,注意此时不要打开Navicat Premium 15
  • 运行navicat并弹出注册界面
  • 如果没有弹出注册界面手动在菜单打开:帮助->注册
  • 点击 补丁程序的generate按钮同时注册码会自动写到navicat
  • 点击navicat注册界面的激活按钮,提示手动激活
  • 点击手动激活之后将得到的RequestCode复制到注册机
  • 点击补丁程序左下方的Generate按钮,生成ActivationCode
  • 复制粘贴到navicat的激活码框并完成激活