解释:

for update是在数据库中上锁用的,可以为数据库中的行上一个排它锁。当一个事务的操作未完成时候,其他事务可以读取但是不能写入或更新。
例子:

比如一张表三个字段 , id(商品id), name(商品名字) , count(数量)
当商品抢购时候会显示剩余商品件数,如果并发量大的时候,商品自减的值可能不准确。所以当我们在一个事务中对count字段进行修改的时候,其他事务应该只能读取指定id的count,而不能进行update等操作。这个时候就需要用到for update.
sql语句:

start transaction ;
select * from table_name where id =1 for update ;

update table_name set count = count - 1 where id= 1;
此时如果另一个事务也想执行类似的操作:

start transaction ;
select * from table_name where id =1 for update ;
//下面的这行sql会等待,直到上面的事务回滚或者commit才得到执行。
update table_name set count = count - 1 where id= 1;

*注:当选中某一个行的时候,如果是通过主键id选中的。那么这个时候是行级锁。
其他的行还是可以直接insert 或者update的。如果是通过其他的方式选中行,或者选中的条件不明确包含主键。这个时候会锁表。其他的事务对该表的任意一行记录都无法进行插入或者更新操作。只能读取。*
---------------------
作者:宇宙意志
来源:CSDN
原文:https://blog.csdn.net/qq_39632561/article/details/80061364
版权声明:本文为博主原创文章,转载请附上博文链接!

sql的for update

欢迎大家吐槽

oracle行级共享锁

通常是通过select … from for update语句添加的,同时该方法也是我们用来手工锁定某些记录的主要方法。比如,当我们在查询某些记录的过程中,不希望其他用户对查询的记录进行更新操作,则可以发出这样的语句。当数据使用完毕以后,直接发出rollback命令将锁定解除(如果我们查询到了并且修改了,则commit后就可以释放了锁)。当表上添加了RS锁定以后,不允许其他事务对相同的表添加排他锁,但是允许其他的事务通过DML语句或lock命令锁定相同表里的其他数据行。

select for update

示例:

select *from goods where goods_code ='9990300100000030001' for update ;

当select语句中使用了for update,如果当前select发现自己的结果集中有一条或者多条数据正在被修改(如有其他的语句提前for update了等),那么再执行此语句就会一直等待:

此时执行:

Update/delete等语句都出现等待。只有对应的占用锁的数据被提交commi(或者rollback)t掉时才可以进行新的for update 上锁或者进行update、delete。

select for update nowait

for update nowait 和for  update都会对查询到的当前结果集进行加锁。区别是是for update nowait 发现自己要加锁的结果集正在被其他操作修改(已经被加锁),则直接反馈资源占用,不会像for update 一样等待执行。

这两个操作等待和弹窗与被那种形式的加锁sql无关,只要要处理的结果集被加锁了直接反馈弹窗。(应该是废话)

select for update wait

与for update nowait的区别是for update wait 可配置等待时间,单位秒。当过了这个时间,被加锁资源还未被释放,则和for update nowait一样直接弹窗反馈资源占用。否则执行此语句。

跳过加锁行,对满足条件的其他行进行加锁

步骤:

窗口1(每个窗口代表一个session)执行

select *from goods where goods_code ='9990300100000030001' for update  ;

窗口2中执行:

由于窗口2的sql集合中有一行被窗口1的集合加锁了,导致窗口二等待锁释放。

窗口2 修改语句如下:

select *from goods for update skip locked ;

关联表加锁

1.关联的表都加锁锁

select *

  from stat_dic_goods sg

 inner join goods g

    on sg.goods_code = g.goods_code

 where g.goods_code = 'qwe002n3'

   for update;

可以得出结论两张表中goods_code='qwe002n3'的商品都被加锁了,所以导致后免得语句对两张整体加锁时出现了等待的情况。

当在新开的窗口中对其他数据进行加锁时加锁成功:

2. 对关联的表中的某一张表进行加锁

select *
from stat_dic_goods sg
inner join goods g
on sg.goods_code = g.goods_code
where g.goods_code = 'qwe002n3'
for update of sg.goods_code;

Oracle共享锁

语法:lock table stat_dic_goods in share mode;

执行完lock语句再执行update语句就会出现等待中,因为lock语句已经将这个表锁了,此时只允许读取不允许修改。

通过lock table in share mode命令添加该S锁。在该锁定模式下,不允许任何用户更新表。但是允许其他用户发出select …from for update命令对表添加RS锁。

Oracle只有表级别的共享锁没有行级别的共享锁,行级别的是排他锁,多个用户可以同时对同一个表加共享锁。通过下面的语句就可以看出来。

Oracle排他锁

示例语句:lock table stat_dic_goods in exclusive mode;

同一张表不能同时执行共享锁和排他锁。

