数据库通关整理2-事务、并发问题、事务隔离级别、锁(S锁、X锁`)、乐观锁、悲观锁、sql注入、内连接、外连接

网上收集整理,仅供笔记参考学习

数据库通关整理1-索引、聚簇索引、非聚簇索引、MyISAM和InnoDB存储引擎、范式

数据库通关整理2-事务、并发问题、事务隔离级别、锁(S锁、X锁`)、乐观锁、悲观锁、sql注入、内连接、外连接

数据库通关整理3-Redis基础(数据库、缓存、消息中间件)、RDB、AOF、发布订阅、主从复制、哨兵模式、缓存穿透、缓存击穿、缓存雪崩


一、事务

1.1 事务的4个属性

ACID:原子性、一致性、隔离性、持久性
原子性 一个事务中的所有操作,要么全部完成,要么全部不完成, 不会结束在中间某个环节。发生错误,会被回滚 (Rollback)
一致性 在事务开始和完成时,数据库中的数据都保持一致的状态,数据的完整性约束没有被破坏。例如:即如果你修改了一张表中的数据,那你还需要修改与之存在外键约束关系的其他表中对应的数据,以达到一致性。
隔离性 一个事务的执行不能被其他事务干扰。
持久性 一个事务一旦提交,它对数据库中数据的改变就应该是永久性的

1.2 并发事务引发的问题

丢失数据、脏读、不可重复读、幻读
丢失数据 T1和T2对同一数据修改,T2的修改覆盖了T1的修改,导致T1的修改数据丢失。
脏读: T1修改数据后写回,但是又由于某一原因撤销,数据已经恢复到原来的数据,但是T2读同一数据时,读取的是T1修改后的数据,与数据库中的数据不一致,T2读到的数据就是”脏“数据,不正确的数据
不可重复读 同一事务T1中前后多次读某一数据,如果前后的数据不一致,就称为不可重复读。(由于T2在T1运行中修改了数据的值)
幻读 事务T1读取与搜索条件相匹配的若干行。事务T2以插入或删除行等方式来修改事务A的结果集,然后再提交。
例如:T1是修改所有数据完成,此时T2插入一条新数据,但T1在再次重新读到这条数据时,发现未修改的数据时,就好像一种没有修改的幻觉一样。

1.3 怎么解决并发问题(并发控制)

乐观并发控制(乐观锁)和悲观并发控制(悲观锁)

1.4 数据库事务的隔离级别

数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们 不会相互影响, 避免各种并发问题。
4种隔离级别:
1.读未提交数据
允许事务读取未被其他事务提交的变更,可能有脏读,不可重复读和幻读的问题。
2.读已提交数据
允许事务读取已经被其他事务提交的变更,可以避免脏读,可能有不可重复读和幻读的问题
3.可重复读(Mysql 的默认隔离级别)
确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新,可以避免脏读和不可重复读可能会有幻读
4.可串行化
所有事务都一个接一个地串行执行。可以避免脏读,不可重复读,幻读

二、锁

2.1 说下数据库的锁机制

锁是一种并发控制技术,锁是用来在多个用户同时访问同一个数据的时候 保护数据的。

2.2 锁的分类

