mysql如何用事务和锁 锁住某一行数据,使得不允许两个用户同时读取一行数据!!

mysql是InnoDB,图片中的是我自己写的,但是我测试了一下两个用户同时操作是可以读取到同一行数据,求教各位有什么好的方法,可以使得多个用户不能同时读取到同一行数据!

1、在mysql数据库中如何锁定一行数据,保证不被其他的操作影响。

2、从对数据的操作类型分为读锁和写锁。从对数据操作的粒度来分:表锁和行锁。

3、现在我们建立一个表来演示数据库的行锁讲解。

4、行锁基本演示如下图所示。

5、如果两个会话操作的是不同的行,就不会互相阻塞了。

温馨提示:内容为网友见解,仅供参考
第1个回答  推荐于2017-12-16
在使用SQL时,大都会遇到这样的问题,
你Update一条记录时,需要通过Select来检索出其值或条件,
然后在通过这个值来执行修改操作。
但当以上操作放到多线程中并发处理时会出现问题:某线程select了一条记录但还没来得及update时,另一个线程仍然可能会进来select到同一条记录。一般解决办法就是使用锁和事物的联合机制:http://blog.csdn.net/smartyaya/article/details/1423995

参考资料:http://blog.csdn.net/smartyaya/article/details/1423995

本回答被网友采纳
第2个回答  2012-04-03
使用 innodb引擎,是行级锁的。追问

那具体怎样实现呢?

第3个回答  2012-04-03
这个是不能实现的,mysql就算锁住单行数据,但是其他线程还是会有读锁的,我觉得你要实现这样的功能,你可以给这个表再加上个字段,用于表示是否被某个线程读取,被读取的时候可以把这个标志位改成1,然后其他线程在select的时候根据这个标识位为0的,这样就无法读取到了追问

你说的 这种方式我试了的确是可以用,但是多次测试下来还是有低概率出现 两个用户同时取到同一条数据的情况!

追答

恩,那这样的话,只能用其他程序来进行限制了,比如同步锁,把读取数据的方法加个同步锁,然后每次调用这个方法的时候都是排队调用的,再加上表中标识位的设置,完全可以屏蔽两个线程同时读取同一条数据的情况

本回答被提问者和网友采纳
第4个回答  2020-07-06

加锁情况与死锁原因分析

为方便大家复现,完整表结构和数据如下:

