数据库——MySQL从入门开始(数据库系统原理篇一)

本文介绍了MySQL数据库的事务概念,包括ACID特性、AutoCommit模式。深入探讨了并发一致性问题,如丢失更新、读脏数据、不可重复读和幻影读。详细讲解了封锁机制,包括封锁粒度、封锁类型以及两段锁协议。最后,讨论了MySQL的四种隔离级别及其作用。

一、事务

1.概念

事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。

2.ACID

  1. 原子性
    事务不可分割,要么成功提交,要么失败回滚。回滚由回滚日志实现(Undo Log),记录事务的修改操作,回滚时反向操作。
  2. 一致性
    事务执行前后保持一致,所有事务对同一个数据的读取结果是相同的。
  3. 隔离性
    某事务修改后提交前,对其他事务不可见。
  4. 持久性
    一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。
    系统发生奔溃可以用重做日志(Redo Log)进行恢复,从而实现持久性。与回滚日志记录数据的逻辑修改不同,重做日志记录的是数据页的物理修改。

四大特性关系:

  • 一致性成立,事务执行结果才正确;
  • 无并发时,事务串行执行,满足隔离性,此处只要满足原子性,就满足一致性;
  • 有并发时,多事务并行执行,事务需满足原子性和隔离性,才可进一步满足一致性;
  • 事务满足持久化操作是为应付系统奔溃。
    在这里插入图片描述

3.AutoCommit

MySQL 默认采用自动提交模式。也就是说,如果不显式使用START TRANSACTION语句来开始一个事务,那么每个查询操作都会被当做一个事务并自动提交。

二、并发一致性

1.原因及解决方法

原因:事务隔离性难以保证。
方法:通过并发控制来保证隔离性。
ps:并发控制可以通过封锁来实现,但是封锁操作需要用户自己控制,相当复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。

2.丢失数据

T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。

先来后到——后到者胜。
在这里插入图片描述

3.读脏数据

T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。

先改后撤——读取了后撤者。

在这里插入图片描述

4.不可重复读

T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。

先读后改再读——已是不同人间。

在这里插入图片描述

5.幻影读

T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。

在这里插入图片描述

三、封锁

1.封锁粒度

两种封锁粒度:行级锁以及表级锁。

锁与并发:应该尽量只锁定需要修改的那部分数据,而不是所有的资源。锁定的数据量越少,发生锁争用的可能就越小,系统的并发程度就越高。

粒度与资源:但是加锁需要消耗资源,锁的各种操作(包括获取锁、释放锁、以及检查锁状态)都会增加系统开销。因此封锁粒度越小,系统开销就越大。

权衡:在选择封锁粒度时,需要在锁开销和并发程度之间做一个权衡。

2.封锁类型

读写锁

互斥锁(Exclusion):X锁,写锁;
共享锁(Shared):S锁,读锁;

规定:
某事务对A加X锁,可读取和更新,其他事务此期间不可加任何锁;
某事务对A加S锁,可读取,不可更新,其他事务此期间可加S锁,不可加X锁。

意向锁

原因:意向锁(Intention Locks)支持多粒度封锁;存在行级锁和表级锁时,使用读写锁后再操作需每行检测,耗时。

形式:意向锁在原来的 X/S 锁之上引入了 IX/IS,IX/IS 都是表锁,用来表示一个事务想要在表中的某个数据行上加 X 锁或 S 锁

规定:

  • 一个事务在获得某个数据行对象的 S 锁之前,必须先获得表的 IS 锁或者更强的锁;
  • 一个事务在获得某个数据行对象的 X 锁之前,必须先获得表的 IX 锁。

举例:

通过引入意向锁,事务 T 想要对表 A 加 X 锁,只需要先检测是否有其它事务对表 A 加了 X/IX/S/IS 锁,如果加了就表示有其它事务正在使用这个表或者表中某一行的锁,因此事务 T 加 X 锁失败。

示意图:

在这里插入图片描述
解释:

  • 任意 IS/IX 锁之间都是兼容的,因为它们只表示想要对表加锁,而不是真正加锁;
  • 这里兼容关系针对的是表级锁,而表级的 IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T1 想要对数据行 R1 加 X 锁,事务 T2 想要对同一个表的数据行 R2 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)

3.封锁协议

三级封锁协议

