MySQL事务以及锁

事务

首先是ACID四个特性:

  • A(Atomicity):原子性是指事务所包含的操作要么全成功,要么全部失败回滚;因此,事务的操作如果成功就必须全部应用到数据库,如果失败,则不能对数据库有任何影响;
  • C(Consistency):一致性:也就是说事务必须从一个一致性的状态变成另一个一致性的状态;例如转账:假设用户A和用户B两者的钱加起来一共是1000,无论他们之间怎么转账,总钱数是不变的,这就是事务的一致性;
  • I(Isolation):隔离性:是指当多个用户并发访问数据库时,假设操作同一张表时,数据库为每一个用户开启的事务,不能被其他用户的事务干扰,多个并发事务之间要相互隔离;
    即要达到一种效果,对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后在执行;这样,每个事务都感觉不到有其他事务在并发的执行;
  • D(Durability):持久性:一个事务一旦被提交了,那么对数据库的数据是永久性的,即便在数据库出现故障的时候也不会丢失提交事务的操作;

对于事务的提交方式来说:

  • 自动提交:Mysql数据库的默认提交方式,当我们在写一些update,delete的语句时,会自动帮我们开启一个事务,执行我们的语句,在帮我们提交事务;
  • 手动提交:我们自己手动开启一个事务;
BEGIN;
update USER set name = 'zhangsan' where id = 1;
COMMIT;
  • 隐式提交:当我们使用start transaction或者begin开启一个事务时,或者把系统变量autocommit的值设为off时,事务就不会自动提交;但是如果我们输入了某些语句之后就会悄悄提交掉,就想我们输了commit一样,这种因为某些特殊的语句而导致事务提交的情况就是隐式提交;
    造成隐式提交的语句主要包括:
    (1):定义或修改数据库对象的数据定义语言(DDL:Data definition language )。所谓的数据库对象指的就是数据库,表,视图,存储过程这些东西,当我们使用create,alter,drop等语句去修改这些数据库对象时,就会隐式提交前边语句所属于的事务;
    (2):隐式使用或修改mysql数据库中的表:当我们使用create user,drop user,alter user,grant, rename user,set password等语句时也会隐式提交之前的事务;
    (3):事务控制或者关于锁定的语句:当我们在一个事务还没提交或者回滚时,使用start transaction或者begin开启了另一个 事务,会隐式提交上一个事务;或者当前autocommit的值为off,我们把它修改为on时,也会隐式的提交上一个事务;或者使用lock tables或者unlock tables关于锁定的语句也会隐式的提交之前的事务;
    (4):加载数据的语句:比如我们使用load data语句批量向数据库中导入数据时,也会隐式提交之前的事务;
    (5):其他的一些语句:使用Analyze table,cache index,check table,flush,load index into cache,optimize table,repair table,reset等语句也会隐式提交之前的事务;

保存点

如果你开启了一个事务,并且已经敲了很多语句,这时候你发现上面一条语句敲得有问题,你只好使用rollback来回滚,然后一切重新开始,这样来说,是特别烦人的;所以MySQL提出了保存点(savepoint)的概念,就是在事务对应的地方打几个点,我们在调用rollback语句时可以指定回滚到那个点,而不是回到最初的点;
定义保存点:

savePoint 保存点名称;

当我们想回滚到某个保存点时:(下面语句中的[work],[savepoint]是可有可无的):

rollback [work] to [savepoint] 保存点名称;

删除保存点:

release savepoint 保存点名称

隔离性详解

修改隔离级别:

set session transaction isolation level read  uncommitted;

查看隔离级别:

select @@tx_isolation;

