ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

事务与流程与索引

2022-08-19 23:01:13  阅读:107  来源: 互联网

标签:事务 流程 cmd id 索引 SQL 数据 create


视图

SQL语句的执行后产生的结果是一张虚拟表,我们可以对该表做其他操作,如果这张虚拟表需要频繁使用,那我们就可以将这张虚拟表保存起来,保存起来的就被称为'视图'

create view 视图名 as SQL语句;
create view teacher2course as
select * from teacher inner jojin course on teacher.tid = course.teacher_id;

'''
在硬盘中,视图只有表结构文件,没有表数据文件
视图通常是用于查询,尽量不要修改视图中的数据
当对通过视图看到的数据进行修改时,相应的基本表的数据也要发生变化
若基本表的数据发生变化,则这种变化也可以自动地反映到视图中
'''

触发器

1.触发器是保证数据完整性的一种方法,它的执行是由事件来触发的,对表的增、改、删都会自动触发该功能(增前、增后、改前、改后、删前、删后)
defore/after insert/update/delete on 表名 for each row
begin
SQL语句
end

2.触发器内部需要用到分号,但分号又是SQL语句默认的结束符,所以为了能完整的使用触发器,需要临时修改SQL语句默认的结束符
delimiter $$
需要使用分号的SQL语句
delimiter :

3.例子
create table cmd (id int primary key auto_increment,
            user char(32),priv char(10),cmd char(64),
            sub_time datetime,  # 命令提交提交时间
            success enum ('yes','no'));  # 0代表执行失败
create table cmd (id int primary key auto_increment,
            err_cmd char(64),  # 记录错误的命令
            err_time datetime);  # 错误命令提交时间
delimiter $$  # 将mysql的结束符该为$$
sreate trigger tri_after_insert_cmd after insert on cmd for each row
begin
	if new.success = 'no' then  # 新记录(cmd)都会被封装成new对象
    	insert into errlog(err_cmd,err_time) values(new.cmd,new.sub_time);
	end if;
end $$
delimiter ;  # 结束后在把结束符改回来
'''
sreate trigger命令定义触发器,即修改特定表中的数据时要执行的代码块
show triggers;
'''
#往表cmd中插入记录,触发接触器,根据if的条件决定是否插入错误日志
insert into cmd (user,priv,cmd,sub_time,success) 
values('barry','0755','1s -1 /etc',now(),'yes'),
('barry','0755','cat /etc/passwd',now(),'no'),
('harry','0755','useradd xxx',now(),'no'),
('harry','0755','ps aux',now(),'yes');
select * from errlog;
# 删除接触器
drop trigger tri_after_insert_cmd;

事务

1.事务的概念
在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序

2.事务的四大特征(ACID)
2.1A:原子性
一个事务是一个不可分割的工作单位,事务中的操作要么都做,要么都不做
2.2C:一致性
事务必须是数据库从一个一致性状态变到另一个一致性状态,因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态,一致性与原子性是密切相关的
2.3I:隔离性
一个事务的执行不能被其他事务干扰
2.4D:持久性
一个事务一旦被提交,它对数据库中数据的改变就应该是永久的,之后的其他操作不应该对其有任何影响

3.使用
# 建表
create table user(id int primary key auto_increment,
            name char(32),balance int);
# 输入数据
insert into user(name,balance) values
('barry',1000),
('harry',1000),
('tom',1000);
# 修改之前开启事务操作
start transaction
# 修改操作
update user set balance=900 where name='barry';  # 支付100
update user set balance=1010 where name='harry';  # 手续费10
update user set balance=1090 where name='tom';  # 卖家拿90
# 回滚到上一个状态
rollback;
# 开启事务之后,只要没有执行commit操作,数据其实都没有真正刷新到硬盘
commit;
'开启事务检测操作是否完整,不完整则回滚到上一状态,完整则执行commit操作'
# 站在python代码的角度,应该实现的伪代码逻辑
try:
    update user set balance=900 where name='barry';  # 支付100
	 update user set balance=1010 where name='harry';  # 手续费10
	 update user set balance=1090 where name='tom';  # 卖家拿90