CREATE TABLE `t3` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` int(11) DEFAULT NULL,
PRIMARY KEY (`c1`),
UNIQUE KEY `c2` (`c2`)
) ENGINE=InnoDB

insert into t3 values(1,1),(15,15),(20,20);


在 session1 执行 commit 的瞬间,我们会看到 session2、session3 的其中一个报死锁。这个死锁是这样产生的:

    1. session1 执行 delete  会在唯一索引 c2 的 c2 = 15 这一记录上加 X lock(也就是在MySQL 内部观测到的:X Lock but not gap);

    2. session2 和 session3 在执行 insert 的时候,由于唯一约束检测发生唯一冲突,会加 S Next-Key Lock,即对 (1,15] 这个区间加锁包括间隙,并且被 seesion1 的 X Lock 阻塞,进入等待;

    3. session1 在执行 commit 后,会释放 X Lock,session2 和 session3 都获得 S Next-Key Lock;

    4. session2 和 session3 继续执行插入操作,这个时候 INSERT INTENTION LOCK(插入意向锁)出现了,并且由于插入意向锁会被 gap 锁阻塞,所以 session2 和 session3 互相等待,造成死锁。

    死锁日志如下: 

    INSERT INTENTION LOCK

    在之前的死锁分析第四点,如果不分析插入意向锁,也是会造成死锁的,因为插入最终还是要对记录加 X Lock 的,session2 和 session3 还是会互相阻塞互相等待。

    但是插入意向锁是客观存在的,我们可以在官方手册中查到,不可忽略:

    Prior to inserting the row, a type of gap lock called an insert intention gap lock is set. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.

    插入意向锁其实是一种特殊的 gap lock,但是它不会阻塞其他锁。假设存在值为 4 和 7 的索引记录,尝试插入值 5 和 6 的两个事务在获取插入行上的排它锁之前使用插入意向锁锁定间隙,即在(4,7)上加 gap lock,但是这两个事务不会互相冲突等待。

    当插入一条记录时,会去检查当前插入位置的下一条记录上是否存在锁对象,如果下一条记录上存在锁对象,就需要判断该锁对象是否锁住了 gap。如果 gap 被锁住了,则插入意向锁与之冲突,进入等待状态(插入意向锁之间并不互斥)。总结一下这把锁的属性:

    1. 它不会阻塞其他任何锁;

    2. 它本身仅会被 gap lock 阻塞。

    在学习 MySQL 过程中,一般只有在它被阻塞的时候才能观察到,所以这也是它常常被忽略的原因吧...

    GAP LOCK

    在此例中,另外一个重要的点就是 gap lock,通常情况下我们说到 gap lock 都只会联想到 REPEATABLE-READ 隔离级别利用其解决幻读。但实际上在 READ-COMMITTED 隔离级别,也会存在 gap lock ,只发生在:唯一约束检查到有唯一冲突的时候,会加 S Next-key Lock,即对记录以及与和上一条记录之间的间隙加共享锁。

    通过下面这个例子就能验证:

    这里 session1 插入数据遇到唯一冲突,虽然报错,但是对 (15,20] 加的 S Next-Key Lock 并不会马上释放,所以 session2 被阻塞。另外一种情况就是本文开始的例子,当 session2 插入遇到唯一冲突但是因为被 X Lock 阻塞,并不会立刻报错 “Duplicate key”,但是依然要等待获取 S Next-Key Lock 。

    有个困惑很久的疑问:出现唯一冲突需要加 S Next-Key Lock 是事实,但是加锁的意义是什么?还是说是通过 S Next-Key Lock 来实现的唯一约束检查,但是这样意味着在插入没有遇到唯一冲突的时候,这个锁会立刻释放,这不符合二阶段锁原则。这点希望能与大家一起讨论得到好的解释。

    如果是在 REPEATABLE-READ,除以上所说的唯一约束冲突外,gap lock 的存在是这样的:

    普通索引(非唯一索引)的S/X Lock,都带 gap 属性,会锁住记录以及前1条记录到后1条记录的左闭右开区间,比如有[4,6,8]记录,delete 6,则会锁住[4,8)整个区间。

    对于 gap lock,相信 DBA 们的心情是一样一样的,所以我的建议是:

    1. 在绝大部分的业务场景下,都可以把 MySQL 的隔离界别设置为 READ-COMMITTED;

    2. 在业务方便控制字段值唯一的情况下,尽量减少表中唯一索引的数量。

    锁冲突矩阵

    前面我们说的 GAP LOCK 其实是锁的属性,另外我们知道 InnoDB 常规锁模式有:S 和 X,即共享锁和排他锁。锁模式和锁属性是可以随意组合的,组合之后的冲突矩阵如下,这对我们分析死锁很有帮助。

mysql如何用事务和锁 锁住某一行数据,使得不允许两个用户同时读取一行数 ...
1、在mysql数据库中如何锁定一行数据,保证不被其他的操作影响。2、从对数据的操作类型分为读锁和写锁。从对数据操作的粒度来分:表锁和行锁。3、现在我们建立一个表来演示数据库的行锁讲解。4、行锁基本演示如下图所示。5、如果两个会话操作的是不同的行,就不会互相阻塞了。

一文详解-MySQL 事务和锁
所有事务只能看见已经提交事务所做的改变,此级别可以解决脏读,但也会导致不可重复读(Nonrepeatable Read):首先开启 A 和 B 两个事务,A事务读取了 B 事务的数据,在 B 事务更新并提交后,A 事务又读取到了更新后的数据,此时就出现了同一 A 事务中的查询出现了不同的查询结果 MySQL 默认的事...

MySQL数据库的两段锁机制及其应用mysql两段锁
假设有两个事务需要对同一表中的数据进行修改操作。事务A为用户购买商品时扣除库存,事务B为管理员修改数据时增加库存。为避免数据出现错误,需要对数据进行加锁,以保证同时只能有一个事务进行修改。1. 事务A首先需要对商品信息表中对应商品行加排他锁,以实现减少库存操作:BEGIN;SELECT * FROM `商品信...

