diff --git "a/47 \346\250\212\345\260\217\351\203\255/20231019 \346\225\260\346\215\256\345\272\223\351\253\230\347\272\247\344\272\213\345\212\241.md" "b/47 \346\250\212\345\260\217\351\203\255/20231019 \346\225\260\346\215\256\345\272\223\351\253\230\347\272\247\344\272\213\345\212\241.md" new file mode 100644 index 0000000000000000000000000000000000000000..a838ca2efec2c0aa43482319314bbb2a3ccab4af --- /dev/null +++ "b/47 \346\250\212\345\260\217\351\203\255/20231019 \346\225\260\346\215\256\345\272\223\351\253\230\347\272\247\344\272\213\345\212\241.md" @@ -0,0 +1,112 @@ +# 笔记 + +### 什么是事务? + +事务指的是一个操作序列,该操作序列中的多个操作要么都做,要么都不做,是一个不可分割的工作单位,是数据库环境中的逻辑工作单位,由DBMS(数据库管理系统)中的事务管理子负者事务的处理 + +### 事务的特性 + +事务处理可以确保除非事务性序列内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的序列,可以简化错误恢复并使应用程序更加可靠 + +但不是所有的操作序列都可以称为事务,这是因为一个操作序列要成为事务,必须满足事务的原子性、一致性、隔离性和持久性。这四个特性简称为ACID特性 + +### 事务的四个特性 + +1.原子性:事务中的所有操作可以看做一个原子(自然界最小的颗粒,具有不可再分的特性),事务是应用中不可再分的最小的逻辑执行体。使用事务对数据进行修改的操作序列,要么全部执行,要么全不执行 + +2.一致性:是指事务执行的结果必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库中只能包含事务成功提交的结果时,数据库处于一致性状态。一致性是通过原子性来保证的 + +例如:在转账时,只有保证转出和转入的金额一致才能构成事务。也就是说事务发生前和发生后,数据的总额依然匹配 + +3.隔离性:是指各个事务的执行互不干扰,任意一个事务的内部操作对其他并发的事务都是隔离的。也就是说:并发执行的事务之间既不能看到对方的中间状态,也不能相互影响 + +例如:在转账时,只有当A账户中的转出和B账户中转入操作都执行成功后才能看到A账户中的金额减少以及B账户中的金额增多。并且其他的事务对于转账操作的事务是不能产生任何影响的 + +4.持久性:持久性指事务一旦提交,对数据所做的任何改变,都要记录到永久存储器中,通常是保存进物理数据库,即使数据库出现故障,提交的数据也应该能够恢复。但如果是由于外部原因导致的数据库故障,如硬盘被损坏,那么之前提交的数据则有可能会丢失 + +### 事务并发问题 + +脏读(Dirty read):当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是"脏数据",依据"脏数据"所做的操作可能是不正确的 + +不可重复读(Unrepeatableread):指在一个事务内多次读同一个数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况。因此称为不可重复读 + +幻读(Phantom read):幻读与不可重复读类似。它发生在一个事务读取了几行数据,接着另一个并发事务插入了一些数据时。在随后的查询中,第一个事务就会发现多了一些原本吧存在的记录,就好像发生了幻觉一样,所以称为幻读 + +串行 + + + +# 作业 + +```mysql +create database db_emp charset utf8; +use db_emp; +-- 部门表 +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 job,sal from emp where sal>1500; +-- 方法二 + select job,MIN(sal) over(partition by job order by sal) from emp where sal>1500; +-- 2、列出在部门 "销售部" 工作的员工的姓名,假定不知道销售部的部门编号。 + select ename from emp where emp.deptno = (select deptno from dept where dept.dname='销售部'); +-- 3、列出薪金高于公司平均薪金的所有员工。 + select ename,sal from emp where sal>(select 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 * from emp where sal>(select MAX(sal) from emp where deptno=30); +-- 7、列出在每个部门工作的员工数量、平均工资、平均服务年限。 + select COUNT(*) 员工数量,AVG(sal) 平均工资,AVG(DATEDIFF(CURRENT_DATE,hiredate)) 平均服务年限 from emp group by deptno; +-- 8、列出所有员工的姓名、部门名称和工资。 + select ename,dname,sal from emp left join dept on emp.deptno=dept.deptno; +-- 9、列出所有部门的详细信息和部门人数。 + -- select * from dept left join (select count(*),deptno from emp group by deptno) e on +-- 10、列出各种工作的最低工资。 + select distinct job,MIN(sal) over(partition by job) from emp; +-- 11、列出各个部门的 经理 的最低薪金。 +-- 1、查出各个部门的经理 + select * from emp where job='经理' +-- 2、查出最低薪资 + select MIN(sal) from emp; +-- 3、最后一步 + select * from emp where (select MIN(sal) from emp where job ='经理' group by deptno) left join dept on emp.deptno=dept.deptno ; + +-- 12、列出所有员工的年工资,按年薪从低到高排序。 + select ename 员工姓名,sal*12 年薪 from emp; \ No newline at end of file