Mysql(2)
数据库事务(Database Transaction):
是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
简单的说:事务就是将一堆SQL(通常是增删改操作)的执行绑在一起,要么都执行成功,要么都执行失败,即都执行成功才算成功,否则就会恢复到这堆SQL执行之前的状态。
事务的四大特性(ACID):
(1)原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
(2)一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号金额之和应该是不变的。
(3)隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。也就是说,在事中务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据.
(4)持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。
MySQL中的事务:
- 开启事务:start transaction;
- 结束事务:commit(提交事务)或rollback(回滚事务)。
事务并发读问题:
多个事务对相同的数据同时进行操作,这叫做事务并发。
在事务并发时,如果没有采取必要的隔离措施,可能会导致各种并发问题,破坏数据的完整性等。这些问题中,其中有三类是读问题,分别是:脏读、不可重复读、幻读。
(1)脏读(dirty read):读到另一个事务的未提交更新数据,即读取到了脏数据;
例如:A给B转账100元但未提交事务,在B查询后,A做了回滚操作,那么B查询到了A未提交的数据,就称之为脏读。
(2)不可重复读(unrepeatable read):对同一记录的两次读取不一致,因为另一事务对该记录做了修改(是针对修改操作)
例如:在事务1中
1.1 事务隔离级别:
事务隔离级别分四个等级,在相同数据环境下,对数据执行相同的操作,设置不同的隔离级别,可能导致不同的结果。不同事务隔离级别能够解决的数据并发问题的能力也是不同的。
set tx_isolation='read-uncommitted';
1、READ UNCOMMITTED(读未提交数据)
安全级别最低, 可能出现任何事务并发问题(比如脏读、不可以重复读、幻读等)
性能最好(不使用!!)
2、READ COMMITTED(读已提交数据)(Oracle默认)
防止脏读,没有处理不可重复读,也没有处理幻读;
性能比REPEATABLE READ好
3、REPEATABLE READ(可重复读)(MySQL默认)
防止脏读和不可重复读,不能处理幻读问题;
性能比SERIALIZABLE好
4、SERIALIZABLE(串行化)
不会出现任何并发问题,因为它是对同一数据的访问是串行的,非并发访问的;
性能最差;
存储引擎
show engines
show variables like '%storage_engines%'
InnoDB
MyISAM
SQL性能下降原因:
SQL执行顺序
手写
机读
总结:
索引
索引是存储引擎用于快速查找记录的一种数据结构
索引可以包含一个或多个列的值,如果索引包含多个列,那么列的顺序也十分关键,因为Mysql只能高效的使用索引的最左前缀列。
分类:索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。
索引的类型
B-tree索引 :当人们讨论索引的时候,如果没有特别指明类型,那多半说的是B-tree索引,它使用B-Tree数据结构来存储数据(按照顺序),大多数Mysql引擎都支持这种索引,Archive除外。
哈希索引:哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效,对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是一个较小的值,并且不同键值的行计算出来的哈希码也不一样。哈希索引是将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。在Mysql中,只有Memory引擎显式支持哈希索引。
空间数据索引(R-Tree):MyISAM表支持空间索引,可以用作地理数据存储。
全文索引:全文索引是一种特殊类型的索引,它查找的是文本中的关键词,而不是直接比较索引中的值。
可以使用SHOW INDEX FROM table_name;
查看索引详情
索引种类
1.普通索引 INDEX
最基本的索引,它没有任何限制。
可以通过ALTER TABLE table_name ADD INDEX index_name (column);
创建普通索引
2.主键索引 PRIMARY KEY
它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引。
注意:一个表只能有一个主键
3.唯一索引 UNIQUE
唯一索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
可以通过ALTER TABLE table_name ADD UNIQUE (column);
创建唯一索引
可以通过ALTER TABLE table_name ADD UNIQUE (column1,column2);
创建唯一组合索引
4.组合索引 INDEX
组合索引,即一个索引包含多个列。多用于避免回表查询。
可以通过ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);
创建组合索引
5.全文索引 FULLTEXT
全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。
可以通过ALTER TABLE table_name ADD FULLTEXT (column);
创建全文索引
索引一经创建不能修改,如果要修改索引,只能删除重建。可以使用DROP INDEX index_name ON table_name;
删除索引。
索引的优缺点
1、优点:
2、 缺点:
视图
视图本身是一个虚拟表,不存放任何数据。在使用SQL语句访问视图的时候,它返回的数据是Mysql从其他表中生成的。视图和表是在同一个命名空间。
不能对视图创建触发器,也不能使用drop table 命令删除视图。
存储过程
存储过程(Stored Procedure)是预编译SQL语句的集合,这些语句存储在一个 名称下并作为一个
单元来处理。存储过程代替了传统的逐条执行SQL语句的方式。 一个存储过程中可包含查询、插入、
删除、更新等操作的一系列SQL语句,当这个存储过程被调用执行时,这些操作也会同时执行。
优点:
(1) 存储过程可以嵌套使用,支持代码重用。
(2) 存储过程可以接受与使用参数动态执行其中的SQL语句。
(3) 存储过程比一般的SQL语句执行速度快。存储过程在创建时已经被编译,每次执行时不需要重新编译。而SQL语句每次执行都需要编译。
(4)存储过程具有安全特性(例如权限)和所有权链接,以及可以附加到它们的证书。用户可以被授予权限来执行存储过程而不必直接对存储过程中引用的对象具有权限。
(5)存储过程允许模块化程序设计。存储过程一- 旦创建,以后即可在程序中调用任意多次。这可以改进应用程序的可维护性,并允许应用程序统一- 访问数据库。
(6)存储过程可以减少网络通信流量。- 个需要数百行SQL语句代码的操作可以通过一条执行过程代码的语句来执行,而不需要在网络中发送数百行代码。
(7)存储过程可以强制应用程序的安全性。参数化存储过程有助于保护应用程序不受SQLInjection攻击。
缺点:
a)存储过程,往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
b)存储过程的性能调校与撰写,受限于各种数据库系统。
创建存储过程:
CREATE PROCEDURE sp_ name ([proc_ parameter[,...]])
[characteristic .. ] routine_ body
sp_ name 要创建存储过程的名称
proc_ parameter 表示存储过程的参数
characteristic 表示存储过程的特性
routine_ body 表示 存储过程的SQL语句代码,可以用 begin ...end 来标志SQL语句的开始和结束
proc_ parameter [in | out inout ] param_name type 带参数
在存储过程的创建中,经常会用到一个十分重要的 MySQL 命令,即 DELIMITER 命令
在 MySQL 中,服务器处理 SQL 语句默认是以分号作为语句结束标志的。然而,在创建存储过程时,存储过程体可能包含有多条 SQL 语句,这些 SQL 语句如果仍以分号作为语句结束符,那么 MySQL 服务器在处理时会以遇到的第一条 SQL 语句结尾处的分号作为整个程序的结束符,而不再去处理存储过程体中后面的 SQL 语句,这样显然不行。为解决这个问题,通常可使用 DELIMITER 命令将结束命令修改为其他字符。
创建不带参数的存储过程:delimiter $$
create procedure ShowStuScore()
begin
select * from tb_students_score;
end $$
创建带参数的存储过程 :delimiter $$
create procedure GetScoreByStu()
(in name varchar(30))
begin
select students_score from tb_students_score;
end$$
执行存储过程 :call sp_name
修改存储过程 : alter procedure sp_name
删除存储过程:drop {procedure | function} [ if exists] sp_name
一次只能删除一个存储过程或者函数,需要有 alter routine 权限
变量的使用
1.变量的定义
通过declare 可以定义一个局部变量,该该变量的作用范围只能在 begin ...end块中,可以用在嵌套的块中。变量的定义必需写在复合语句的开头
并且写在其它语句的前面。可以一次生明多个相同类型的变量。如果需要,可以使用default默认值。
语法: declare var_name [ ,...type[default value]]
2.变量的赋值
变量可以直接赋值,或者通过查询赋值。直接赋值使用set,可以赋常量或者赋表达式
语法: set var_name =expr [,var_name = expr]
例:set last_month_start =date_sub(current_date(),interval 1 month);
也可以通过查询将结果赋值给变量,这要求查询返回的结果必须只用一行,具体语法:
select col_name[,....] into var_name[,...]table_expr
光标的使用
在存储过程和函数中,可以使用光标对结果集进行循环的处理。光标的使用包括光标的声明、open、fetch和close,其语法分别如下。
声明光标: declare cursor_name cursor for select_statement
open 光标:open cursor_name
fetch光标:fetch cursor_name into var_name[,var_name]...
close 光标 : close cursor_name
触发器
mysql数据库中触发器是一个特殊的存储过程,不同的是执行存储过程要使用 CALL 语句来调用,而触发器的执行不需要使用 CALL 语句来调用,也不需要手工启动,只要一个预定义的事件发生就会被 MySQL自动调用。
触发器的优点
(1)触发器自动执行,对表中的数据进行修改后,触发器立即被激活。
(2)为了实现复杂的数据库更新操作,触发器可以调用一一个或多个存储过程,甚至可以通过调用外部过程(不是数据库管理系统本身)完成相应的操作。
(3)触发器能够实现比CHECK约束更为复杂的数据完整性约束。在数据库中,为了实现数据完整性约束,可以使用CHECK约束或触发器。CHECK约束不允许引用其他表中的列来完成检查工作,而触发器可以引用其他表中的列。它更适合在大型数据库管理系统中用来约束数据的完整性。
(4) 触发器可以检测数据库内的操作,从而取消了数据库未经许可的更新操作,使数据库修改、更新操作更安全,数据库的运行也更稳定。
(5)触发器能够对数据库中的相关表实现级联更改。触发器是基于一个表创建的,但是可以针对多个表进行操作,实现数据库中相关表的级联更改。
(6)一个表中可以同时存在3个不同操作的触发器( INSERT、UPDATE和DELETE)。
创建触发器:
create trigger trigger_name trigger_time trigger_event on tbl_name for each row trigger_stmt
触发器只能创建在永久表上,不能对临时表创建触发器
trigger_time 是触发器的触发时间,可以是before 或者after ,before 的含义值在检查约束前触发,而after是在检查约束后触发
trigger_even 就是触发器的触发事件,可以是insert、update或者delete。
删除触发器:
drop trigger [schema_name]trigger_name