MYSQL SELECT 是多彩的, 业务如何应用适应不同场景

2020-07-29 00:00:00 数据 操作 事务 业务 情况




看过不少文字, 实际上基本上很少看到select 语句被研究的,  select 不就是select 出数据这么简单, NO NO NO . 


我们先看看MYSQL 的SELECT 到底有几种形式, 在什么方式上需要被使用,可以满足某些系统的功能.


1 select for share;


这个应用到的相对于for update 要少的多, 但实际上有些业务中是可以用到他来避免一些问题的. 例如某行内容,在事务的操作中不能被改变,但可以被查询,则就可以在程序的事务中添加 select for share语句保证,在事务的运行过程中,这行数据不被修改.


例如: 对当前的雇员的信息进行审核,在审核时员工的title是不能被改变的.

事务1  审核员工过程

事务 2 


我们可以看到在事务1 运行过程中, 事务2 已经将查看的员工信息的title 进行了更改.


所以没有达到预定的需求, 下面在查询时 添加了for share 则update 在事务2 中失败了. 



FOR SHARE  在行上加了  S 锁


另有些业务在查询时需要避免数据被查询或被修改,这样的业务流程例如预定业务.

事务 1

事务 2


这样的情况就使用  select for update  对操作的行添加 X 锁的方式解决问题.

那可能有同学会问那我什么都不加的情况下,加的什么锁.

select 什么都不加的情况下,读取的数据是快照,所以不加锁. (当然这里是有条件的)

对于有些业务中,对于数据在操作时,不运行读的情况可以使用  for update 和 for share 的组合,

事务 1


事务2 


这样的情况下,就可以避免某些业务中要对某行业务数据,在修改前就不允许访问的情况,就如同购票,占座等业务.


在mysql 8 后给出了新的select 支持的方式, 其中NOWAIT 就是一个在原有模式中添加的附加的功能, 和NOWAIT 一样,不必等待



实际上如果没有NOWAIT, 在遇到上面的情况,大多我们会等待5秒后, 在告知你事务失败了,以及相关的原因.

MYSQL 数据库本身的定位是快速的OLTP的操作,在高并发中这样的等待的情况可能不被允许,应用程序希望快速的得到我是否可以对这行是否能进行操作,所以在此基础上,MYSQL 8 提供了 NOWAIT 的方式来满足应用的需求.


例如

对行进行X锁添加

继续对行进行操作, 添加了nowait 操作符后, 操作直接会反馈释放可以进行操作如不行直接反馈, 

Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set.

其中包含了执行的语句和那个其他操作事务的锁有冲突. 这样就提供了更多方式更方便的提供了对OLTP方式的快速处理和反馈


另外MYSQL 还提供了 SKIP LOCKED 功能, 这个功能在业务中可以避免一些互斥的问题, 例如


我们在进行update 的时候操作两个集合中的合并集合, 而此时又进行了另一个扩大范围的操作,这样的情况如果不使用skip locked 则 第二幅图的小圆操作必然会失败, 使用了skip locked 操作则会让这两个操作不在冲突.



事务1 在更新数据,并且是更新一个数据的范围

事务2 

可以从图2中看到,如果此时想对已经部分被锁定 部分未被锁定的数据 查询时使用了 for update skip locked 则是可以查到在集合内并未被锁定的数据.


但如果没有for update skip locked 这个语句,则数据是无法被查询到的


所以灵活的使用目前MYSQL 8 提供的 nowait  skip locked 语句对于一些业务是有相关的帮助来解决.


另外可能有些同学会对 for update  lock in share mode  for share 等几个方式的select 的锁的情况有疑问,下面我们在确认一下.

for update

for share

lock in share mode


相关文章