通过lock table in exclusive mode命令添加X锁。在该锁定模式下,其他用户不能对表进行任何的DML和DDL操作,该表上只能进行查询。

Oracle行级排他锁

当我们进行DML时会自动在被更新的表上添加RX锁,或者也可以通过执行lock命令显式的在表上添加RX锁。在该锁定模式下,允许其他的事务通过DML语句修改相同表里的其他数据行,或通过lock命令对相同表添加RX锁定,但是不允许其他事务对相同的表添加排他锁(X锁)。

参考了这里:http://www.cnblogs.com/hsz1124/p/7409981.html

找了相关资料理解的还不是懂

Oracle共享行级排他锁

通过lock table in share row exclusive mode命令添加SRX锁。该锁定模式比行级排他锁和共享锁的级别都要高,这时不能对相同的表进行DML操作,也不能添加共享锁。

找了相关资料理解的还不是懂

TM锁,表级锁;

TX(事务)锁;

lock只会给表上锁(TM锁),select for update,insert,delete,update既给表上锁(TM锁),也给行上锁(TX锁)。select for update给表上行共享锁,insert,delete,update给表上行排他锁。

数据库的隔离级别

回头看看数据库的隔离级别:

隔离级别就是对事务并发控制的等级。ANSI/ ISO SQL将其分为串行化(SERIALIZABLE)、可重复读(REPEATABLE READ)、读已提交(READ COMMITED)、读未提交(READ UNCOMMITED)四个等级。为了实现隔离级别通常数据库采用锁(Lock)。一般在编程的时候只需要设置隔离等级,至于具体采用什么锁则由数据库来设置。

Oracle: Read Commited

MySQL : Repeatable Read

Oracle默认情况下,读数据不加锁,而是通过回滚段防止脏读和保证可重复读。

Oracle具有死锁检查功能,周期性检查系统是否有死锁,如果存在死锁,则撤销执行更新操作次数最少的事务。

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQLOracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!要是对应的SQL语句没有走索引,则会锁掉整张表。

Mysql

Mysql只有在InnoDB引擎下才支持行锁和表锁。Mysql的默认引擎就是innoDB。

MySQL默认操作模式就是autocommit自动提交模式(值为1)。这就表示除非显式地开始一个事务,否则每个查询都被当做一个单独的事务自动执行。我们可以通过设置autocommit的值改变是否是自动提交autocommit模式。

可以手动设置:set autocommit = 0;则将自动提交关闭了。

示例:

悲观锁:

begin;

select * from goods where id = 1 for update;

update goods set stock = stock - 1 where id = 1;

commit;

乐观锁:(已改造)

#不加锁获取 id=1 的商品对象

select * from goods where id = 1

begin;

#更新 stock 值,这里需要注意 where 条件 “stock = cur_stock”,只有程序中获取到的库存量与数据库中的库存量相等才执行更新

update goods set stock = stock - 1 where id = 1 and stock = cur_stock;

commit;

程序中大多用的是乐观锁,悲观锁

与oracle差异:

Mysql支持:select * from orders for update wait 6 –语法错误

select * from orders for update nowait 6 ; –语法错误

还没有总结完,后续补充

项目组用的jpa。谢谢jpa的配置吧

@Repository 

public interface JobInfoDao extends JpaRepository<JobInfo, Long> {

    @Query(value = "select j from JobInfo j where j.jobName = :jobname ") 

public JobInfo getJobForUpdate(@Param("jobname") String jobname); 

    @Lock(value = LockModeType.PESSIMISTIC_WRITE) 

    @Query(value = "select j from JobInfo j where j.id = :id ") 

public void getJobByIdForUpdate(@Param("id") Long id); 

@Lock(value = LockModeType.PESSIMISTIC_WRITE) // TODO 千万不要用这个哦! 

    @Query(value = "select j from JobInfo j where j.jobName = :jobname ") 

public void getJobByNameForUpdate(@Param("jobname") String jobname); 

} 

.jpa如何搞 select for update。

也是醉了,在Dao层的方法上,要配置Lock的注解。并且要加上LockModeType.PESSIMISTIC_WRITE ,这个就相当于for update了。大家也可以在程序运行时,打印出的sql中看到。

ALTER TABLE pay_bill
CHANGE COLUMN `created_time` `created_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ;

ALTER TABLE  order
CHANGE COLUMN `created_time` `created_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ;