except 异常:
    rollback;
else:
    commit;
    
4.扩展知识
4.1MySQL提供两种事务型存储引擎InnoDB和NDB、cluster及第三方XtraDB、PBXT

4.2事务处理中有几个关键词汇会反复出现
事务(transaction)
回退(rollback)
提交(commit)
保留点(savepoint)

4.3为了支持回退部分事务处理,必须在事务处理块中适合的位置放置占位符,这样如果需要回退就可以回退到某个占位符(保留点)
创建占位符可以使用savepoint
savepoint.sp01;
回退到占位符位置
rollback to sp01;
# 保留点在执行rollback或者commit之后自动释放

5.在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改
InnoDB支持所有隔离级别
set transaction isolation level 级别
5.1read uncommitted(未提交读)
事务中的修改即使没有提交,对其他事务也都是可见的,事务可以读取未提交的数据,这一现象也称为'脏读'
5.2read uncommitted(提交读)
大多数数据库系统默认的隔离级别
一个事务从开始到提交之前所做的任何修改对其他事务都是不可见的,这种级别也叫'不可重复读'
5.3repeatable read(可重复读)		# MySQL默认隔离级别
可以解决'脏读'问题,但无法解决'幻读'
所谓幻读指的是当某个事务在读取某个范围内的记录时另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录会产生幻行,InnoDB和XtraDB通过多版本并发控制(MVCC)及间隙锁策略可以解决该问题
5.4serializable(可串行读)

6.事务日志
6.1事务日志可以帮助提高事务的效率 
6.2存储引擎在修改表的数据时,只需要修改其内存拷贝再把该修改记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘
6.3事务日志采用的是追加方式,因此写日志操作是磁盘上一小块区域内的顺序IO,而不像随机IO需要次哦按的多个地方移动磁头,所以采用事务日志的方式相对来说要快的多
6.4事务日志持久之后,内存中被修改的数据再后台可以慢慢刷回磁盘,目前大多数存储引擎都是这样实现的,通常称之为'预写式日志'修改数据需要写两次磁盘
img

mvcc多版本并发控制

1.MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问

2.MVCC只能在read committed(提交读)、repeatable read(可重复读)两种隔离级别下工作,其他两个不兼容,read uncommitted总是读取最新,serializable所有的行都加锁

3.InnoDB的MVCC通过在每行记录后面保存两个隐藏的列来实现MVCC
一个列保存了行的创建时间
一个列保存了行的过期时间或删除时间  # 本质是系统版本号
每开始一个新的事务版号都会自动递增,事务开始时刻的系统版本号会作为事务的版本号,用来和查询到每行记录版本号进行比较

4.例如
4.1刚插入第一条数据的时候,我们默认事务id为1,实际是这样存储的
    username		create_version		delete_version
    jason						1			
我们在content列插入了kobe这条数据,在create_version这列存储了1,1是这次插入操作的事务id
4.2在将jason修改为barry01,实际存储是这样的
	 username		create_version		delete_version
    jason					1									   2
    jason01					2	
update的时候,会先将之前的数据delete_version标记为当前新的事务id,也就是2,然后将新数据写入,将新数据的create_version标记为新的事务id
4.3删除数据的时候,实际存储是这样的
		username		create_version		delete_version
    jason01					2		         3
'''
由此当我们查询一条记录的时候,只有满足以下两个条件的记录才会被显示出来:
1.当前事务id要大于或者等于当前行的create_version值,这表示在事务开始前这行数据已经存在了
2.当前事务id要小于delete_version值,这表示在事务开始之后这行记录才被删除
'''

存储过程

1.类似python中的自定义函数

delimiter 临时结束符
create procedure 名字(参数,参数)
begin
	SQL语句
end 临时结束符

delimiter $$
create procedure p1(in m int,  # in表示这个参数必须只能是传入不能被返回出去
in n int,out res int)  # out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去
begin
    select tname from teacher where tid > m and tid < n;
    set res=0;  # 用来标志存储过程是否执行
