目录
数据库四大特性
原子性:事务内包含的所有操作要么全部成功,要么全部失败回滚;实现:日志,将所有的更新操作全部写入日志当中,若因为一些系统奔溃/断电等原因导致事务中的部分更新操作已经执行,部分操作未执行,则通过回溯日志,将操作回滚,使系统保证原子性以及一致性;
一致性:不管任何时间有少个并发的事务,系统也必须保持一致;
隔离性:多个并发的事务的操作,在同一时间只能有一个事务执行(及串行的执行);
持久性:事务正确执行后,事务中对数据的操作不会回滚;
事务的隔离级别
事务的隔离级别从低到高分别是:读未提交,读已提交,可重复读,串行化,这四个隔离级别可以分别解决脏读,不可重复读,幻读的问题。
读未提交
操作:写数据的时候添加一个X锁(排他锁),也就是在写数据的时候不允许其他事务进行写操作,但是读不受限制,读不加锁。
这样就可以解决了多个人一起写数据而导致了“数据丢失”的问题,但是会引发新的问题——脏读。
脏读:读取了别人未提交的数据。
因而引入了另外一个事务隔离级别——读已提交
读已提交(Oracle默认隔离级别,还支持序列化)
操作:写数据的时候加上X锁(排他锁),读数据的时候添加S锁(共享锁),而且有约定:如果一个数据加了X锁就没法加S锁;同理如果加了S锁就没法加X锁,但是一个数据可以同时存在多个S锁(因为只是读数据),并且规定S锁读取数据,一旦读取完成就立刻释放S锁(不管后续是否还有很多其他的操作,只要是读取了S锁的数据后,就立刻释放S锁)。
这样就解决了脏读的问题,但是又有新的问题出现——不可重复读。
不可重复读:同一个事务对数据的多次读取的结果不一致。
解决方法——引入隔离级别更高事务隔离:可重复读
可重复读(MySQL默认隔离级别)
操作:对S锁进行修改,之前的S锁是:读取了数据之后就立刻释放S锁,现在修改是:在读取数据的时候加上S锁,但是要直到事务准备提交了才释放该S锁,X锁还是一致。
这样就解决了不可重复读的问题了,但是又有新的问题出现——幻读。
例如:
有一次旺财对一个“学生表”进行操作,选取了年龄是18岁的所有行, 用X锁锁住, 并且做了修改。
改完以后旺财再次选择所有年龄是18岁的行, 想做一个确认, 没想到有一行竟然没有修改!
这是怎么回事? 出了幻觉吗?
原来就在旺财查询并修改的的时候, 小强也对学生表进行操作, 他插入了一个新的行,其中的年龄也是18岁! 虽然两个人的修改都没有问题, 互不影响, 但从最终效果看, 还是出了事。
(注: 正是小强的操作, 让旺财出现了“幻读”)
解决幻读的方式——串行化
串行化
事务只能一件一件的进行,不能并发进行。
总结:
1.幻读与不可重复读的区别?
幻读针对于记录的个数(insert/delete),而不可重复读针对于记录的内容(update);
2.
如何实现隔离性?
俩种类型的锁,乐观锁、悲观锁;
悲观锁:当前事物将所有涉及操作的对象全部加锁,操作完之后释放给其他对象使用;
乐观锁:不同的事务可以看到统一数据的不同的历史版本;如果有俩个事务同时修改了同一个数据,则较晚的事务提交时进行冲突检测;
乐观锁的实现方式:1、日志的方式;2、在内存中保存同一数据的多个历史版本,通过时间戳来区分;
如何设置隔离性?
(1)配置mysql.ini文件
1 #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE.
2 [mysqld]
3 transaction-isolation = REPEATABLE-READ
(2)use 数据库名;
(3)select @@tx_isolation;//查看是否设置成功,一般设置完成后需要重启mysql的服务;
SQL语言分类
DQL:数据查询语言 SELECT FROM WHERE组成;
DML:数据操纵语言 UPDATE INSERT DELET组成;
DDL:数据定义语言,用来定义数据库的各种对象表、视图、索引、同义词、聚簇等;
DCL:数据控制语言,用来授予或者回收访问数据库的某种特权,并控制数据库操控事务的发生时间以及效果,对数据库实行监控;
数据库设计三大范式
为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。
总结:
- 第一范式:一个单元格只存储一个值。
- 第二范式:满足所有的属性字段唯一依赖主键
- 第三范式:消除传递依赖,例如:订单号----决定----->用户id------决定------>用户名;这个时候我们就需要消除这种依赖传递;但是又时候也得兼顾查询效率,高查询率低修改率的字段可以考虑违反第三范式。