数据库,事务与锁

事务

事务(Transaction)是由一系列对系统中数据进⾏访问与更新的操作所组成的⼀个程序执行逻辑单元。

1.1事务的语法

  1. starttransaction;begin;
  2. commit;使得当前的修改确认
  3. rollback;使得当前的修改被放弃

1.2事务的ACID特性

  1. 原⼦性(Atomicity)

    指事务必须是⼀个原子的操作序列单元。事务中包含的各项操作在⼀次执⾏过程中,只允许出现两种状态之一。(1)全部执行成功(2)全部执行失败事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执⾏过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发⽣一样。

  2. ⼀致性(Consistency)

    指事务的执⾏不能破坏数据库数据的完整性和一致性,一个事务在执⾏之前和执行之后,数据库都必须处以⼀致性状态。

  3. 隔离性(Isolation)

    指在并发环境中,并发的事务是互相隔离的。也就是说,不同的事务并发操作相同的数据时,每个事务都有各自完整的数据空间。⼀个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务是不能互相干扰的。

    隔离性分4个级别,READUNCOMMITTED(未提交读)READCOMMITTED(已提交读)REPEATABLEREAD(可重复读)SERIALIZABLE(序列化)。

  4. 持久性(Duration)

    事务⼀旦提交后,数据库中的数据必须被永久的保存下来。即使服务器系统崩溃或服务器宕机等故障。只要数据库重新启动,那么一定能够将其恢复到事务成功结束后的状态。

1.3事务的并发问题

事务之间的相互影响分为几种,分别为:脏读,不可重复读,幻读,丢失更新

1.脏读

脏读意味着一个事务读取了另一个事务未提交的数据,而这个数据是有可能回滚的;

2.不可重复读

不可重复读意味着,在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。

3幻读(虚读)

幻读,是指当事务不是独立执行时发生的一种现象,例如A给全部的员工加了1000元的工资,在此期间,B加入了一名新的员工,结果A的事务作用在B的对象上,导致新员工和老员工一样加了1000工资,在B看来是虚幻的。

幻读和不可重复读的结果相似,幻读体现在修改数据的同时对数据量进行操作所引发的问题;而不可重复读是由于原有数据内容的更替造成的,两者有差别。

4.丢失更新

两个事务同时读取同一条记录,A先修改记录,B也修改记录(B是不知道A修改过),B提交数据后B的修改结果覆盖了A的修改结果。

1.4事务隔离级别

为解决上述并发问题,提出了事务隔离概念。

隔离级别脏读不可重复读幻读丢失更新并发模型更新冲突检测
未提交读:ReadUncommited悲观
已提交读:Readcommited悲观
可重复读:RepeatableRead可能悲观
可串行读(序列化):Serializable悲观

使用方法:setsessiontransactionisolationlevel隔离级别

检测方法:mysql:select@@tx_isolation;

​ mysql8以后:select@@transaction_isolation;

1.5不同的隔离级别的锁的情况

未提交读:在读数据时不会检查或使用任何锁。因此,在这种隔离级别中可能读取到没有提交的数据。

已提交读:只读取提交的数据并等待其他事务释放排他锁。读数据的共享锁在读操作完成后立即释放。已提交读是SQLServer的默认隔离级别。

可重复读:像已提交读级别那样读数据,但会保持共享锁直到事务结束。

可串行读:工作方式类似于可重复读。但它不仅会锁定受影响的数据,还会锁定这个范围。这就阻止了新数据插入查询所涉及的范围。

总结

  1. 未提交读(RU):有行级的锁,没有间隙锁。读取到没有提交的数据。
  2. 已提交读(RC):有行级的锁,没有间隙锁,读不到没有提交的数据。
  3. 可重复读(RR):有行级的锁,也有间隙锁,每次读取的数据都是一样的,并且可能有幻读的情况。
  4. 可串行读(S):有行级锁,也有间隙锁,读表的时候,就已经上锁了

1.6隐式提交(了解)

DQL:查询语句句

DML:写操作(添加,删除,修改)

DDL:定义语句句(建库,建表,修改表,索引操作,存储过程,视图)。DDL都是隐式提交。

DCL:控制语⾔言(给⽤用户授权,或删除授权)

隐式提交:执⾏行行这种语句句相当于执⾏行行commit;

1.7关于锁

悲观锁、乐观锁,表锁、行锁,共享锁、排他锁

乐观锁

相当于乐观的人,总是想着事情往好的方向发展

乐观锁是指对数据库进行 增、删、改 操作时,想法很乐观,认为这次的操作不会导致冲突,在操作数据时,不进行加锁处理,而在进行更新后,再去判断是否有冲突

使用场景

适用于写比较少的情况下,多用于读

实现方式

数据库没有实现功能,需要开发者实现:

  • 版本号机制
    在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。要update该条记录时,先读取该条记录,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。
  • CAS算法实现

悲观锁

悲观锁就是在操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时都要通过 获取锁 才能进行操作

与java中的synchronized类似,所以悲观锁需要耗费较多的时间。

应用场景

一般多写的场景下

实现方式

由数据库实现

表锁

MyISAM 存储引擎不支持事务,使用 表锁,就是锁一整张表,更新一条记录就要锁整个表,导致性能较低,并发不高。

不会死锁

行锁

InnoDB 存储引擎支持事务,使用 行锁,在事务中,修改哪行,就只锁定哪行

行锁并不是直接锁记录,而是锁索引

索引分为 主键索引非主键索引 两种:

  • 如果一条sql 语句操作了主键索引,Mysql 就会锁定这条主键索引;
  • 如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引
  • 如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。
    也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。因为没有了索引,找到某一条记录就得扫描全表,要扫描全表,就得锁定表。

共享锁

又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改,要想修改就必须等所有共享锁都释放完之后。

select 语句

select可以通过 select ... lock in share mode 加共享锁

排他锁

又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。

delete、insert、update 语句

都会自动给涉及到的数据加上排他锁

select 语句

select语句默认不会加任何锁,所以可以查询被 排他锁 锁住的记录

select可以通过 select ...for update 加排他锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Spring事务数据库的相关问题,我可以为你提供一些基本的信息。请注意,以下内容仅供参考。 Spring事务是一种用于管理数据库操作的机制,它确保了数据的一致性和完整性。在Spring中,你可以使用声明式事务或编程式事务来管理数据库操作。 声明式事务是通过在方法或类级别上添加事务注解来实现的。常用的事务注解包括`@Transactional`,它可以应用在方法或类上,并提供了一系列属性来配置事务的行为。 编程式事务是通过编写代码来手动管理事务的开始、提交和回滚过程。Spring提供了`TransactionTemplate`类来支持编程式事务管理。 关于数据库,它是一种用于控制并发访问数据库的机制。数据库可以保证数据的一致性和完整性,防止多个事务同时对同一数据进行修改而导致冲突。 常见的数据库包括行级、表级和页级。行级用于数据库中的单个数据行,表级用于定整个表,而页级则用于数据库中的页。 在Spring事务中,默认情况下,使用的是数据库的行级机制。如果需要使用其他级别的或更复杂的模式,你可以在SQL语句中明确指定。 需要注意的是,使用机制可能会导致性能下降和死等问题。因此,在设计和实现数据库操作时,需要合理地选择和使用机制。 希望以上信息对你有所帮助。如果你还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值