隔离级别

  • 读未提交(read uncommitted):一个事务可以读到其他事务还没有提交的数据,会出现脏读 ;
  • 读已提交(read commited):一个事务只能读到另一个已提交的事务修改过的数据,并且其他事务每一次对该数据进行修改提交后,该事务都能查询得到最新的值,会出现不可重复读,幻读;
  • 可重复读(repeatable read):一个事务第一次读过某条记录后,即使其他事务已经修改并提交了该数据, 该事务之后再读该记录时,仍是第一次读到的值,而不是每次都是不同的值,这就是可重复读,解决了不可重复读的问题,但是还是会出现幻读;
  • 串行化(serializable ):以上三种隔离级别都允许对同一条记录进行读-读,读-写,写-读的并发操作,如果我们不允许写-读,读-写的并发操作,可以使用serializable隔离级别,这种隔离级别因为对同一条记录都是串行的,所以不会出现脏读,幻读的现象;
    这四种隔离级别是SQL定义的标准定义,不同的数据库会有不同的实现,特别需要注意的是“mysql在repeatable read”隔离级别下, 是可以禁止幻读问题的发生的;

版本链

对于使用InnoDB存储引擎的表来说,他的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们创建的主键或者非null唯一键时都不会包含row_id):
trx_id: 每次对某条记录进行改动时,都会把对应的事务Id赋给trx_id列;
roll_pointer:每次对某条记录进行改动时,这个隐藏列会存一个指针,这个指针指向记录修改前的数据信息;

ReadView

对于使用read uncommited隔离级别的事务来说,直接读取数据的最新版本就好了;对于使用serializable隔离级别的事务来说,使用加锁的方式来访问记录;对于使用read committed和repeatable read隔离级别的事务来说,就要适用上面说的版本链了,核心问题就是需要判断版本链中那个版本是当前事务可见的;
readview中主要包含4个比较重要的内容:

  • m_ids:表示在生成ReadView时,当前系统中活跃的读写事务的事务id列表;
  • min_trx_id:表示在生成ReadView时,当前系统中活跃的读写事务的事务id列表中,最小的事务id;
  • max_trx_id:表示在生成ReadView时,当前系统中活跃的读写事务的事务ID列表中,最大的事务id;
  • creator_trx_id:表示生成该ReadView的事务的事务id;
    MVCC(Multi-version Concurrency control)多版本并发控制,指的就是在使用read committed,repeatable read 这两种隔离级别的事务在执行普通的select操作时,访问记录的版本链的过程。可以使不同事务的写-读,读-写操作并发执行,从而提升系统性能,read committed和repeatable read这两个隔离级别的一个很大的不同是:生成readView的时机不同,read committed在每一次执行select操作时都会生成一个ReadView,而repeatable read只在第一次进行select的操作时生成一个ReadView,之后的查询都使用这一个就好了;

读锁和写锁
读锁:共享锁,Shared Locks ,S锁;
写锁:排他锁,Exclusive locks, X锁;
select:不加锁;

S锁X锁
S锁不冲突冲突
X锁冲突冲突

读操作

对于普通的select语句,InnoDB不会加锁;

select … lock in share mode

将查找到的数据加上一个S锁,允许其他事务继续获取这些记录的S锁,但是不能获取这些记录的X锁(会阻塞) ;

select … for update

将查找到的数据加上一个X锁,不允许其他事务获取这些数据的X锁和S锁;
使用场景:读出数据后,其他事务既不能写,也不能加读锁,那么就导致只能自己修改数据;

写操作

  • delete:删除一条数据,先对数据加X锁,再执行删除操作;
  • insert:插入一条数据时,会先加隐式锁来保护这条新加入的记录在提交前不被其他事务访问;
  • update:
    (1):如果更新的列,没有导致存储空间发生变化,那么会先给记录加X锁,在直接对记录进行修改;
    (2):如果更新的列,导致存储空间发生变化,那么会先给记录加X锁,然后将记录删除,再重新插入;
    隐式锁:一个事务插入一条记录后,还未提交,这条记录会保存该事务的id,而其他事务如果想要对这条记录加锁,会发现事务Id不对应,这时会产生X锁,所以相当于在插入一条记录时,隐式的给这条记录加了一个隐式X锁;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值