2.2.1 按锁的粒度来分(行级锁页级锁表级锁

1.行级锁
**仅对指定的记录进行加锁,**这样其它进程还是可以对同一个表中的其它记录进行操作。特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
InnoDB 存储引擎既支持行级锁,也支持表级锁,但默认情况下是采用行级锁

2.页级锁
一次**锁定相邻的一组记录。**开销和加锁时间界于表锁和行锁之间;会出现 死锁;锁定粒度界于表锁和行锁之间,并发度一般

3.表级锁
直接锁定整张表,在你锁定期间,其它进程无法对该表进行写操作。如果
你是写锁,则其它进程则读也不允许。特点:开销小,加锁快;不会出现死锁;锁定粒度最大,发生锁冲突的概率最高,并发度最低。

最常用的处理多用户并发访问的方法是加锁,加锁对并发访问的影响体现在锁 的粒度上。
比如,(表锁)放在一个表上的锁限制对整个表的并发访问;(页锁) 放在数据页上的锁限制了对整个数据页的访问;(行锁)放在行上的锁只限制 对该行的并发访问。

2.2.2 按锁的级别来分(S锁X锁

2种基本锁类型
共享(S)锁: 多个事务可封锁一个共享页(页:磁盘IO的最小单位);任何事务都不能修改该页; 通常是该页被读取完毕,S 锁立即被释放
加锁之前需要检查是否有排他锁,如果没有,则可以加共享锁
排它(X)锁: 仅允许一个事务封锁此页; 其他任何事务必须等到 X 锁被释放才能对该 页进行访问;X 锁一直到事务结束才能被释放

2.2.3 按锁的机制来分(乐观锁悲观锁

锁有两种机制:悲观锁和乐观锁。

  • 悲观锁
  • 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在修改数据时就会上锁,直到更改完成才释放

悲观锁的实现,往往依靠数据库提供的锁机制,也只有数据库层提供的锁机制才能真正保证数据访问的排他性。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

  • 乐观锁
  • 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据
2.2.3.1乐观锁悲观锁使用场景

悲观锁一般适用于多写的情况下。多写的情况,往往更容易产生冲突。并发量不大的情况。

  • 悲观锁可能会造成加锁的时间很长,并发性不好,特别是长事务,影响系统的整体性能。处理加锁的机制会让数据库产生额外的开销。

乐观锁适用于写比较少的情况下(多读场景)即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。并发量大的时候。

  • 乐观锁加锁的时间要比悲观锁短,大大提升了大并发量下的系统整体性能 表现。
2.2.3.2乐观锁悲观锁实现方式

乐观锁、悲观锁是两种加锁的思想,并不是真的有这两种锁。
悲观锁: 往往依靠数据库提供的锁机制,传统的关系型数据库里边就用到 了很多这种锁机制,比如**行锁,表锁等,读锁(共享锁),写锁(排他锁)**等,都是在做操作之前先 上锁。

用InnoDB存储引擎举例,来说明在SQL中如何使用悲观锁。

要使用悲观锁,需要关闭MySQL的自动提交属性。因为MySQL默认是自动提交。

0.开始事务
1.加锁 select * from db where id=1 for update
2.更改数据
3.提交事务

乐观锁:

1.数据版本(Version)记录机制
为每一行数据增加一个版本标识(也就是每一行数据多一个字段 version),每次更新数据都要更新对应的版本号+1。

工作原理:读出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本信息与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号则予以更新,否则认为是过期数据,不得不重新读取该对象并作出更改。

2.使用时间戳来实现
同样是在需要乐观锁控制的 table 中增加一个字段,名称无所谓,字段类型 使用时间戳 , 和上面的 version 类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一 致则 OK,否则就是版本冲突。

三、常使用的sql命令

插入一行数据:
insert into stu(stuName,stuAge,stuSex) values(‘张三’,‘20’,‘男’)

增加列:
alter table tableName add (column)columnName varchar(30) (数据类型要有)

删除列:
alter table tableName drop (column) columnName

四、sql注入的问题

4.1 sql语句相关的安全性

1.sql注入
2.sql运行错误时,将数据库返回的全部错误信息返回给用户(会泄露服务器和数据库相关的信息)

4.2 sql注入

所谓SQL注入,它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器

SQL注入攻击是最古老,最流行,最危险的Web应用程序漏洞之一。

以下注入sql语句时,没有过滤特殊字符$name,此时就会把不需要的DELETE FROM users语句插入,就会删除所有信息。

// 设定$name 中插入了我们不需要的SQL语句
$name = "Qadir'; DELETE FROM users;";
 mysqli_query($conn, "SELECT * FROM users WHERE name='{$name}'");

4.2 防止sql注入

1.参数PreparedStatement
采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。

2、检查变量的数据类型和格式
只要是有固定格式的变量,在 SQL 语句执行 前,应该严格按照固定格式去检查,确保变量是我们预想的格式,这样很大程 度上可以避免 SQL 注入攻击。

3.字符串过滤
把关于数据库操作的字符过滤掉

String inj_str = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";

4、所有的 SQL 语句都封装在存储过程

五、内连接、外连接

内连接(inner join):也称为等值连接,返回两张表都满足条件的部分,inner join 就等于 join
在这里插入图片描述

左外连接(left join)
左表全部出现在结果集中,若右表无对应记录,则相应字段为NULL
在这里插入图片描述

右外连接(right join)
右表全部出现在结果集中,若左表无对应记录,则相应字段为NULL
在这里插入图片描述

全外连接(FULL JOIN )
除了显示符合连接条件的记录外,在2个表中的其他记录也显示出来。

MySQL目前不支持此种方式,可以用其他方式替代解决。

5.1 数据库两个表的交集、并集、差集

交集(用 inner join)
差集(用 left join 或 right join)
求并集(用 union)

猜你喜欢

转载自blog.csdn.net/weixin_45773603/article/details/108178128