diff --git "a/34 \345\210\230\346\231\272\347\277\224/\344\272\213\347\211\251.md" "b/34 \345\210\230\346\231\272\347\277\224/\344\272\213\347\211\251.md" new file mode 100644 index 0000000000000000000000000000000000000000..1ebad2a965fce012bc64ca76ed80285dd6528599 --- /dev/null +++ "b/34 \345\210\230\346\231\272\347\277\224/\344\272\213\347\211\251.md" @@ -0,0 +1,181 @@ +# 日志 + +## 笔记 + +事务:事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作的请求,即这些操作要么同时成功,要么同时失败 + +事务的操作: + +```mysql +-- 开启事务:标记事务的开启 +begin 或 start transaction; +-- 提交事务:成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步 +commit; +-- 回滚事务:失败的结束,将所有的DML语句操作历史全部清空 +rollback; + + +-- 默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句时,MySQL会立即隐式的提交事务 +-- 关闭自动事务 +set autocommit = off; +set autocommit = 0; -- 禁止自动提交,显式提交 +-- 开启自动事务 +set autocommit = on; +set autocommit = 1; -- 开启自动提交,隐式提交 +``` + +事务的四大特性: + +原子性:事务是一个不可分割的整体,事务开始后的所有操作,要么全部完成,要么全部不做 + +一致性:系统从一个正确的状态,迁移到另一个正确的状态 + +隔离性:每个事务的对象对其他事务的操作对象互相分离,事务提交前对其他事务不可见 + +持久性:事务一旦提交,其结果是永久性的 + +并发事务的问题: + +脏读:一个事务读到另一个事务还没有提交的值 + +不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读 + +幻读:一个事务按照条件查询数据时吗,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了一个幻影 + +事务的隔离级别: + +读未提交(read uncommitted):一个事务可以读取另一个事务未提交的数据,最低级别,任何情况都无法保证,会造成脏读 + +读已提交(read committed):一个事务要等另一个事务提交后才能读取数据,可避免脏读,会造成不可重复读 + +可重复读(repeatable read):在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读,不可重复读的发生,但是会造成幻读 + +串行(serializable):最高级别的隔离,在该级别下,事务串行化顺序执行,可以避免脏读,不可重复读与幻读。但是这种事务隔离级别效率低下,比较消耗数据库性能,一般不使用。 + +```mysql +-- 查看事务隔离级别 +select @@transaction_isolation +-- 设置事务隔离级别 +set [session|global] transaction isolation level {read uncommitted|read committed|repeatable read|serializable} +-- 注意 +-- mysql的默认隔离级别是 repeatable read 可重复读 +-- 事务隔离级别越高,数据越安全,但是性能越低 +``` + +事务部分回滚:savepoint,将事务分为几个部分(存档) + +```MySQL +savepoint 保存点1; -- 设置一个保存点 +rollback to 保持点; -- 回滚到保存点,此时事务还未结束,还可以继续回滚或者提交 + +-- 注意 +-- 因为有保存点的事务是分段执行的,所以回滚到某个保存点,事务并未结束,只有到commit才会结束 + +``` + +只读事务: + +```mysql +start transaction read only -- 手动开启只读事务 +此事务中只能读取数据,不能对数据进行操作 +``` + + + +## 作业 + +```mysql +create database test charset utf8; +use test; +-- 建表语句: +-- 执行以下SQL,建表插数: +-- 部门表 +create table dept( + deptno int primary key auto_increment, -- 部门编号 + dname varchar(14) , -- 部门名字 + loc varchar(13) -- 地址 +) ; +-- 员工表 +create table emp( + empno int primary key auto_increment,-- 员工编号 + ename varchar(10), -- 员工姓名 - + job varchar(9), -- 岗位 + mgr int, -- 直接领导编号 + hiredate date, -- 雇佣日期,入职日期 + sal int, -- 薪水 + comm int, -- 提成 + deptno int not null, -- 部门编号 + foreign key (deptno) references dept(deptno) +); +insert into dept values(10,'财务部','北京'); +insert into dept values(20,'研发部','上海'); +insert into dept values(30,'销售部','广州'); +insert into dept values(40,'行政部','深圳'); +insert into emp values(7369,'刘一','职员',7902,'1980-12-17',800,null,20); +insert into emp values(7499,'陈二','推销员',7698,'1981-02-20',1600,300,30); +insert into emp values(7521,'张三','推销员',7698,'1981-02-22',1250,500,30); +insert into emp values(7566,'李四','经理',7839,'1981-04-02',2975,null,20); +insert into emp values(7654,'王五','推销员',7698,'1981-09-28',1250,1400,30); +insert into emp values(7698,'赵六','经理',7839,'1981-05-01',2850,null,30); +insert into emp values(7782,'孙七','经理',7839,'1981-06-09',2450,null,10); +insert into emp values(7788,'周八','分析师',7566,'1987-06-13',3000,null,20); +insert into emp values(7839,'吴九','总裁',null,'1981-11-17',5000,null,10); +insert into emp values(7844,'郑十','推销员',7698,'1981-09-08',1500,0,30); +insert into emp values(7876,'郭十一','职员',7788,'1987-06-13',1100,null,20); +insert into emp values(7900,'钱多多','职员',7698,'1981-12-03',950,null,30); +insert into emp values(7902,'大锦鲤','分析师',7566,'1981-12-03',3000,null,20); +insert into emp values(7934,'木有钱','职员',7782,'1983-01-23',1300,null,10); +-- 完成以下练习题 +-- +-- 1、列出最低薪金大于1500的各种工作。 +SELECT DISTINCT job FROM emp e,dept d WHERE e.deptno = d.deptno and e.sal>1500; +-- +-- 2、列出在部门 "销售部" 工作的员工的姓名,假定不知道销售部的部门编号。 +SELECT e.ename FROM emp e,dept d WHERE e.deptno = d.deptno and d.dname = '销售部'; +-- +-- 3、列出薪金高于公司平均薪金的所有员工。 +SELECT * FROM emp WHERE sal > ( +SELECT avg(sal) avg_sal FROM emp); +-- +-- 4、列出与"周八"从事相同工作的所有员工。 +SELECT * FROM emp WHERE job = ( +SELECT job FROM emp WHERE ename = '周八'); +-- +-- 5、列出薪金等于部门30中员工的薪金的所有员工的姓名和薪金。 +SELECT ename,sal FROM emp WHERE sal in ( +SELECT sal FROM emp WHERE deptno=30); +-- +-- 6、列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金。 +SELECT ename,sal FROM emp WHERE sal > ( +SELECT max(sal) FROM emp WHERE deptno=30); +-- +-- 7、列出在每个部门工作的员工数量、平均工资、平均服务年限。 +SELECT DISTINCT + deptno, + avg( sal ) over ( PARTITION BY deptno ), + COUNT(*) over ( PARTITION BY deptno ), + avg( + TIMESTAMPDIFF( + YEAR, + hiredate, + NOW())) over ( PARTITION BY deptno ) +FROM + emp; +-- +-- 8、列出所有员工的姓名、部门名称和工资。 +SELECT ename,sal,dname FROM emp e,dept d WHERE e.deptno = d.deptno; +-- +-- 9、列出所有部门的详细信息和部门人数。 +SELECT d.*,count(*) FROM emp e,dept d WHERE e.deptno = d.deptno GROUP BY d.deptno; + +-- +-- 10、列出各种工作的最低工资。 +SELECT job,min(sal) FROM emp GROUP BY job; +-- +-- 11、列出各个部门的 经理 的最低薪金。 +SELECT d.dname,d.deptno,min(sal) FROM emp e,dept d WHERE e.deptno = d.deptno and job = '经理' GROUP BY d.deptno; +-- +-- 12、列出所有员工的年工资,按年薪从低到高排序。 +SELECT sal*12 年工资 FROM emp ORDER BY 年工资; +-- +``` \ No newline at end of file