end $$
delimiter ;

# 针对res需要提前定义
set @res=10;	定义
select @res;	查看
call p1(1,5,@res)	调用
select @res	查看
'''
1.查看存储过程具体信息
show create procedure pro1;
2.查看所有存储过程
show procedure status;
3.删除存储过程
drop procedure pro1;
'''

内置函数

'可以通过help 函数名	查看帮助信息'
1.移除指定字符
Trim、LTrim、RTrim

2.大小写转换
Lower、Upper

3.获取左右起始指定个数字符
Left、Right

4.返回读音相似值(对英文效果)
Soundex
'''
eg:客户表中有一个顾客登记的用户名为J.Lee
但如果这是输入错误真名其实叫J.Lie,可以使用soundex匹配发音类似的
where Soundex(name)=Soundex('J.Lie')
'''

5.日期格式:date_format
'在MySQL中表示时间格式尽量采用2022-11-11形式'
create table blog(id int primary aut_increment,
            name char(32),sub_time datetime);
insert into blog(name,sub_time) values
('第1篇','2015-03-01 11:31:21'),
('第2篇','2015-03-11 16:31:21'),
('第3篇','2016-07-01 10:21:31'),
('第4篇','2016-07-22 09:23:21'),
('第5篇','2016-07-23 10:11:11'),
('第6篇','2016-07-25 11:21:31'),
('第7篇','2017-03-01 15:33:21'),
('第8篇','2017-03-01 17:32:21'),
('第9篇','2017-03-01 18:31:21');
select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_fromat(sub_time,'%Y-%m');  # 获取时间年月分组与篇数

where Date(sub_time) = '2015-03-01'
hwere Year(sub_time)=2016 and Month(sub_time)=07;
'''
其他日期处理相关函数
adddate	增加一个日期 
addtime	增加一个时间
datediff	计算两个日期差值
'''

流程控制

1.if条件语句
delimiter //
create procedure proc_if ()
begin

   declare i int default 0;
   if i = 1 then
		select 1;
   elseif i = 2 then
		select 2;
   else
		select 7;
   end if;

end //
delimiter ;

2.while循环
delimiter //
create procedure proc_while ()
begin

   deckare num int ;
   set num = 0 ;
   while num < 10 do
       select
        num ;
       set num = num + 1 ;
   end while

end //
delimiter ;

索引

1.索引就像是书的目录,它能让你更快的找到自己想要的内容

2.让获取的数据更有目的性,从而提高数据库检索数据的性能

3.索引在MySQL中也叫做'键',是存储引擎用于快速找到记录的一种数据结构
primary key
unique key
index key
'这三种键在数据查询的时候使用,都可以加快查询的速度'
primary key、unique key除了可以加快数据查询还有额外限制
index key只能加快数据查询,本身没有任何额外限制

4.理解索引加快数据查询
索引的存在可以加快数据查询,但是会减慢数据的增删

5.索引相关概念
索引是为了加速对表中数据行的检索而创建的一种分散的存储结构,是针对表而建立的,它是由数据页面以外的索引页面组成的,每个索引页面中的行都会含有逻辑指针,以便加速检索物理数据

索引底层原理

1.树
一种数据结构,主要用于优化数据查询的操作

2.二叉树:两个分支
B树(B-树)、B+树、B*树
2.1 B树
除了叶子节点可以有多个分支,其他节点最多只能两个分支,所有节点都可以直接存放完整数据(每个数据块是有固定大小的)
2.2B+树
只有叶子节点存放真正的数据,其他节点只存放主键值(辅助索引值)
2.3B*树
在树节点添加了通往其他节点的通道,减少查询次数

慢查询优化

explain SQL语句
'''
慢查询可以在日志中记录运行比较慢的SQL语句,通过慢查询可以找出SQL语句中执行效率低的,进行优化
'''

标签:事务,流程,cmd,id,索引,SQL,数据,create
来源: https://www.cnblogs.com/riuqi/p/16604363.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有