数据库事务探究

2023-05-12 19:47:56 浏览数 (1)

数据库事务(Database Transaction)

1. 事务是个啥玩意?

数据库事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。 通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。

2. 事务都有啥属性特征呢?

  1. 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
  2. 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
  3. 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
  4. 持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。

3. 事务这玩意能干啥?

一个数据库事务通常包含对数据库进行读或写的一个操作序列。它的存在包含有以下两个目的: 1、为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。 2、当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

4. 追根究底的将事务之前,先问问自己commit和rollback的还知道是干啥的不?

commit即提交,表示这个事务的所有操作都执行成功,commit告诉系统,数据库要进入一个新的正确状态,该事务对数据库的所有更新都要确保不因数据库的宕机而丢失。 rollback即回退或回滚,表示事务中有执行失败的操作,这些操作必须被撤销,rollback告诉系统,已发生错误,数据库可能处在不正确的状态,该事务对数据库的部分或所有更新必须被撤销。

代码语言:javascript复制
commit的作用不是把缓存/内存中的数据更新/同步到数据库。
commit 之前,数据已经提交到服务器了,只是写在日志里,没有正式提交。所以可以被另外的客户端读取。

5. 都有哪些事务?

1.读事务

如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性; 如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。

2.写事务

很好理解,如银行转账A用户需要扣钱B用户需要加钱。

6. 事务并发执行时会产生哪些影响?

首先程序是可以并发执行的,同样,在MySQL中,一个表可以由两个或多个进程同时来读写数据。 比如,此时有两个进程来读数据,这也没什么问题,允许。但是如果一个进程在读某一行的数据的过程中,另一个在进程又往这一行里面写数据(改、删),那结果会是如何?同样,如果两个进程都同时对某一行数据进行更改,以谁的更改为准?那结果又会怎样,不敢想象,是不是数据就被破坏掉了。所以此时是冲突的。

代码语言:javascript复制
某一时刻同时发来3000个请求指定进程,进程中单线程执行的话那相当与3000个读写操作同时发生。
一个进程中开3000个线程同时对数据库进行读写操作。

7. 隔离级别是个啥?

代码语言:javascript复制
并发事务所作的修改必须与任何其它并发事务所作的修改隔离。
事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据,这称为隔离性。

  1. 读未提交:(Read Uncommitted)
  2. 读已提交(Read Committed) 大多数数据库默认的隔离级别
  3. 可重复读(Repeatable-Read) mysql数据库所默认的级别
  4. 序列化(serializable)

上面四中都是事务并发时可能会产生的影响,按照影响性大小的不同又被称为事务的隔离级别。

8. 啥情况需要隔离,那又咋隔离呢?

既然会冲突就要想办法解决,靠谁来解决,这时候就是靠锁机制来维护了。怎么使用锁来使他们不冲突? 1.丢失更新

当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。每个事务都不知道其它事务的存在。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。

如:两个事务都需要更新同一条记录中的Name字段

时间点

事务A

事务B

1

事务开始

2

读取Name=‘张三’

事务开始

3

读取Name=‘张三’

4

更新Name=‘毛蛋’

5

事务结束

更新Name=‘狗子’

6

事务结束

事务A:‘老子的毛蛋怎么没了!’

事实上Mysql数据库会在事务里面默认添加写锁,上面的现象是没法重现的。

2.读未提交(脏读)

脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。 事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的。

时间点

事务A

事务B

1

事务开始

2

读取Name=‘张三’

事务开始

3

更新Name=‘狗子’

4

读取Name=‘狗子’

5

事务回滚Name=‘张三’

6

读取Name=‘张三’

7

事务结束

事务结束

事务A:‘中间咋突然冒出个狗子,真纳闷!’

解决办法:把数据库的事务隔离级别调整到READ_COMMITTED

3.读已提交(不可重复读)

不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。 事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。

时间点

事务A

事务B

1

事务开始

2

读取Name=‘张三’

事务开始

3

更新Name=‘狗子’

4

读取Name=‘张三’

5

事务结束

6

读取Name=‘狗子’

7

事务结束

事务A:‘在我的一个事务里先后读取同样的记录结果却不一样,真奇怪。’

解决办法:把数据库的事务隔离级别调整到REPEATABLE_READ

4.幻读

和可重复读类似,但是事务二的数据操作仅仅是插入和删除,不是修改数据,读取的记录数量前后不一致。 按一定条件从数据库中读取了某些记录后,T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录消失。 T1按一定条件从数据库中删除某些数据记录后,T2插入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录。

不可重复读侧重表达 读-读,幻读则是说 读-写,用写来证实读的是鬼影。

时间点

事务A

事务B

1

事务开始

2

查询到有两个人的Name=‘张三’

事务开始

3

将所有Name=‘张三’的Score变成100分

4

插入Name=‘张三’且Score=60

5

读取到3条Name=‘张三’且有一条得分为60

事务结束

6

事务结束

事务A:‘怎么多出来一条数据?还是60分,难不成我刚才眼花了,还是产生了幻觉?’

解决办法:把数据库的事务隔离级别调整到SERIALIZABLE_READ

9. 锁机制实现事务隔离

两把锁

0 人点赞