①一级封锁协议

做法:事务 T 要修改数据 A 时必须加 X 锁,直到 T 结束才释放锁。

结果:可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。

在这里插入图片描述

②二级封锁协议

做法:在一级的基础上,要求读取数据 A 时必须加 S 锁,读取完马上释放 S 锁

结果:可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。

在这里插入图片描述

③三级封锁协议

做法:在二级的基础上,要求读取数据 A 时必须加 S 锁,直到事务结束了才能释放 S 锁

结果:可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。

两段锁协议

过程:加锁和解锁

可串行调度:通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。串行执行的事务互不干扰,不会出现并发一致性问题

事务遵循两段锁协议是保证可串行化调度的充分条件

例子:满足两段锁协议,可串行化调度

lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)

不满足,但是可串行调度

lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)

4.MySQL隐式与显示锁定

隐式:
MySQL 的 InnoDB 存储引擎采用两段锁协议,会根据隔离级别在需要的时候自动加锁,并且所有的锁都是在同一时刻被释放,这被称为隐式锁定。
显式:

SELECT ... LOCK In SHARE MODE;
SELECT ... FOR UPDATE;

四、隔离级别

1.未提交读(Read Uncommitted)

事务中的修改,即使没有提交,对其它事务也是可见的。

2.提交读(Read Committed)

一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。

3.可重复读(Repeatable Read)

保证在同一个事务中多次读取同一数据的结果是一样的。

4.可串行化(Serializable)

强制事务串行执行,这样多个事务互不干扰,不会出现并发一致性问题。

PS:该隔离级别需要加锁实现,因为要使用加锁机制保证同一时间只有一个事务执行,也就是保证事务串行执行

在这里插入图片描述

1、 Find the name, loan number and loan amount of all customers; rename the column name loan_number as loan_id. 2、 Find the names of all customers whose street includes the substring “Main”. 3、Find all customers who have a loan, an account, or both: 4、Find all customers who have both a loan and an account. 5、Find all customers who have an account but no loan. 6、Find the average account balance at the Perryridge branch. 7、 Find the number of tuples in the customer relation. 8、 Find the number of depositors in the bank. 9、 Find the number of depositors for each branch. 10、Find the names of all branches where the average account balance is more than $1,200. 11、Find all loan number which appear in the loan relation with null values for amount. 12、Find all customers who have both an account and a loan at the bank. 13、Find all customers who have a loan at the bank but do not have an account at the bank 14、Find all customers who have both an account and a loan at the Perryridge branch 15、Find all branches that have greater assets than some branch located in Brooklyn. 16、Find the names of all branches that have greater assets than all branches located in 1、创建个School数据库,该数据库的主数据文件逻辑名称为SCHOOL_data,物理文件名为School.mdf,初始大小为10MB,最大尺寸为无限大,增长速度为10%;数据库的日志文件逻辑名称为School_log,物理文件名为School.ldf,初始大小为1MB,最大尺寸为5MB,增长速度为1MB。 2、用SQL语句建立上述表,自定义主键和外键,对于student表建立约束条件:ssex仅能取male或female;sage在18和22之间。并完成下面的查询语句。 1、查询所有选修过“Bibliometrics”课的学生的姓名和成绩; 2、查询考试成绩不及格的学生的个数; 3、查询名字中至少含有个“z”字符的学生的姓名、学号和性别; 4、查询选修了“Introduction to the Internet”课程的学生的学号及其成绩,查询结果按分数的降序排列; 5、查询“Zuo li”同学选修课程的总学时(time)数 6、查询年龄不大于20岁的学生的平均考试成绩; 7、查询 “computer science”专业学生选修 “Database System”的人数; 8、查询同时选修课程“Database System”和“Introduction to the Internet”的学生姓名; 9、查询选修的课程中含有“Wang gang”同学所有选修课程的学生姓名。 10、查询“Information Technology for Information Management”考试成绩为空的学生姓名及专业名称。 11、查询“computer science”专业学生每个人的选修课总学分。 12、查询个人考试平均成绩高于专业平均成绩的学生姓名 13、查询个人考试平均成绩高于女生平均成绩的男生姓名 14、查询比“computer science”专业所有学生年龄都大的学生姓名。 15、查询考试成绩仅有科不及格学生姓名
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值