锁会带来三种问题。
1. 脏读
在不同的事务下,当前事务可以读到另外事务未提交
的数据。
发生的条件
事务隔离级别为:Read uncommitted。
使用场景
主从复制环境中,slave节点可以设为Read uncommitted。
2. 不可重复读
在一个事务内多次读取同一数据集合。在这个事务还没有结束时,另外一个事务也访问该同一数据集合,并做了一些DML操作。因此,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据不一样
的情况,这种情况称为不可重复读
。
和脏读的区别
脏读是读到未提交
的数据,而不可重复读读到的却是已经提交
的数据,但是其违反了数据库事务一致性的要求。
一般来说
,不可重复读的问题是可以接受的
,因为其读到的是已经提交的数据,本身并不会带来很大的问题。因此,很多数据库厂商(如Oracle、MicrosoftSQLServer)将其数据库事务的默认隔离级别设置为READCOMMITTED,在这种隔离级别下允许不可重复读的现象
。
3. 丢失更新
一个事务的更新操作会被另一个事务的更新操作所覆盖,从而导致数据的不一致。
要避免丢失更新发生,需要让事务在这种情况下的操作变成串行化
,而不是并行的操作。
即对用户读取的记录
加上一个排他X锁
,注意这需要在同一个事务中,然后再更新,提交事务之后,才会释放排他锁。
举例:
begin;
-- 查询的时候,在后面加上 for update,即加排他锁;
select * from account where id = 10 for update;
-- update
update account set balance = 30000 where id = 10;
commit;
网友评论