ALTER TABLE refund
CHANGE COLUMN `created_time` `created_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ;

mysql中 for update 使用的更多相关文章

  1. 在MySQL中阻止UPDATE语句没有添加WHERE条件的发生

    如果在生产环境中使用UPDATE语句更新表数据,此时如果忘记携带本应该添加的WHERE条件,那么..Oh,no…后果可能不堪设想.那么有没有什么办法可以阻止这样的事情发生,又不使用任何的审核工具呢.. ...

  2. mysql中【update/Delete】update中无法用基于被更新表的子查询,You can't specify target table 'test1' for update in FROM clause.

    关键词:mysql update,mysql delete update中无法用基于被更新表的子查询,You can't specify target table 'test1' for update ...

  3. bash中使用mysql中的update命令

    mysql -uroot -ppasswd -e "update tbadmin set sPassword ='************' where sUserName='admin'& ...

  4. Mysql中,update语句引起的时间戳自动更新问题

    前几天遇到一个奇怪的问题. 在Mysql数据库中有一张表,表中有一个字段是timestamp类型的.我在update别的字段时,这个timestamp字段的时间会自动更新为当前时间. 后来发现,是My ...

  5. mysql中使用update select

    UPDATE t_user INNER JOIN t_shake ON t_shake.user_id = t_user.user_id SET t_user.shake_total_num = t_ ...

  6. Mysql中不能update自身的解决方法

    不能执行:update bi_data.order_all_detailset err_msg='同时存在于wx,zfb平台',proc_time=now()where order_no in( se ...

  7. MySQL中的 ”SELECT FOR UPDATE“ 一次实践

    背景 最近工作中遇到一个问题,两个不同的线程会对数据库里的一条数据做修改,如果不加锁的话,会得到错误的结果. 就用了MySQL中for update 这种方式来实现 本文主要测试主键.唯一索引和普通索 ...

  8. sqlserver 中数据导入到mysql中的方法以及注意事项

    数据导入从sql server 到mysql (将数据以文本格式从sqlserver中导出,注意编码格式,再将文本文件导入mysql中): 1.若从slqserver中导出的表中不包含中文采用: bc ...

  9. MySQL 中删除的数据都去哪儿了?

    不知道大家有没有想过下面这件事? 我们平时调用 DELETE 在 MySQL 中删除的数据都去哪儿了? 这还用问吗?当然是被删除了啊 那么这里又有个新的问题了,如果在 InnoDB 下,多事务并发的情 ...

随机推荐

  1. YTU 2414: C语言习题 字符串排序

    2414: C语言习题 字符串排序 时间限制: 1 Sec  内存限制: 128 MB 提交: 656  解决: 305 题目描述 输入n个字符串,将它们按字母由小到大的顺序排列并输出.编写三个函数实 ...

  2. shinx索引部分源码分析——过程:连接到CSphSource对应的sql数据源,通过fetch row取其中一行,然后解析出field,分词,获得wordhit,最后再加入到CSphSource的Hits里

    CSphSource 数据源 CSphSource_XMLPipe2-XML文件获取数据 CSphSource_SQL-SQL(MySQL)获取数据 CSphIndex 索引器 派生类CSphInde ...

  3. java.lang.NoSuchMethodError: org.springframework.web.context.ConfigurableWebApplicationContext.setId

    运行spring报了这个错误,网上说是spring版本冲突,检查maven依赖,发现我依赖的是spring-core.3.0.5,但是spring-orm和spring-tx依赖了spring-bea ...

  4. pascal倒序输出

    program Project6; {$APPTYPE CONSOLE} uses SysUtils; var a,b,c,d:integer; begin { TODO -oUser -cConso ...

  5. ubuntu /etc/profile和/etc/environment的比较 (转载)

    转自:http://blog.csdn.net/teamlet/article/details/8257853 先将export LANG=zh_CN加入/etc/profile ,退出系统重新登录, ...

  6. bzoj 3398: [Usaco2009 Feb]Bullcow 牡牛和牝牛【dp】

    设f[i]为i为牡牛的方案数,f[0]=1,s为f的前缀和,f[i]=s[max(i-k-1,0)] #include<iostream> #include<cstdio> u ...

  7. bzoj 4078: [Wf2014]Metal Processing Plant【二分+2-SAT+枚举+并查集】

    枚举从大到小s1,二分s2(越大越有可能符合),2-SAT判断,ans取min 思路倒是挺简单的,就是二分的时候出了比较诡异的问题,只能二分s2的值,不能在数组上二分... 有个优化,就是当不是二分图 ...

  8. 【OpenJ_Bailian - 4001】 Catch That Cow(bfs+优先队列)

    Catch That Cow Descriptions: Farmer John has been informed of the location of a fugitive cow and wan ...

  9. springboot(五) 加载配置文件优先级顺序

    github代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-service ...

  10. 组合数的几种球阀 By cellur925

    先来了解几个概念:排列数,组合数. 一.定义及有用的性质 排列数:从n个不同元素中依次取出m个元素排成一列的方案数.P(n,m)=n!/(n-m)! 组合数:从n个不同元素中依次取出m个元素形成一个集 ...