2019-03-10 常用管理SQL语句应用实践(2)

SQL语句实践

1. DDL语句之管理数据库

DDL的特点是对数据库内部的对象进行创建、修改、删除等操作,不涉及对表中内容的操作和更改。

1、创建数据库

1)建立一个名为oldboy的数据库

mysql> create database oldboy;    ---创建名为oldboy的数据库
Query OK, 1 row affected (0.04 sec)    ---Ouery OK表示执行成功,1 row affected表示影响了1行,0.04 sec表示执行的时间
mysql> show databases;    ---查看所有的数据库
+--------------------+
| Database           |
+--------------------+
| information_schema |    ---此表为系统表,存储数据库内置对象信息,如用户,权限等
| mysql              |    ---此表为系统表,存储用户授权和权限相关的信息,授权时会用到
| oldboy             |    ---这里就是刚才创建的数据库
| performance_schema |    ---这是MySQL第二条产品线增加的系统表,存储与性能相关的表数据
+--------------------+
4 rows in set (0.06 sec)
mysql> 

查看刚刚创建的oldboy库对应的SQL语句

mysql> show create database oldboy\G    ---\G是为了调整显示的格式
*************************** 1. row ***************************
       Database: oldboy
Create Database: CREATE DATABASE `oldboy` /*!40100 DEFAULT CHARACTER SET utf8 */
1 row in set (0.00 sec)
---当不指定字符集建库时,库的字符集默认和编译时指定的字符集一致

2)建立一个GBK字符集数据库,名为oldboy_gbk,并查看建库语句

mysql> create database oldboy_gbk CHARACTER SET gbk COLLATE gbk_chinese_ci;
Query OK, 1 row affected (0.08 sec)
mysql> show create database oldboy_gbk\G
*************************** 1. row ***************************
       Database: oldboy_gbk
Create Database: CREATE DATABASE `oldboy_gbk` /*!40100 DEFAULT CHARACTER SET gbk */
1 row in set (0.00 sec)

3)创建不同字符集格式的数据库命令集合

create database oldboy;    ---默认数据库的字符集设置配置
create database oldboy_gbk DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;    ---创建gbk字符集数据库
create database oldboy_utf8 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;    ---创建utf8字符集数据库

提示:字符集的不一致是数据库里中文内容出现乱码的罪魁祸首,查看字符集及校对规则名字(指定字符集建库结尾的语句,例如SET gbk COLLATE gbk_chinese_ci)的方法为"mysql>SHOW CHARACTER SET;"
如果编译的时候指定了特定的字符集,则以后创建对应字符集的数据库时就不需要指定字符集了

cmake . -DCMAKE_INSTALL_PREFIX=/application/mysql-5.6.41 \
-DMYSQL_DATADIR=/application/mysql-5.6.41/data \
-DMYSQL_UNIX_ADDR=/application/mysql-5.6.41/tmp/mysql.sock \
-DDEFAULT_CHARSET=utf8 \    ---指定默认的数据库字符集
-DDEFAULT_COLLATION=utf8_general_ci \    ---指定默认数据库校对规则

在企业里的不同场景下,可根据公司开发的程序确定字符集(建议选择UTF8,移动互联网环境下可选utf8mb4)。也可以在编译的时候指定字符集。
此时,建库的时候默认创建即可,例如“create database oldboy;”
编译时没有指定字符集或者指定了与网站程序不同的字符集,创建数据库时指定字符集即可,也可以在数据库配置文件里修改默认的字符集显示

2、显示数据库
show databases;

示例:

mysql> show databases like 'oldboy';    ---匹配oldboy字符串的内容
+-------------------+
| Database (oldboy) |
+-------------------+
| oldboy            |
+-------------------+
1 row in set (0.34 sec)
mysql> show databases like 'oldboy%';    ---%为通配符,表示匹配以oldboy开头的所有内容
+--------------------+
| Database (oldboy%) |
+--------------------+
| oldboy             |
| oldboy_gbk         |
+--------------------+
2 rows in set (0.04 sec)
3、切换数据库

所谓的切换库,就相当于系统中的切换路径一样,只不过,系统中使用的是类似于“cd /etc”的命令,而数据库里切换库使用的是use命令。
如果oldboy数据库存在,则可通过如下命令尝试进入oldboy数据库里

