数据库【只写自己认为重要的部分】
文章目录
- 数据库基本原理
- 一.事务
- 1. 回滚与事务
- 2. 事务的特性(ACID)
- 3. 多个事务并发运行带来的问题
- 4. 事务隔离级别
- 5. 封锁技术解决并发问题
- 二. 数据库的 三大设计范式
- 三. MySQL基本操作
- 1. 数据库操作
- 2. 表操作
- 3. 操作表中的数据【增删改】
- 4. 查
- 5. 视图
- 四. MySQL 约束建表
- 五. 数据库存储引擎
- 六. 索引
- 1. 索引数据结构
- 2. B树和B+树
- 3. Hash索引和B+树索引
- 4. 联合索引
- 5. 聚集索引与非聚集索引
- 七. 索引代码描述:
- 1. ALTER TABLE
- 2. CREATE INDEX
- 3. 删除索引
- 4. 查看索引
- 八. 锁
- 1. 表级锁(共享锁和排他锁)
- 2. 行级锁
- 九. 锁代码
- 1. MyISAM表级锁模式
- 2. InnoDB锁模式:
- 十. 存储过程
- 十一. 触发器
数据库基本原理
一.事务
在执行SQL语句的时候,某些业务要求,一系列操作必须全部执行,而不能仅执行一部分。例如转账的语句,两条SQL语句必须全部执行,或者,由于某些原因,如果第一条语句成功,第二条语句失败,就必须全部撤销。
这种把多条语句作为一个整体进行操作的功能,被称为数据库事务。数据库事务可以确保该事务范围内的所有操作都可以全部成功或者全部失败。如果事务失败,那么效果就和没有执行这些SQL一样,不会对数据库数据有任何改动。
这种把多条语句作为一个整体进行操作的功能,被称为数据库事务。要么都执行,要么都不执行。
事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。
1. 回滚与事务
在 MySQL 中,事务的自动提交状态默认是开启的。
那么,默认事务开启的作用是什么?
当我们去执行一个sql语句的时候,效果会立即体现出来,且不能回滚。
什么是回滚rollback;
?所谓回滚的意思就是,撤销执行过的所有 SQL 语句,使其回滚到最后一次提交数据时的状态。
我们可以通过设置默认事务为0的方式来进行改变,也就是设置mysql默认提交为false ,set autocommit=0;
(1为开启,0为关闭)
set autocommit=0;
则表示将事务自动提交关闭了。
尝试回滚操作:发现虽然我们能够看到自己操作的数据发生了变化,但是一旦我们执行rollback;
操作,就会发现,数据回到了你的上一次操作,说明我们没有真正的操作数据库,得到的只是一张虚拟的表。
如果我们操作数据以后,执行commit
,这时在执行rollback;
,无法回到操作数据库之前的状态了,说明手动提交以后,不能进行回滚了。只要commit了,rollback也没有用了。
事务开启后,一旦 commit 提交,就不可回滚(也就是这个事务在提交的时候结束了),此时再rollback也没有用了
2. 事务的特性(ACID)
- 原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
- 一致性: 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
- 隔离性: 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
- 持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。事务满足持久化是为了能应对系统崩溃的情况。
3. 多个事务并发运行带来的问题
在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对统一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题:
- 脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
- 丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
- 不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。不可重复读(虚读): 指一个线程中的事务读取到了另外一个线程中提交的update的数据,导致了产生不同于刚才的结果。
- 幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
不可重复度和幻读区别:
不可重复读的重点是修改,幻读的重点在于新增或者删除。
例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读。
例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读。
4. 事务隔离级别
SQL 标准定义了四个隔离级别:
- READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
- REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
隔离级别越高,性能越差:
read uncommitted > read committed > repeatable read > serializable
mysql默认隔离级别是repeatable read
5. 封锁技术解决并发问题
为了解决并发问题,数据库系统引入锁机制。
基本的封锁类型有两种: 排它锁(Exclusive locks 简记为X锁) 和 共享锁(Share locks 简记为S锁)。
- 排它锁又称为写锁X。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其它事务在T释放A上的锁之前不能再读取和修改A。
- 共享锁又称为读锁S。若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其它事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其它事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
**其实事务的隔离级别正是三级封锁协议的体现或运用。**怎么说呢,为了提高性能,我们会希望数据库能并行执行我们提交的所有事务,但并行执行事务会带来一系列问题,比如我们之前提到过的脏读,不可重复读,幻读等问题。为了解决这些问题,MySQL事务提出了4个不同的隔离级别,而这些隔离级别的实现本质上就是通过加锁,解锁来实现的。那么我们该何时加锁,占锁多长时间,何时解锁呢?有三种协议:
- 一级封锁协议:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK)。 一级封锁协议可以防止丢失修改,并保证事务T是可恢复的。使用一级封锁协议可以解决丢失修改问题。在一级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,它不能保证可重复读和不读“脏”数据。
- 二级封锁协议:在一级封锁协议之上,事务T在读取数据R之前必须先对其加S锁,读完后方可释放S锁。 二级封锁协议除防止了丢失修改,还可以进一步防止读“脏”数据。但在二级封锁协议中,由于读完数据后即可释放S锁,所以它不能保证可重复读。
- 三级封锁协议 :在一级封锁协议之上,事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。 三级封锁协议除防止了丢失修改和不读“脏”数据外,还进一步防止了不可重复读。
二. 数据库的 三大设计范式
- 第一范式: 数据中所有字段都是不可分割的原子值。
强调的是列的原子性,即列不能够再分成其他几列。 - 第二范式:首先是 1NF,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。
在满足第一范式的前提下,其他列都必须完全依赖于主键列。如果出现不完全依赖,只可能发生在联合主键的情况下。 - 第三范式:必须满足第二范式,除主键列的其他列之间不能有传递依赖关系。
三. MySQL基本操作
增删改主要参考博客1
查询主要参考博客2
内连接外连接主要参考博客3
打开数据库:以管理员身份打开dos窗口,然后执行:net start mysql
关闭数据库则是:net stop mysql
进入数据库基本操作:
cd到数据库的bin文件。然后执行 mysql -hlocalhost -uroot -p密码
1. 数据库操作
显示数据库中的数据:mysql> show databases;
选中了这个数据库:use test;
创建数据库:create databases test
删除数据库 :drop databases test;
2. 表操作
显示表:show tables;
查看表内容,列情况:describe pet;
创建表:CREATE TABLE table_name (column_name column_type);
eg:
create table student( -> snumber varchar(20) primary key,-> sname varchar(20) not null,-> ssex varchar(20) not null,-> sbirthday datetime,-> class varchar(20)-> );
3. 操作表中的数据【增删改】
增:INSERT INTO+表名+values+(数据字段)
删:delete from + 表 + where name=’ 要删除的数据
改:update pet set sex='男' where name='蔡坤';
4. 查
distinct: 相同值只出现一次
mysql> select distinct depart from teacher;
limit: 限制返回行数
mysql> select * from score limit 2,3 ;
返回3–5行数据排序: asc升序(默认) desc降序,可以按多个列进行排序,并且每个列指定不同的排序方式。
mysql> select * from score order by cnumber asc
过滤: >= <= between…and…
mysql> select * from score where degreebetween 60 and 80;
匹配符:% 匹配大于等于0任意字符 like模糊查询
cnumber like '3%';
函数: avg求平均,max求最大值
select cnumber,avg(degree) from score
分组: group by… 或者group by… having…
select cnumber,avg(degree) from score group by cnumber;
mysql> select cnumber from score group by cnumber having count(cnumber)>=2;
子查询: 嵌套select语句叫子查询
mysql> select snumber,cnumber from score where degree=(select max(degree) from score);
多表查询:
mysql> select sname,cnumber,degree from student,score where student.snumber=score.snumber;#加上限制条件,不然会乱
连接:
内连接:inner join
外连接:left join ; right join;
select * from person inner join card on person.cardid=card.id;
mysql> select * from person left join card on person.cardid=card.id;
组合查询: union
select * from person left join card on person.cardid=card.id-> union-> select * from person right join card on person.cardid=card.id;
5. 视图
- 为什么需要视图:
不同的人职位看到不同的数据范围,这就可以用到视图。 - 什么是视图:
- 视图是从一个或者多个表导出的,视图的行为与表非常相似,但视图是一个虚拟表。
(1)表示一张表的部分数据或多张表的综合数据
(2)其结构和数据是简历在堆表的查询基础上 - 视图中不存放数据
数据存放在视图所引用的原始表中。 - 一个原始表,根据不同用户的不同需求,可以创建不同的视图。
- 视图的用途:
筛选表中的行;
放置未经许可的用户访问敏感数据;
降低数据库的复杂度;
将多个物理数据库抽象为一个逻辑数据库 - 语法:
创建视图格式:create view 视图名 as select 语句
删除视图:drop view 视图名
使用视图(和使用表一样):select * from 视图名
在视图中可以使用select语句查询数据,以及使用insert、update和delete语句修改记录。但是,为了安全考虑,一般开发中只是用作视图查询。
四. MySQL 约束建表
约束包括:(主键约束、自增约束),(外键约束),(唯一约束),(非空约束),(默认约束)
参考博客
五. 数据库存储引擎
MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能。 存储引擎其实就是数据库的底层,它决定了数据库中的数据以什么样的结构存储在计算机硬盘中,如何为数据库的数据建立索引,以及在查询和更新数据的时候需要有各自的实现方法,比如查询更新数据库时使用的锁不同,锁定整个表或者只锁定那一行数据等等…
存储引擎说白了就是
- 如何存储数据
- 如何为存储的数据建立索引和如何更新
- 查询数据等技术的实现方法。
因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和操作此表的类型)。
不同的存储引擎在计算机中有不同的存储数据的方法,也会有不同建立索引的方法,更新查找数据的实现方法也是不同的。不同的存储引擎数据在计算机中存储肯定是不同的形式。
mysql 有多种存储引擎,目前常用的是 MyISAM 和 InnoDB 这两个引擎,除了这两个引擎以外还有许多其他引擎。
- MyISAM
(1)MyISAM 是 mysql 5.5.5 之前的默认引擎,它支持 B-tree/FullText/R-tree 索引类型。
(2)锁级别为表锁,表锁优点是开销小,加锁快;缺点是锁粒度大,发生锁冲动概率较高,容纳并发能力低,这个引擎适合查询为主的业务。
(3)此引擎不支持事务,也不支持外键。
(4)MyISAM 强调了快速读取操作。它存储表的行数,于是 SELECT COUNT (*) FROM TABLE 时只需要直接读取已经保存好的值而不需要进行全表扫描。 - InnoDB
(1)InnoDB 存储引擎最大的亮点就是支持事务,支持回滚,它支持 Hash/B-tree 索引类型。
(2)锁级别为行锁,行锁优点是适用于高并发的频繁表修改,高并发是性能优于 MyISAM。缺点是系统消耗较大,索引不仅缓存自身,也缓存数据,相比 MyISAM 需要更大的内存。
(3)InnoDB 中不保存表的具体行数,也就是说,执行 select count (*) from table 时,InnoDB 要扫描一遍整个表来计算有多少行。
(4)支持事务,支持外键。
如何选择:
- 是否要支持事务,如果要请选择 InnoDB,如果不需要可以考虑 MyISAM;
- 如果表中绝大多数都只是读查询,可以考虑 MyISAM,如果既有读写也挺频繁,请使用InnoDB。
- 系统奔溃后,MyISAM恢复起来更困难,能否接受,不能接受就选 InnoDB;
- MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的。如果你不知道用什么存储引擎,那就用InnoDB,至少不会差。
六. 索引
索引基础知识参考
主键索引和辅助索引的区别(MyISAM和InnoDB)
- 什么情况下建立索引:
- 定义主键的时候一定建立索引
- 定义外键的时候一定建立索引
- 对于经常要查询的数据列要建立索引
- 对于需要在指定范围内的快速或者频繁查询的数据列
- 经常用WHERE子句中的数据列
- 经常出现在关键字order by、group by、distinct后面的字段
- 对于经常存取的列避免建立索引
- 对于定义为text、image和bit的数据类型的列不要建立索引
- 对于查询中很少涉及到的列或者有大量重复的列不要建立索引
- 索引类型
从存储的物理结构来分:
聚簇索引:
聚簇索引的叶子节点就是数据节点,聚簇索引对磁盘上的实际数据组织以按照特定的一个或多个列的值排序的算法,特点是存储的顺序和索引顺序一致(因为叶子结点中索引和数据绑定在一起),一般情况下主键会默认生成聚簇索引,且一张表只有一个聚簇索引。InnoDB使用的是聚簇索引。
非聚簇索引:
非聚簇索引将数据存储与索引分开存储,索引结构的叶子节点指向了数据的位置,所以要进行二次索引,数据的存储顺序和索引不一致。查询速度比聚簇索引慢。MyISAM使用的就是非聚簇索引。
从逻辑上来分:
主键索引(primary key):定义主键时自动创建主键索引,该数据列不许重复,不许为NULL
唯一索引(unique):数据列不允许重复,允许为NULL
普通索引(index):没有唯一性的限制;
联合索引:MySQL中可以同时使用多个字段同时建立一个索引,叫做联合索引,如果想要命中该索引,必须按照创建索引时的字符顺序挨个使用,否则无法命中。在多个字段中建立的索引提高符合查询的速度;
原因:MySQL中使用索引时需要索引有序,如建立了索引a, b, c那么排序就先用a来排序,然后b,c,所以进行查询时,此时只针对a严格有序,所以要注意顺序。
全文索引:是目前搜索引擎中使用的一种关键技术。
索引是一种用于快速查询和检索数据的数据结构。常见的索引结构有: B树, B+树和Hash。
索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引。
索引的作用就相当于目录的作用。打个比方: 我们在查字典的时候,如果没有目录,那我们就只能一页一页的去找我们需要查的那个字,速度很慢。如果有目录了,我们只需要先去目录里查找字的位置,然后直接翻到那一页就行了。
索引的优点
可以大大加快 数据的检索速度(大大减少的检索的数据量), 这也是创建索引的最主要的原因。毕竟大部分系统的读请求总是大于写请求的。另外,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。索引的缺点
创建索引和维护索引需要耗费许多时间:当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低SQL执行效率。
占用物理存储空间 :索引需要使用物理文件存储,也会耗费一定空间。
1. 索引数据结构
- 不用索引:
数据库表时存储在磁盘中的。如果不用索引时查找数据要一行一行比对,如果数据成千上万,每一次比对都要经过一个io磁盘交换,既浪费时间也浪费io磁盘的寿命。 - 搜索二叉树:
这样查询经过2次就查询得到,但是如果索引是连续的1–2--3–4--5–6这种情况下,二叉树就会退化成链表,这样查询数据和不用索引一样,也要逐个比对了。 - 红黑树:
红黑树是一种平衡树,每次自动调整树,保证左子树和右子树高度差变小,解决上面问题。但是有新的问题,就是,海量数据时,树的高度可能很高,这样数以千万的数据还是要经过很多次io磁盘交换。 - 所以考虑横向扩宽,利用B树和B+树。
2. B树和B+树
B树:
(1) 所有键值分布在整颗树中(索引值和具体data都在每个节点里);
(2)任何一个关键字出现且只出现在一个结点中;
(3)搜索有可能在非叶子结点结束(最好情况O(1)就能找到数据);
(4)在关键字全集内做一次查找,性能逼近二分查找;B+树:
B+树最大的特点就是:是一种排好序的数据结构。
为什么B+树比B树更适合做索引?
(1)B+树磁盘读写代价更低
B+的内部结点并没有指向关键字具体信息的指针,即内部节点不存储数据。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
(2)B+tree的查询效率更加稳定
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
(3)B树中每个节点的关键字都有data域,而B+树除了叶子节点,其他节点只有索引,也就是说同样的磁盘页B+树可以容纳更多的节点。
3. Hash索引和B+树索引
Hash索引定位快
Hash索引指的就是Hash表,最大的优点就是能够在很短的时间内,根据Hash函数定位到数据所在的位置,这是B+树所不能比的。Hash冲突问题
知道HashMap或HashTable的同学,相信都知道它们最大的缺点就是Hash冲突了。不过对于数据库来说这还不算最大的缺点。Hash索引不支持顺序和范围查询(Hash索引不支持顺序和范围查询是它最大的缺点。
试想一种情况:
SELECT * FROM tb1 WHERE id < 500;
B+树是有序的,在这种范围查询中,优势非常大,直接遍历比500小的叶子节点就够了。而Hash索引是根据hash算法来定位的,难不成还要把 1 - 499的数据,每个都进行一次hash计算来定位吗?这就是Hash最大的缺点了。
4. 联合索引
先按照第一个字段排序,第一个字段相同然后按照第二个字段排序,同理往下。所以:
这三条SQL语句,哪一个语句会走索引?
只有第一条会走索引,后两个为什么不走索引?
因为:假设看第二个语句,查询的是age=30,发现由于没有第一个name索引,去除name,发现age根本不是排好序的,所以查找起来不能够利用索引排好序按序查找。只能全表查找。
5. 聚集索引与非聚集索引
- 聚集索引:
聚集索引即索引结构和数据一起存放的索引。主键索引属于聚集索引。
在 Mysql 中,InnoDB引擎的表的 .ibd文件就包含了该表的索引和数据,对于 InnoDB 引擎表来说,该表的索引(B+树)的每个非叶子节点存储索引,叶子节点存储索引和索引对应的数据。
聚集索引的优点
聚集索引的查询速度非常的快,因为整个B+树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。
聚集索引的缺点
(1)依赖于有序的数据 :因为B+树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或UUID这种又长又难比较的数据,插入或查找的速度肯定比较慢。
(2)更新代价大 : 如果对索引列的数据被修改时,那么对应的索引也将会被修改, 而且况聚集索引的叶子节点还存放着数据,修改代价肯定是较大的, 所以对于主键索引来说,主键一般都是不可被修改的。 - 非聚集索引
非聚集索引即索引结构和数据分开存放的索引。
MYISAM引擎的表的.MYI文件包含了表的索引, 该表的索引(B+树)的每个叶子非叶子节点存储索引, 叶子节点存储索引和索引对应数据的指针,指向.MYD文件的数据。
非聚集索引的叶子节点并不一定存放数据的指针, 因为二级索引的叶子节点就存放的是主键,根据主键再回表查数据。
非聚集索引的优点
更新代价比聚集索引要小 。非聚集索引的更新代价就没有聚集索引那么大了,非聚集索引的叶子节点是不存放数据的
非聚集索引的缺点
(1)跟聚集索引一样,非聚集索引也依赖于有序的数据
(2)可能会二次查询(回表) :这应该是非聚集索引最大的缺点了。 当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。 - 非聚集索引一定回表查询吗(覆盖索引)?
非聚集索引不一定回表查询。
想一种情况,用户准备使用SQL查询用户名,而用户名字段正好建立了索引。
SELECT name FROM table WHERE username='guang19';
那么这个索引的key本身就是name,查到对应的name直接返回就行了,无需回表查询。
七. 索引代码描述:
从逻辑上来分:
主键索引
唯一索引
普通索引
联合索引
全文索引
举一个简单例子帮助理解:
本例演示如何创建名为 "Person"
的表,有四个列。列名是:"LastName"、"FirstName"、"Address" 以及 "Age"
:
CREATE TABLE Person
(
LastName varchar(30),
FirstName varchar,
Address varchar,
Age int(3)
)
建立一个简单索引:
CREATE INDEX 索引名称
ON 表名称 (列名称)
索引名称:自己随便起名字,下面的index_name都可以自己替换成自己想要的名字。
“列名称” 规定你需要索引的列。
table_name:下面的table_name表示表的名字。
具体简历一个索引的例子:
CREATE INDEX PersonIndex
ON Person (LastName)
1. ALTER TABLE
ALTER TABLE
用来创建普通索引、unique索引或者primary key索引。
- 主键索引:即主索引,根据主键pk_clolum(length)建立索引,不允许重复,不允许空值
ALTER TABLE 'table_name' ADD PRIMARY KEY pk_index('col');
- 唯一索引:用来建立索引的列的值必须是唯一的,允许空值
ALTER TABLE 'table_name' ADD UNIQUE index_name('col');
- 普通索引:用表中的普通列构建的索引,没有任何限制
ALTER TABLE 'table_name' ADD INDEX index_name('col');
- 全文索引:用大文本对象的列构建的索引
ALTER TABLE 'table_name' ADD FULLTEXT INDEX ft_index('col');
- 组合索引:用多个列组合构建的索引,这多个列中的值不允许有空值
ALTER TABLE 'table_name' ADD INDEX index_name('col1','col2','col3');
2. CREATE INDEX
CREATE INDEX
可以创建普通索引和UNIQUE索引。
- 普通索引:
CREATE INDEX index_name ON table_name (column_list)
- 唯一索引:
CREATE UNIQUE INDEX index_name ON table_name (column_list)
3. 删除索引
可利用ALTER TABLE或DROP INDEX语句来删除索引。
DROP INDEX index_name ON talbe_name
ALTER TABLE table_name DROP INDEX index_name
ALTER TABLE table_name DROP PRIMARY KEY
- 前两条语句是等价的,删除掉table_name中的索引index_name。
- 第3条语句只在删除PRIMARY KEY索引时使用,因为一个表只可能有一个PRIMARY KEY索引,因此不需要指定索引名。如果没有创建PRIMARY KEY索引,但表具有一个或多个UNIQUE索引,则MySQL将删除第一个UNIQUE索引。
- 如果从表中删除了某列,则索引会受到影响。对于多列组合的索引,如果删除其中的某列,则该列也会从索引中删除。如果删除组成索引的所有列,则整个索引将被删除。
4. 查看索引
show index from tblname;
show keys from tblname;
八. 锁
1. 表级锁(共享锁和排他锁)
- 表级锁是 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分 MySQL 引擎支持。最常使用的 MyISAM 与 InnoDB 都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。
- 特点
开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。 - 共享锁
共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
假设开启两个session操作同一个数据库,分别将默认的commit取消,自己进行commit观察加锁之后的结果。
session1对一个表加了表锁,然后session1 可以读刚才锁的那个表,但不可以写那个表,也不可以读其他表了。
由于表锁是共享锁,所以session2可以查session1锁的那个表,也可以查看其他表,但是不能改刚才session1的锁的那个表,会出现阻塞,系统性能很慢。session1一旦解锁,session2立马不在阻塞。 - 排它锁
排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
session1对一个表加上写锁,可以读自己锁的表,可以写自己锁的表,不可以读其他表。
session2不可以读session1锁的写锁,写就更不可以了,都会进入进入阻塞状态。
对MyISAM表进行表操作,会有以下情况:
(1)对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其他进程的写操作。
(2)对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当读锁释放后,才会执行其他进程的读写操作。
简而言之,就是读锁会阻塞写,但不会阻塞读。而写锁会把读写都阻塞。
2. 行级锁
行级锁是MySQL中粒度最小的一种锁,他能大大减少数据库操作的冲突。但是粒度越小,实现的成本也越高。MYISAM引擎只支持表级锁,而INNODB引擎能够支持行级锁,也支持表级锁。下面的内容也是针对INNODB行级锁展开的。
INNODB的行级锁有 共享锁(S LOCK)和排他锁(X LOCK) 两种。
共享锁允许事物读一行记录,不允许任何线程对该行记录进行修改。
排他锁允许当前事物删除或更新一行记录,其他线程不能操作该记录。
当session1修改第4行数据以后,没有commit,session2也修改第4行数据,发现会发生阻塞。 阻塞:是因为session1在修改那一行呢,session2也在修改,但是由于行锁,1在改,2就不能在改了,只能阻塞。当1改完并提交以后,意味着释放行锁了,2才能继续修改。
但是如果1修改的是第4行数据,然而2修改的是第9行数据,那么即便1没有提交,也不影响2修改第9行数据,因为行锁只锁定操作的那一行。行锁变表锁:
本来你修改4,我修改9不相互影响,但是由于,你vachar类型写错了,应该写’4000’,你写成了4000,忘记加引号了,导致索引失效,所以行锁变表锁,9那里在修改就发生了阻塞。间隙锁:
左侧按理来说只是修改3 4 5 的值,本身没有2,按理来说右侧可以增加2这个数据,但是右侧却不能增加2,发生阻塞。这是因为差生间隙锁。
数据库锁的用法
https://blog.csdn.net/u010708759/article/details/77864439
九. 锁代码
锁代码参考、
1. MyISAM表级锁模式
- 表共享读锁 (Table Read Lock):不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;
- 表独占写锁 (Table Write Lock):会阻塞其他用户对同一表的读和写操作;
MyISAM 在执行查询语句(SELECT)
前,会自动给涉及的表加读锁。
在执行更新操作(UPDATE、DELETE、INSERT 等)
前,会自动给涉及的表加写锁。
这个过程并不需要用户干预,因此,用户一般不需要直接用 LOCK TABLE 命令给 MyISAM 表显式加锁。
2. InnoDB锁模式:
InnoDB 实现了以下两种类型的行锁:
- 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
- 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
(1)对于 UPDATE、 DELETE 和 INSERT 语句, InnoDB会自动给涉及数据集加排他锁(X);
(2)对于普通 SELECT 语句,InnoDB 不会加任何锁;
(3)显示加锁:
select ... lock in share mode //共享锁
select ... for update //排他锁
for update 和 lock in share mode 的区别:
前一个上的是排他锁(X 锁),一旦一个事务获取了这个锁,其他的事务是没法在这些数据上执行 for update ;后一个是共享锁,多个事务可以同时的对相同数据执行 lock in share mode。
十. 存储过程
完全参考即可:博主是总结B栈视频课程
- 定义:简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法。
- 优点
- 提高代码的重用性
- 简化操作
- 减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率
delimiter
命令定义结束符,取代分号
参考- 存储过程创建
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN# 存储过程体(一组合法的SQL语句)
END
- 调用
CALL 存储过程名(实参列表);
- 删除
如果存在该存储过程 则删除该存储过程。
drop procedure if exists 存储过程名称
- set设置变量以及DECLARE
局部变量和全局变量参看 - 流程控制结构-----IF语句
IF结构最后都需要END IF;结尾。 - CASE------变为:when 值1 then 语句1;
- 循环结构
while:先判断后执行。leave跳出循环
repeat :先执行后判断
loop:简单死循环。(相当于while(true))
十一. 触发器
- 触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。
触发器的这种特性可以协助应用在数据库端确保数据的完整性,比如现在有一个学生表,当有一个学生入学后,就需要在学生表中插入创建的数据,如果在不适用触发器的情况下,对于数据是否正确就需要使用高级程序语言进行控制,比如JDBC中要通过java语句自己控制,但是如果定义一个触发器,触发器的作用就是当学生表中插入一条数据是检查数据是否正确,如果不正确就不会进行插入。在触发器中可以对表进行常规操作。 - 触发器:在指定表上,(insert(插入)、update(跟新)、delete(删除))事件动作,触发(After(之后)时机,Before(之前)),执行指定的一群或一个sql语句。
- after 和before
- after:是数据库表记录操作之后再触发,先进行数据的增/删/改操作,再触发,触发器无法影响前面的增/删/改操作。
- before:是数据库表记录操作之前就触发,再进行数据的增/删/改操作,触发器可以影响后面的增/删/改操作。
- new和old关键字
NEW与OLD关键字:该关键字,表示触发了触发器的那一行数据。
- INSERT触发器中,
NEW
用来表示将要(BEFORE)或已经(AFTER)插入的新数据。 - DELETE触发器中,
OLD
用来表示将要或已经被删除的原数据。 - UPDATE触发器中,
OLD
用来表示将要或已经被修改的原数据,NEW
用来表示将要或已经修改为的新数据。 - 使用方法
NEW.columnName
(columnName为相应数据表某一列名)
另外,OLD
是只读的,而NEW
则可以在触发器中使用SET
赋值,这样不会再次触发触发器,造成循环调用(如每插入一个学生前,都在其学号前加“2013”)。
- 几个案例:
(1)在表t_persons上创建insert触发器,当学生数据插入后就给t_courses表插入一条记录(为这个新入学的学生分配课程)
delimiter //
CREATE tigger g_afterinsert_persons
AFTER INSERT
ON t_persons for EACH ROW
BEGIN
INSERT INTO courses(Name,Score,UserId) VALUES('入学教育',0,new.ID);
END;
//
(2)在表t_persons上创建update触发器,当学生数据更新后,判断学生的姓名是否为特别关注的学生,如果是那么久把这个学生的成绩所有课程的成绩都更新为0。
delimiter //
CREATE tigger g_afterUpdate_persons
AFTER UPDATE
ON t_persons for EACH ROW
BEGIN
if old.Name = '张三' THEN
UPDATE courses set score = 0 wher userId = old.id;
end if;
END;
//
(3)在表t_persons上创建delete触发器,当学生记录被删除后,就删除课程表中对应的学生记录。
delimiter //
CREATE tigger g_afterDelete_persons
AFTER DELETE
ON t_persons for EACH ROW
BEGIN
DELETE FROM t_courses where UserId = old.Id;
END;
//
(4)在表t_persons上创建insert触发,在学生记录插入之前检查数据是否符合规定。
delimiter //
CREATE tigger g_beforeInsert_persons
AFTER INSERT
ON t_persons for EACH ROW
BEGIN
if length(new.Name) <3 then
SET new.Name = '插入的姓名的长度不能小于3';
END IF;
END;
//
数据库【只写自己认为重要的部分】相关推荐
- 宁愿“大小周”、每天只写 200 行代码、月薪 8k-17k 人群再涨!揭晓中国开发者真实现状...
作者 | 郑丽媛 出品 | CSDN(ID:CSDNnews) 程序员,一个圈外人羡慕.圈内人喊苦的"神奇"职业--高薪.福利好是旁人羡慕的理由,高压.加班多却也是他们最常见的写照 ...
- 读数据库遇到空就进行不下去_如何解决高并发场景下缓存+数据库双写不一致问题?...
推荐阅读: 一只Tom猫:手撕分布式技术:限流.通讯.缓存,全部一锅端走送给你!zhuanlan.zhihu.com 一只Tom猫:MySQL复习:20道常见面试题(含答案)+21条MySQL性能调 ...
- session.merge 缓存不更新_如何保证缓存与数据库双写时的数据一致性?
在做系统优化时,想到了将数据进行分级存储的思路.因为在系统中会存在一些数据,有些数据的实时性要求不高,比如一些配置信息.基本上配置了很久才会变一次.而有一些数据实时性要求非常高,比如订单和流水的数据. ...
- 宁愿“大小周”、每天只写 200 行代码、月薪 8k-17k 人群再涨 | 揭晓中国开发者真实现状
作者 | 郑丽媛 出品 | CSDN(ID:CSDNnews) 程序员,一个圈外人羡慕.圈内人喊苦的"神奇"职业--高薪.福利好是旁人羡慕的理由,高压.加班多却也是他们最常见的写照 ...
- Reids面试题集合 数据结构+穿透雪崩+持久化+内存淘汰策略+数据库双写+哨兵
问题1 你对redis有什么了解? 简单的来说redis 就是一个数据库不同的是redsi的数据是存在内存中的,所以读写速度非常快因此,redis被广泛运用到缓存,另外redis也用来做分布式锁,re ...
- 掌握分布式环境缓存更新策略,提高缓存与数据库双写一致性!
概述 随着时代的发展,服务系统架构也已经由最初的单体架构转变为分布式.微服务架构模式. 从数据体量上来看,各系统存储的数据量越来越大,数据的查询性能越来越低. 此时,就需要我们不断的进行优化,最常用的 ...
- Redis缓存穿透-热点缓存并发重建-缓存与数据库双写不一致-缓存雪崩
解决缓存问题 1.解决Redis把内存爆满的三种方法 1.1 定期删除 1.2 惰性删除 1.3 内存淘汰策略 2. 缓存穿透--缓存击穿--缓存雪崩 3. 如何解决线上缓存穿透问题 3.1 缓存击穿 ...
- 高并发下缓存与数据库双写不一致解决方案
高并发下缓存与数据库双写不一致解决方案 参考文章: (1)高并发下缓存与数据库双写不一致解决方案 (2)https://www.cnblogs.com/wlwl/p/11601632.html (3) ...
- 教你从0到1搭建秒杀系统-缓存与数据库双写一致
本文是秒杀系统的第四篇,我们来讨论秒杀系统中缓存热点数据的问题,进一步延伸到数据库和缓存的双写一致性问题. 在秒杀实际的业务中,一定有很多需要做缓存的场景,比如售卖的商品,包括名称,详情等.访问量很大 ...
- 一套代码编译出ios和android,Hippy: Hippy 是一个新生的跨端开发框架,目标是使开发者可以只写一套代码就直接运行于三个平台(iOS、Android 和 Web)...
Hippy 跨端开发框架 介绍 Hippy 是一个新生的跨端开发框架,目标是使开发者可以只写一套代码就直接运行于三个平台(iOS.Android 和 Web).Hippy 的设计是面向传统 Web 开 ...
最新文章
- 蓝桥杯:基础练习 特殊的数字
- Vue 模板语法 插值操作 绑定属性 计算属性 事件监听 条件判断 循环遍历 阶段案例
- 我的编程之路(二十五) 上海的老同学
- sklearn之Pipeline 估计器
- java multibox_月光软件站 - 编程文档 - Java - Struts 中 Multibox 的用法
- 基于JavaWeb的企业出差费用报销管理系统设计与实现
- 缺少JAVA环境,无法运行软件解决办法
- 【spring cloud】(四)服务网关——gateway
- 库文件 c语言 编译器,抽取VS文件组成类GCC的编译器,并编译C程序为dll动态链接库...
- 在window中nginx安装腾讯云ssl报错nginx: [emerg] cannot load certificate
- Java HotSpot虚拟机提高性能,做了哪些操作
- css 心形动画 爱心动画
- 升级!鹏业云计价i20(西藏)软件V11.0.27版本
- 程序员缓解职业病的秘方
- 装linux系统的工具箱,PE,Dos工具箱,自动安装linux的U盘制作
- [数据结构] python 单链表的创建
- cakephp mysql_攻克CakePHP系列一 连接MySQL数据库
- JDK8 HashMap源码
- Oralce数据库的详解解析(包括操作步骤)【1】
- 单机版(新手教学)理发店管理系统
热门文章
- ELK搭建开源日志系统(window版本)—图文详细
- spring事务详解
- 计算机文件丢失系统无法启动,电脑由于系统注册文件丢失无法启动系统 用安全模式也进不去。怎么办?...
- 用ajax提交表单给数据库,如何利用ajax提交form表单到数据库
- 王艾老哥---余生很长,何必慌张。不做鳏寡孤惸之人。
- 麦肯锡给CEO的元宇宙指南
- python使用you-get批量下载网站视频
- 智能车摄像头组 障碍处理方法
- android sdk快速下载,Android SDK Manager 快速下载的方法!
- 超简单,人人都能弄明白的 6 种限流实现方案