MySQL多版本锁机制全解析mysql个版本的锁机制
1. 共享锁:共享锁又称为读锁,多个事务可以同时获取该锁,读取相同的数据,但不能进行修改。共享锁可以避免脏读(Dirty Reads)和不可重复读(Non-Repeatable Reads)。2. 排它锁:排它锁又称为写锁,只能有一个事务获取该锁,进行修改操作。排它锁可以避免脏写(Dirty Writes)。锁粒度 锁粒度...

MySQL是如何实现事务的ACID
意向锁:意向锁是表级锁,如果在一个事务已经对一个表中的某个数据加上了排他锁或共享锁,那么就可以加上意向锁,这样当下一个事务来进行锁表的时候发现已经存在意向锁了,就会先被阻塞,如果不加意向锁的话,第二个事务来锁表的时候需要一行一行的遍历查看是否有数据已经被锁住了。间隙锁:间隙锁是...

MySQL的两阶段锁功能及其应用场景解析mysql两阶段锁
二、MySQL两阶段锁原理 MySQL两阶段锁分为共享锁和排他锁两个阶段。当事务需要对某个数据行进行操作时,首先需要获取共享锁(读锁),确保该数据行不会被其它事务修改。在事务执行期间,如果该数据行被其它事务占用且需要修改,则必须等待前一个事务释放该占用。等待过程中,MySQL将会等待并阻塞当前事务...

mysql数据库锁:行锁
共享锁,也称为读锁(S锁),允许其他事务读取这行数据,但不能进行修改。排它锁,也称为写锁(X锁),禁止其他事务查询、添加、修改或删除这行数据。需要注意的是,行级锁仅在事务中有效。在一个事务开始后,直到事务提交或回滚之前,才能对数据行进行锁定。以下为行锁发生的命令:select...for ...

MySQL中的悲观锁保护数据的可行之道mysql悲观锁
Write lock会锁定一行数据,以防止其他事务访问相同数据。 这种锁会阻止任何类型操作,包括读取写入。 获取写锁时,你可以使用如下代码:SELECT * FROM table WITH(WRLOCK);Row lock 锁定的是某行数据,而不是整个表。 这种锁会阻止其他事务访问该行,从而减少事务引起的数据库行为冲突。 下面的指令将...

MySQL中的共享锁 排他锁 意向锁、 架构与存储引擎
MySQL锁机制分为表锁和行锁,其中行锁包括共享锁与排他锁。共享锁(S锁)允许多个事务读取同一数据,但禁止其他事务写入。排他锁(X锁)禁止其他事务对同一数据进行任何操作,包括读取和写入。共享锁与排他锁的主要区别在于:共享锁仅允许读取数据,不允许修改;而排他锁在加锁后,持有事务既可读取数据...

MySQL解释器防幻读算法用户并发修改数据时请求统一锁释放防止幻读现象存...
在执行该语句时,MySQL会自动锁定整个表,从而保证了其他并发事务无法修改这个表中的数据,从而避免了幻读现象的发生。综上所述,MySQL解释器防幻读算法是一种保障并发修改数据的一致性的算法,它通过锁定数据行和表的方式来避免多个用户同时更改同一行或同一表的数据,防止幻读现象的存在,保证数据库数据...

相似回答