mysql> select database();    ---查看当前管理员所在的库名
+------------+
| database() |
+------------+
| NULL       |    ---空值,表示没有在任何库里
+------------+
1 row in set (0.03 sec)
mysql> use oldboy    ---切换到oldboy库里
Database changed
mysql> select database();    ---重新查看
+------------+
| database() |
+------------+
| oldboy     |    ---表示存在于oldboy库里了
+------------+
1 row in set (0.00 sec)
4、查看数据库包含的表信息

查看数据库包含的表信息有两种常见的方法,第一种是切到数据库里面去查看,第二种是在外面查看库里的表信息。
切到数据库里面去查看表信息:

mysql> use oldboy
Database changed
mysql> show tables;
Empty set (0.00 sec)    ---空表,因为是新库,还没有建立表

在库外面查看库里的表信息:

mysql> show tables from oldboy;    ---查看指定库oldboy中包含的表
Empty set (0.00 sec)
mysql> show tables in oldboy_gbk;
Empty set (0.00 sec)
mysql> show tables from mysql like 'db%';    ---还可以匹配包含指定字符开头的表
+-----------------------+
| Tables_in_mysql (db%) |
+-----------------------+
| db                    |
+-----------------------+
1 row in set (0.00 sec)
5、删除数据库
mysql> drop database oldboy_gbk;
Query OK, 0 rows affected (0.06 sec)
mysql> show databases like 'oldboy_gbk';
Empty set (0.00 sec)

2. DDL&&DCL语句之管理用户

1、查看当前数据库用户列表:
mysql> select user,host from mysql.user;
+--------+-----------+
| user   | host      |
+--------+-----------+
| root   | 127.0.0.1 |
| root   | localhost |
| system | localhost |
+--------+-----------+
3 rows in set (0.00 sec)

select表示查询,user和host为要查找的mysql表的字段,from表示去哪查,mysql.user是mysql库里的user表

2、创建数据库用户
mysql> create user blog@localhost identified by 'oldboy123';
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host from mysql.user;
+--------+-----------+
| user   | host      |
+--------+-----------+
| root   | 127.0.0.1 |
| blog   | localhost |    ---创建成功
| root   | localhost |
| system | localhost |
+--------+-----------+
4 rows in set (0.00 sec)

企业里创建用户一般是授权一个内网网段登录,最常见的网段写法有两种。
方法1:172.16.1.%(%为通配符,匹配所有的内容)
方法2:172.16.1.0/255.255.255.0,但是不能使用172.16.1.0/24
创建一个用户bbs,授权192.168.1.0/24网段内机器访问:

mysql> create user bbs@'192.168.1.%' identified by 'bbs123';
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host from mysql.user where user='bbs';
+------+-------------+
| user | host        |
+------+-------------+
| bbs  | 192.168.1.% |
+------+-------------+
1 row in set (0.00 sec)

登录测试:

[root@oldboy ~]# mysql -ublog -poldboy123
[root@oldboy ~]# mysql -ubbs -pbbs123 -h 192.168.1.115    ---异地或本机登录bbs用户必须制定IP

使用create创建的用户仅仅是空用户,即除了可以连接数据库之外,其没有任何数据库权限,有关用户授权还必须要使用grant命令。而grant命令可以同时完成创建用户和授权两种操作,因此,一般都使用grant代替create来创建用户。

3、删除数据库用户
mysql> select user,host from mysql.user where user='blog';
+------+-----------+
| user | host      |
+------+-----------+
| blog | localhost |
+------+-----------+
1 row in set (0.00 sec)
mysql> drop user 'blog'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host from mysql.user where user='blog';
Empty set (0.00 sec)    ---删除成功
mysql> flush privileges;    ---使得处理用户后,对数据库生效,一般有数据库改动的情况,最好执行这个固定命令
Query OK, 0 rows affected (0.00 sec)

如果使用drop删除不了用户,很可能是因为用户或主机部分是特殊字段或大写内容等,可以用下面的方式删除:

mysql> select user,host from mysql.user where user='bbs';
+------+-------------+
| user | host        |
+------+-------------+
| bbs  | 192.168.1.% |
+------+-------------+
1 row in set (0.00 sec)
mysql> delete from mysql.user where user='bbs' and host='192.168.1.%';
Query OK, 1 row affected (0.07 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host from mysql.user where user='bbs';
Empty set (0.00 sec)
4、授权数据库用户

示例1:创建test用户,对oldboy库具有所有权限,允许从localhost主机登录管理数据库,密码是test123

mysql> grant all privileges on oldboy.* to test@localhost identified by 'test123';
Query OK, 0 rows affected (0.00 sec)
mysql> select user,host from mysql.user where user='test';
+------+-----------+
| user | host      |
+------+-----------+
| test | localhost |    ---创建成功
+------+-----------+
1 row in set (0.00 sec)
mysql> show grants for 'test'@'localhost';    ---查看test用户权限
+-------------------------------------------------------------------------------------------------------------+
| Grants for test@localhost                                                                                   |
+-------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'test'@'localhost' IDENTIFIED BY PASSWORD '*676243218923905CF94CB52A3C9D3EB30CE8E20D' |
| GRANT ALL PRIVILEGES ON `oldboy`.* TO 'test'@'localhost'                                                    |
+-------------------------------------------------------------------------------------------------------------+
2 rows in set (0.01 sec)

示例2:
授权与root同等地位的system用户权限,创建完成可以选择删除原来的root用户

mysql> show grants for root@localhost;    ---查看root用户的权限
+----------------------------------------------------------------------------------------------------------------------------------------+
| Grants for root@localhost                                                                                                              |
+----------------------------------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*FE28814B4A8B3309DAC6ED7D3237ADED6DA1E515' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION                                                                           |
+----------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.05 sec)

mysql> grant all on *.* to system@'localhost' identified by 'system123' with grant option;
Query OK, 0 rows affected (0.15 sec)
mysql> GRANT PROXY ON ''@'' TO 'system'@'localhost' WITH GRANT OPTION;    ---允许创建代理用户,注意,如果之前在my.cnf设置了登录帐号密码,上一步操作会修改掉my.cnf的帐号,然后这一步会报错,需要去my.cnf改回root账户再执行才能成功
Query OK, 0 rows affected (0.15 sec)
mysql> show grants for system@localhost;
+------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for system@localhost                                                                                                              |
+------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'system'@'localhost' IDENTIFIED BY PASSWORD '*87C0B9109E34C30E15316C528EC1F15C71E45D7A' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION                                                                           |
+------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

若是要授权局域网内的主机远程连接数据库,根据grant命令的语法,我们知道test@'localhost'位置为授权访问数据库的用户和主机,其中localhost可以用域名、IP地址或IP段来替代,因此,要授权局域网内的主机可以通过如下方法来实现。
第一种方法:一条命令+百分号的匹配法示例如下:

mysql> grant all on *.* to test@'192.168.9.%' identified by 'test123';
Query OK, 0 rows affected (0.00 sec)

第二种方法:一条命令+子网掩码的配置法,示例如下:

mysql> grant all on *.* to test@'192.168.9.0/255.255.255.0' identified by 'test123';
Query OK, 0 rows affected (0.00 sec)

注意:要记得对上述每条grant命令最好都刷新权限(即使添加用户不需要,养成良好的一致性操作习惯很重要)

mysql> flush privileges;
Query OK, 0 rows affected (0.03 sec)
5、企业中grant授权权限问题说明

(1)企业里主数据库用户的授权问题说明
在企业生产环境中,如果是以Web形式连接数据库的用户,那么尽量不要授予all权限,最好是分拆授权,比如,授予select、insert、update、delete等适合Web使用的DML语句关键字权限。下面示例中授予的权限就比较规范合理,当然,对于不同的企业,要具体问题具体分析。

grant select,insert,update,delete on oldboy.* to test@'192.168.9.%' identified by 'test123';

注意:授予用户权限时有如下3条安全红线不要轻易跨过

  • 权限不能用all,而应用select、insert、update、delete等具体权限
  • 库不能用.,而应用“oldboy.*”格式具体到库
  • 主机不能用%,而应用内网IP段,即'192.168.9.%'格式

PHP程序语言连接MySQL的简易程序代码如下:

<?php
        //$link_id=mysql_connect('数据库主机名','用户','密码');
        $link_id=mysql_connect('192.168.9.115','test','test123') or mysql_error();
        if($link_id){
                echo "mysql successful by oldboy!";
        }else{
                echo mysql_error();
        }
?>

(2)博客、CMS、BBS等产品的数据库授权
前面说过,采用Web形式连接数据库的用户应尽量采用最小化原则进行授权,但是很多开源软件都是通过Web界面安装的,因此,在安装期间除了select、insert、update、delete这4个权限之外,有可能还需要create、drop等比较危险的权限。针对这种情况,需要建库、建表,授权例子如下:

mysql> grant select,insert,update,delete,create,drop on blog.* to 'blog'@'192.168.9.%' identified by 'blog123';
Query OK, 0 rows affected (0.04 sec)

生成数据库、表后,可以使用revoke命令收回create、drop授权:

mysql> revoke create,drop on blog.* from 'blog'@'192.168.9.%';    ---一定要输入正确,否则会收不回来
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for blog@'192.168.9.%';
+---------------------------------------------------------------------------------------------------------------+
| Grants for blog@192.168.9.%                                                                                   |
+---------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'blog'@'192.168.9.%' IDENTIFIED BY PASSWORD '*D6D67F3D1547519E29B7193DD019E55571BD09CA' |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `blog`.* TO 'blog'@'192.168.9.%'                                      |
+---------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

(3)生产环境针对主库(写为主读为辅)用户的授权策略
如果是单机,即Web或应用程序和数据库在一台电脑上的数据库授权,则可以采用如下命令:

GRANT all privileges ON `blog`.* TO 'blog'@'localhost' identified by 'blog123';

如果应用程序服务器和数据库服务器不在一个主机上,则授权命令如下:

GRANT all privileges ON `blog`.* TO 'blog'@'192.168.9.%' identified by 'oldboy456';

由于工作中异机环境比较多,因此下面都是针对异机进行说明的。
下面的命令为严格授权,使用该命令虽然重视了安全,但却忽略了方便

GRANT SELECT,INSERT,UPDATE,DELETE ON `blog`.* TO 'blog'@'192.168.9.%' identified by 'blog123';

(4)生产环境从库(只读)用户的授权
授权命令如下:

GRANT SELECT ON `blog`.* TO 'blog'@'192.168.9.%' identified by 'blog123';

这里表示为192.168.9.0/24的用户blog授予管理blog数据库中所有表(*表示所有表)的只读权限(SELECT),密码为blog123。
(5)生产环境主从库高级授权策略
针对这种情况,有两种授权形式,具体如下:
第一种,使用简单方法

使用简单方法

第二种,配置简单方法

配置简单方法

显然,第一种方法是最专业的,第二种方法给开发者的感觉是有多个用户,不专业。
(6)生产场景下的具体授权
主库授权的命令为:

GRANT SELECT,INSERT,UPDATE,DELETE ON `blog`.* TO 'blog'@'192.168.9.%' identified by 'blog123';

从库授权用户的命令为:

GRANT SELECT ON `blog`.* TO 'blog'@'192.168.9.%' identified by 'blog123';

当然,从库除了做SELECT授权之外,还可以加read-only等只读参数,严格控制Web用户写从库。
(7)生产场景下,主从库读写分离授权难点与解决方案
若主从库的mysql库和表是同步的,则会无法针对同一个用户授权不同的权限。主库授权后会自动同步到从库上,导致从库的授权只读失败。
解决方法有如下几点:

  • 取消数据库中mysql库的同步功能
  • 授权主库权限后,从库执行收回增删改权限,只保留查的权限
  • 不在授权上控制增删改,而是用read-only参数控制普通用户更新从库。注意,read-only参数对超级用户无效

(8)授权不规范导致的生产血案
运维人员授权用户all权限,导致开发人员通过该用户自行修改了表结构(字段),造成服务出问题,最后黑锅甩在了运维人员身上。
运维人员排查了半天也没有结果,终于在对比表结构(对比生产数据和备份的数据)的时候发现了问题,最后告诉开发人员,把字段改回去,服务就好了。
启发:生产场景下尽量不要给开发人员select以外的权限,对于网站的连接帐号,不要授予select、insert、delete、update以外的权限。对别人的“仁慈”,就是对自己的岗位和公司最大的“背叛”。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容