数据库事务详解(面试常考点)

(一)事务

事务就是就是一个操作可以分为多个单元,这些单元要么全部成功,要么全部失败。

(二)事务的特性

原子性:事务是一个不可分割的单位,在一组事务操作中,可以分为多个步骤,这些步骤要么全部成功,要么全部失败。

一致性:数据库事务执行前后,数据在完整性上是前后一致的。

隔离性:事务存在线程安全问题。隔离性是为了解决事务的线程安全问题而存在的一个特性。两个事务同时访问一条数据,一个事务可能会受到另外一个事务的影响,导致数据前后读取操作不一致。这种情况可以通过隔离性来避免。

持久性:如果数据库中的事务被提交,则数据库中的数据将会发生真实的修改,这个过程不可逆,任何操作都无法撤销已经被提交的事务。

(三)隔离性概述

在数据库中可能会出现线程安全问题,问题包含虚读/幻读、不可重复读,脏读。这些问题可以通过修改数据库的隔离级别来避免。数据库的管理员可以根据自己的业务需求对隔离级别进行修改,如果希望避免的问题较多,则可以提升隔离级别,如果要求效率大于数据的安全性,则可以降低数据库的隔离级别。

线程安全问题概述:

  1. 脏读:在一次事务提交前后,另一个事务读取到了不同数据,这种情况称之为脏读。
  2. 不可重复读:一个事务读取到另外一个已经提交事务的结果,导致事务提交前后数据读取不一致,这种现象称之为不可重复读。
  3. 虚读/幻读:在整表操作的情况下,一个事务读取到另一个事务已经提交的数据,造成数据前后不一致,这种情况称之为虚读/幻读

(四)数据库的隔离级别 

read uncommitted

最低的隔离级别,在这种隔离级别之下安全性最低,所有事务都会出现线程安全问题。

问题包含脏读、不可重复读、虚读/幻读。

read committed

较低的隔离级别,在这种隔离级别之下,安全性较低,事务可能会发生线程安全问题。

问题包含不可重复度、虚读/幻读。可以避免脏读。

repeatable read

mysql数据库默认的事务隔离级别。

较高的隔离级别,在这种隔离级别之下,安全性较高,不容易出现线程安全问题。

问题包含虚读/幻读。可以避免脏读/不可重复读。

serializable

最高的隔离级别。在这种隔离级别之下,安全性最高,效率最低

所有的事务均不会出现线程安全问题,整个数据库的运行就变成另一个串行化的运行模式。

这种隔离级别下任何线程问题都不会出现。

 

提升数据的隔离级别可以提升数据库的数据安全性,保证数据正确,但是由于数据库提升隔离性,是通过添加锁来实现,所以随之带来的是效率的降低,如果安全性很高,执行效率将会很低。数据库的执行效率和安全性都应该保证,所以应该在保证数据安全的情况下,尽
可能的提升数据库的执行效率。

安全性:
Serializable > repeatable read > read committed > read uncommitted
效率:
read uncommitted > read committed > repeatable read > serializable

补充:

设置数据库的隔离级别:set global/session transaction isolation level 隔离级别;

global表示在全局范围内设置隔离级别,重启mysql服务端之后,mysql的隔离级别便是global。

session 表示在当前窗口设置全局隔离级别,设置的隔离级别只对当前窗口的mysql的隔离级别有用。

查询数据库隔离级别: select @@tx_isolation;/ select @@transaction_isolation;

(五)锁问题

数据库隔离性的实现,其实就是在数据库服务器中添加各种各样的锁。

【共享锁和排他锁】

共享锁(S锁),又称为读锁
排他锁(X锁),又称为写锁

共享锁:

select * from ad_plan lock in share mode;

排他锁:

select * from ad_plan for update

在非Serializable级别之下,查询不添加锁。

在Serializable级别之下,查询添加共享锁

在任意隔离级别之下,更新添加排它锁

共享锁和共享锁可以共存。

共享锁和排他锁不可以共存。

排它锁和排它锁不可以共存。

共享锁适用于两张表存在业务关系时的一致性要求,排他锁适用于操作同一张表时的一致性要求。

关于共享锁与排他锁,大家可以参考https://www.cnblogs.com/liaoweipeng/p/7615959.html

表级锁和行级锁

表级锁是指可以锁住整张表的锁,行级锁是指锁住一行数据的锁。被锁住的表或者数据只能被一个事务操作。表级锁和行级锁已经在数据库实现的时候有数据库者数据只能被一个事务操作。表级锁和行级锁已经在数据库实现的时候有数据库服务器指定完成,所以不需要数据管理员手动指定。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章