1、视图
①定义:视图(View)是一种虚拟存在的表,对于使用视图的用户来说基本上是透明的。视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。
②定义视图:create view 视图名 as sql语句
-- 查询所有省份的数据
SELECT * FROM provinces;
-- 创建一个视图表,将查询的结果放在这张视图中
CREATE VIEW v_pro AS SELECT * FROM provinces;
-- 查询视图中的所有信息
SELECT * FROM v_pro;
③使用视图
查看视图:show tables;视图会以一张虚拟表
查询视图:select * from v_pro;将视图中的信息查询出来
删除视图:drop view 视图名称;将创建的视图删掉
④视图的作用
简单:提高了重用性,就像一个函数。想用的时候不用写复杂的sql语句。
安全:提高了安全性能,可以针对不同的用户,设定不同的视图。
数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响
⑤只有当不包含以下情况时候视图才能被修改
select子句中包含distinct
select字句中包含组函数
select语句中包含group by子句
selecy语句红包含order by子句
where子句中包含相关子查询
from字句中包含多个表
如果视图中有计算列,则不能更新
如果基表中有某个具有非空约束的列未出现在视图定义中,则不能做insert操作。
2、事务
2.1定义
它是一个操作序列,这些操作要么都执行,要么都不执行,是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性,它是一个不可分割的工作单位,广泛的运用于订单系统、银行系统等多种场景
2.2案例
假如一个银行的数据库有两张表:支票表(checking)和储蓄表(savings)。现在要从用户Jane的支票账户转移200美元到她的储蓄账户,那么至少需要三个步骤:
1.检查支票账户的余额高于或者等于200美元。
select * from checking where name='jane' and money>200;
2.从支票账户余额中减去200美元。
update checking set money=money-200 where name='jane';
3.在储蓄帐户余额中增加200美元。
update saving set money=money+200 where name='jane';
上述三个步骤的操作必须打包在一个事务中,任何一个步骤失败,则必须回滚所有的步骤。不能说只是扣费成功或者只是收钱成功,只要有一句sql有错误则去全体不执行
2.3事务的特性(ACID)
①原子性(Atomicity):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性
②一致性(Consistency):数据库总是从一个一致性的状态转换到另一个一致性的状态。(在前面的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。)
③隔离性(isolation):通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。(在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外的一个账户汇总程序开始运行,则其看到支票帐户的余额并没有被减去200美元。)
④持久性(durability):一旦事务提交,则其所做的修改会永久保存到数据库。(此时即使系统崩溃,修改的数据也不会丢失。)
2.4事务的状态
①活动的(active):事务对应的数据库操作正在执行过程中时,我们就说该事务处在活动的状态。
②部分提交的(partially committed):当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时,我们就说该事务处在部分提交的状态。
③失败的(failed):当事务处在活动的或者部分提交的状态时,可能遇到了某些错误(数据库自身的错误、操作系统错误或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在失败的状态。
④中止的(aborted):如果事务执行了半截而变为失败的状态,当狗哥账户的钱被扣除,但是猫爷账户的钱没有增加时遇到了错误,从而当前事务处在了失败的状态,那么就需要把已经修改的狗哥账户余额调整为未转账之前的金额,换句话说,就是要撤销失败事务对当前数据库造成的影响。书面一点的话,我们把这个撤销的过程称之为回滚。当回滚操作执行完毕时,也就是数据库恢复到了执行事务之前的状态,我们就说该事务处在了中止的状态。
⑤提交的(committed):当一个处在部分提交的状态的事务将修改过的数据都同步到磁盘上之后,我们就可以说该事务处在了提交的状态。
2.5事务的命令
数据库引擎必须是innodb,因为其它的引擎不支持
①开启事务:开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中begin;或者start transaction;
第二个可以添加事务的修饰符多个修饰符之间可以通过逗号进行分隔,例如start transaction read only创建只读属性或者start transaction read write创建读写事务
②提交事务:将缓存中的数据变更维护到物理表中commit;
③回滚事务:放弃缓存中变更的数据rollback;
只能在内存中回滚,回滚之后还得commit一下
2.6保存点
如果你开启了一个事务,并且已经敲了很多语句,忽然发现上一条语句有点问题,你只好使用ROLLBACK语句来让数据库状态恢复到事务执行之前的样子,然后一切从头再来。所以设计数据库的大叔们提出了一个保存点(英文:savepoint)的概念,就是在事务对应的数据库语句中打几个点,我们在调用rollback语句时可以指定会滚到哪个点,而不是回到最初的原点。
①创建保存点savepoint 保点名称;
②回滚到指定保存点的位置rollback [work] to [savepoint] 保存点;
③删除保存点release savepoint 保存点名称;
注意点:
1.修改数据的命令会自动的触发事务,包括insert、update、delete
数据库会把每一条修改命令当成一个独立的事务去执行,可以通过show variables like 'autocommit';
查看自动提交的状态
2.在SQL语句中手动开启事务的原因是:可以进行多次数据的修改,如果成功一起成功,否则一起回滚到之前的数据
3、索引
3.1定义
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度,创建索引也会占用内存只是找不到可以直接操作的文件
3.2原理
用的是数据结构中B+树的思想,可以先给数据排序,然后再将数据以树状显示,通过排序查找提高查询速度
3.3索引的使用
①查看索引show index from 表名;
②创建索引create [unique唯一索引] index 索引名称 on 表名(字段名称(长度))
如果指定字段是字符串,需要指定长度,建议长度与定义字段时的长度一致,字段类型如果不是字符串,可以不填写长度部分
③删除索引drop index 索引名称 on 表名;
3.4验证索引的强大
①创建测试表:create tables test(title varchar(50))
②用python添加测试数据
import pymysql
def test():
conn = pymysql.connect(host='127.0.0.1',port=3306,password='root',username='root',database='mytest')
cs = conn.cursor()
for i in range(100000):
cs.execute('insert into test values(%s)'%i)
conn.commit()
cs.close()
conn.close()
if __name__ == '__main__'
test()
③开启运行时间监测set profiling=1;
④查询第10000条数据select * from test where title='ha-99999';
⑤查看执行的时间show profiles;
⑥为title列创建索引create index idx_title on test(title(10));
⑦再次查询select * from test where title='ha-99999';
⑧查看时间show profiles;
对比之后发现时间相差100倍
3.5索引的创建
①适合建立索引的情况
主键自动建立索引
频繁作为查询条件的字段应该建立索引
查询中与其他表关联的字段,外键关系建立索引
在高并发的情况下创建复合索引
查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度 (建立索引的顺序跟排序的顺序保持一致)
②不适合建立索引的情况
频繁更新的字段不适合建立索引
where条件里面用不到的字段不创建索引
表记录太少,当表中数据量超过三百万条数据,可以考虑建立索引
数据重复且平均的表字段,比如性别,国籍
4、MySQL的账户权限管理
4.1意义
方便多人共同操作数据库,给不同的人不同的权限,这样就会使数据更加的安全和可操作,避免出现权限不足,或者删库跑路等事件,在生产环境下操作数据库时,绝对不可以使用root账户连接,而是创建特定的账户,授予这个账户特定的操作权限,然后连接进行操作,主要的操作就是数据的CRUD
4.2类别
服务实例级账号:启动了一个mysql,即为一个数据库实例;如果某用户如root,拥有服务实例级分配的权限,那么该账号就可以删除所有的数据库、连同这些库中的表
数据库级别账号:对特定数据库执行增删改查的所有操作
数据表级别账号:对特定表执行增删改查等所有操作
字段级别的权限:对某些表的特定字段进行操作
存储程序级别的账号:对存储程序进行增删改查的操作
4.3权限分配
①创建用户:语法create user ‘username’@‘host’ identified by ‘password’;
username:登录的用户名
password:是登录的密码
host:指定可以登录的主机,其中localhost表示本机,%表示所有主机create user 'wchao'@'%' identified by '123'
②修改当前用户的密码alter user user() identified by '123456'
③删除用户drop wchao;
必须在root下才能删除
4.4.1创建账户&授权
需要使用实例级账户登录后操作,以root为例
常用权限主要包括:create、alter、drop、insert、update、delete、select
如果分配所有权限,可以使用all privileges
grant 权限列表 on 数据库 to '用户名'@'访问主机' identified by '密码';
①举例:创建一个laowang的账号,密码为123456,只能通过本地访问, 并且只能对jing_dong数据库中的所有表进行读操作
grant select on jing_dong.* to 'laowang'@'localhost' identified by '123456';
flush privileges;--如果报错就刷新数据库权限
②举例:创建一个laoli的账号,密码为12345678,可以任意电脑进行链接访问, 并且对jing_dong数据库中的所有表拥有所有权限
grant all privileges on jing_dong.* to "laoli"@"%" identified by "12345678"
常见权限