目录
01事务transaction
事务主要用于处理操作量大,复杂度高的数据,事务可以保证多个操作原子性,对于数据库来说,事务可以保证批量的DML( insert,update,delete ) 要么全执行,要么全不执行。
通常一个事务对应一个完整的业务.
假设银行的用户表如下:
以银行转账为例,A账户向B账户转账300元,执行两个sql语句
update table bank set money=1000-300 where id='A';
update table bank set money=1000+300 where id='B';
假设转账需要完成上述两行语句,如果第一句执行,A的账户少了300块钱,但第二句因为某些原因没执行,这就造成了问题
so,为了保证转账业务的正常,要么上述两句全部执行,要么就都不执行
事务具有4个特征(ACID)
-
原子性(Atomicity):事务是最小单元,不可再分,一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态.
-
一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
-
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
-
持久性(Durability):事务处理结束后,对数据的修改就是永久地保存再数据库中,即便系统故障也不会丢失.
事务的处理:
1、用 begin, rollback, commit来实现
- begin 或者start transaction开始一个事务
- rollback 事务回滚
- commit 事务确认
2、直接用 set 来改变 MySQL 的自动提交模式:
- set autocommit=0 禁止自动提交
- set autocommit=1 开启自动提交
示例:
-- 开启事务
BEGIN;
--操作1
UPDATE bank SET money=700-300 WHERE id='A';
-- 操作2
UPDATE bank SET money=1300+300 WHERE id='B';
-- 在当前连接中查询表是否被修改,发现被修改
SELECT * FROM bank;
说明,虽然还没有提交事务,但是本连接上查询到的表已修改是因为在内存中修改,还没储存
另开一个连接B,输入查询语句
select * from bank;
数据还是原来的样子
在原来的连接中,提交事务
commit;
再次在连接B中查询时,才发现数据被修改.如果在提交事务前,使用回滚命令
rollback;
那么之前的事务操作将会被清空,回到开启这个事务前的状态.
事务的隔离级别
- read uncommitted 读未提交
事务A和事务B,事务A未提交的数据,事务B可以读取,这里读取到的数据叫做“脏数据”,该级别最低,一般只是理论上存在,数据库的默认隔离级别都高于该级别。 - read committed 读已提交
事务A和事务B,事务A提交的数据,事务B才可读取到,换句话说:对方事务提交之后的数据,当前事务才可读取到,可以避免读取“脏数据”,但是该级别会有“不可重复读”的问题,事务B读取一条数据,当事务A修改这条数据并提交后,事务B再读取这条数据时,数据发生了变化,即事务B每次读取的数据有可能不一致,这种情况叫做“不可重复读”。 - repeatable read 重复读
MySQL默认的隔离级别是重复读,该级别可以达到“重复读”的效果,但是会有“幻读”的问题,即事务A读取数据,此时事务B修改了这条数据,但是事务A读取的还是之前的旧数据的内容,这样就出现了幻读。 - serializable 串行化
事务A和事务B,事务A在操作数据库表中数据的时候,事务B只能排队等待,这样保证了同一个时间点上只有一个事务操作数据库,该级别可以解决“幻读”的问题。但是这种级别一般很少使用,因为吞吐量太低,用户体验不好。
02 索引
索引是由数据表中一列或者多列组合而成,其作用是提高对表中数据的查询速度,类似于图书的目录,方便快速定位寻找指定的内容
表中每一个字段都可添加索引。主键会自动添加索引,在查询时,如果能通过主键查询的尽量使用主键查询,效率高
优点:提高了数据查询的速度
缺点:创建和维护索引的时间增加了
什么情况下适合添加索引?
- 该字段数据量庞大;
- 该字段很少的DML操作(由于索引也需要维护,DML操作多的话,也影响检索效率);
- 该字段经常出现在where条件中order by,group by中,且数据分布比较离散的列适合创建索引
注:实际中添加索引不一定能提高效率,索引添加不当可能导致效率降低
索引的分类
- 普通索引:index 这是最基本的索引,它没有任何限制
- 唯一性索引:使用unique index关键字,与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
- 主键索引:特殊的唯一索引,不允许有空值。
- 全文索引,使用fulltext unique关键字,只能创建在char varchar text字段上,提高查询较大字符串的速度,只能用在MyISAM引擎
- 单列索引,在一个字段上创建索引,可以是上面三种索引的任意一种
- 联合索引(又叫复合索引),在表的多个字段上创建索引
- 空间索引:使用spatial index 关键字,只能建立在空间数据类型,提高系统获取空间数据的效率
创建索引:
1创建表时直接创建
create table table_name(
字段1 数据类型,
字段2 数据类型,
...,
index [别名](字段名1,...)
);
2在已有表上创建
create index 索引名 on 表名(列名);
3修改表结构创建
alter table 表名 add index [索引名](列名);
示例:
-- 方式1
CREATE TABLE bank1(
id INT,
username VARCHAR(20),
sex VARCHAR(2),
INDEX uname(username)
);
-- 方式2
CREATE INDEX enumber ON employee(employeenumber);
-- 方式3
ALTER TABLE employee ADD INDEX (employeename);
删除索引
drop index 索引名 on 表名
示例:
DROP INDEX uname ON bank1;
SHOW INDEX FROM employee;
DROP INDEX employeename ON employee;
查看表中的索引
show index from 表名;
注: 1 联合索引的名命名规则
如果where条件中是or关系,加索引不起作用
符合最左原则或者叫需前缀原则
比如index (a,b,c)可以使用where a='值',或者where a='值' and b='值' 或者 where a='值' and b='值' and c='值'
2 只要列涉及到运算,MySQL就不会使用索引,不管是使用函数还是使用加减乘除等运算
3 列值为NULL时,查询会用到索引,如果计划对列进行索引,就要尽量避免把它设置为可空,MySQL难以优化引用了可空列的查询,它会使索引、索引统计和值更加复杂
4 如果MySQL估计使用索引比全表扫描更慢,会放弃使用索引
5 以“%”开头的LIKE语句,模糊匹配
6 or语句前后没有同时使用索引
7数据类型出现隐式转化(如varchar不加单引号的话可能会自动转换为int型)
03 视图
视图是虚拟的表,只是一个查询结果,不包含任何列或数据。使用视图可以隐藏具体的细节,保护数据;视图创建后,可以使用与表相同的方式利用它们。可以对视图进行增,改,查,操作,视图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。
视图不能被索引,也不能有关联的触发器或默认值,如果视图本身内有order by 则对视图再次order by将被覆盖。
创建视图:
create view 视图名 as 查询语句;
查看视图:
select 字段(或者*全部) from 视图名;
修改视图:
alter view 视图名 as 查询语句;
删除视图:
drop view if exists 视图名;
示例:
-- 创建视图,视图中的内容是employee表中的员工编号,姓名,工作
CREATE VIEW eview AS SELECT employeenumber ,employeename, job FROM employee;
-- 查看视图
SELECT * FROM eview;
-- 修改视图,使其内容是employee表的全部
ALTER VIEW eview AS SELECT * FROM employee;
-- 查看修改后的视图
SELECT * FROM eview;
-- 删除视图
DROP VIEW IF EXISTS eview;
04 触发器trigger
触发器(TRIGGER)是由事件来触发某个操作。这些事件包括 INSERT 语句、UPDATE 语句和 DELETE 语句。当数据库系统执行这些事件时,就会激活触发器执行相应的操作。MySQL 从 5.0.2 版本开始支持触发器
触发器中不能包含 START TRANSACTION, COMMIT, ROLLBACK,CALL 等。
创建触发器
创建一条执行语句的触发器:
create trigger 触发器名 before|after 触发条件(update|delete|insert) on 表名 for each row 执行语句
创建多条执行语句的触发器
delimiter &&
create trigger 触发器名 before|after 触发事件(update|delete|insert) on 表名 for each row
begin
执行语句1;
执行语句2;
执行语句3;
end
&&
delimiter ;
说明:一般 SQL 语句以“;”结束,在创建多个语句执行的触发器时,要用到“;”,所以用 delimiter 关键字来作为段落
delete,在where条件中被删除的行用old代替,update,insert操作,where条件语句中修改的行用new代替
示例:
-- 复制表
INSERT INTO empcount SELECT job, COUNT(*) AS jobcount FROM employee GROUP BY job ;
-- 创建一条语句的触发器
CREATE TRIGGER addnum AFTER INSERT ON employee FOR EACH ROW UPDATE empcount SET jobcount=jobcount+1 WHERE new.job=empcount.jobtype;
--测试触发器
INSERT INTO employee VALUES(8000,'liudehua','CLERK',7499,'1992-05-08',1500,NULL,20);
-- 创建多条执行语句的触发器
DELIMITER &&
CREATE TRIGGER dele AFTER DELETE ON employee FOR EACH ROW
BEGIN
INSERT INTO emplog VALUES(NOW(),'删除了一条数据');
UPDATE empcount SET jobcount=jobcount-1 WHERE empcount.jobtype=old.job;
END
&&
DELIMITER ;
-- 测试触发器
DELETE FROM emp`empcount`loyee WHERE employeename='liudehua';
查看触发器:
show triggers ;
SELECT * FROM information_schema. triggers
删除触发器:
drop trigger 触发器名;
参考:小猴子视频
https://blog.csdn.net/weixin_38399962/article/details/80081913