`
dingjun1
  • 浏览: 208257 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

并发问题可能导致的脏数据

阅读更多
在整理应用中旧系统数据移植的问题,发现表中出现了几条异常记录,记录除主键不同外,记录的时间和其它内容完全一致。
业务本身的逻辑是,如果碰到数据库中有相关的记录需要把这些记录置为无效,然后插入一条记录。现在是出现了二条有效的记录,是违背业务逻辑本意的。

猜测问题可能出在
1、重复提交表单引起的
2、两个人同时进行相同的操作引起的
3、由于生产环境使用了集群,当不同的人访问不同的集群上的节点时,也会导致这个问题

避免1,2,系统改动不会太大,如果避免3引起的问题,就不是那么好搞了。
市检办案系统虽然使用的人不是太多,但是有些模块会有集中使用的情况,由3导致问题的机率也会增大。


--trancation start
update tab set flag=2 where flag=1 and id=10;
insert into tab values(1,10);
--trancation complete
两个事务并行时,两个事务同时运行到update 语句,由于表中并没有满足条件的记录,update语句并没有使其中的一个事务挂起。这时就出现两条相同数据的语句。

如果说update时,数据表中有满足条件的语句,由于获取不到相同行的排他锁,其中一个事务是会被挂起的,就相当两个事务是串行的了。

初次解决方案(失败):
1、可以把事务的隔离级别设为Serializable(Oracle缺省是Read committed);

如果update没有更新记录,是不存在幻想读的。

(一个事务中,查询时看到了另一个已完成事务的插入记录),update时,由于更新为0,所以不会导致事务失败。还是会有两条相同记录插入到了表中。
serializable并不是对事务串行执行。可以考虑用锁,比如在另一张表t_mylock中放一条记录,永久不删,事务开始时使select * from t_mylock for update。让事务真正串行
--trancation start
--set transaction isolation level serializable;
select * from t_mylock for update;
update tab set flag=2 where flag=1 and id=10;
insert into tab values(1,10);
--trancation complete


ps: serializable 可能会报不能序列化访问的错误,在实际应用中可能不太合适。
ora-08177 :cann't serialize access for this transaction
如果update时,更新了其它事务提交的记录(当前事务开始时还看不到这条记录)就会报这个错。




解决方案:

2、使用select t from table_lock  for update 及在数据库端使用锁,这条语句有一个前提是必须要有记录,才能起到阻塞的效果。
--trancation start
select id from table_mylock where id=1 for update;(表table_mylock中有满足条件的记录)
update tab set flag=2 where flag=1 and id=10;
insert into tab values(1,10);
--trancation complete
分享到:
评论

相关推荐

    并发控制指的是当多个用户同时更新行时,用于保护数据库完整性的各种技术。并发机制不正确可能导致脏读、幻读和不可重复读等此类问题。

    并发控制指的是当多个用户同时更新行时,用于保护数据库完整性的各种技术。并发机制不正确可能导致脏读、幻读和不可重复读等此类问题。

    三级封锁机制实现数据不一致问题

    通过具体的例子实现。通过三级封锁机制实现并发操作导致的数据不一致(丢失更新问题、读过时的数据、读“脏”数据)。

    分析MySQL并发下的问题及解决方法

    对于数据库系统来说在多用户并发条件下提高并发性的同时又要保证数据的一致性一直是数据库系统追求的目标,既要满足大量并发访问的需求又必须保证在此条件下数据的安全,为了满足这一目标大多数数据库通过锁和事务...

    数据库九(并发控制)

    事务并发执行带来的问题 ...读脏数据:事务T1修改某一数据后写回磁盘,T2读取同一数据后,T1却被撤销了 并发控制主要技术: 有封锁、时间戳、乐观控制法。 二、封锁: 一个事务对某个数据对象加锁后究竟拥有什么样

    msyql锁、事务隔离级别各种场景验证测试.rar

    我们的数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能 就会导致我们说的脏写、脏读、不可重复读、幻读这些问题。 这些问题的本质都是数据库的多事务并发问题,为了...

    ------事务的隔离级别

    更新丢失(Lost update):两个事务都同时更新一行数据但是第二个事务却中途失败退出导致对数据两个修改都失效了这是系统没有执行任何锁操作因此并发事务并没有被隔离开来 2. 脏读取(Dirty Reads):一个事务开始...

    分布式面试题免费下载咯.md

    2,建唯一索引:唯一索引或唯一组合索引来防止新增数据存在脏数据 (当表存在唯一索引,并发 时新增异常时,再查询一次就可以了,数据应该已经存在了,返回结果即可)。 3,token机制:由于重复点击或者网络重发,...

    数据库原理与应用.docx

    系统故障 正确答案: A 并发操作若不加控制的话,可能带来数据不一致问题不包括 A.不可重复读 B.丢失修改 C.可重复读 D.读脏数据 数据库原理与应用全文共77页,当前为第2页。数据库原理与应用全文共77页,当前为第2...

    基于更新SQL语句理解MySQL锁定详解

    数据库是一个多用户共享的资源,当出现并发的时候,就会导致出现各种各样奇怪的问题,就像程序代码一样,出现多线程并发的时候,如果不做特殊控制的话,就会出现意外的事情,比如“脏“数据、修改丢失等问题。...

    SQL Server事务的隔离级别

     两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。  脏读(Dirty Reads)  一个事务开始读取了...

    程序员5个刷题网站-InterviewFAQ-database:总结数据库部分的面试常见问题

    这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。 不过理论上会导致幻读(Phantom Read)。 幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行...

    题库系统源码.zip

    魔众题库系统基于PHP开发,可以用于题库管理和试卷生成软件,拥有极简界面和强大的...·[Bug修复] 部分脏数据导致的试卷答案页面报错 ·[Bug修复] 题目分类缓存清除异常问题 ·[Bug修复] 后台用户状态修改失败问题

    魔众题库系统 v7.6.0.zip

    魔众题库系统基于PHP开发,可以用于题库管理和试卷生成软件,拥有极简界面和强大的...·[Bug修复] 部分脏数据导致的试卷答案页面报错 ·[Bug修复] 题目分类缓存清除异常问题 ·[Bug修复] 后台用户状态修改失败问题

    mysql数据库my.cnf配置文件

    # innodb主线程刷新缓存池中的数据,使脏数据比例小于90% innodb_lock_wait_timeout = 120 # InnoDB事务在被回滚之前可以等待一个锁定的超时秒数。InnoDB在它自己的锁定表中自动检测事务死锁并且回滚事务。InnoDB用...

    MySQL管理之道 性能调优、高可用与监控.part2.rar

    1.1.10 提高默认innodb线程并发数 21 1.1.11 预读算法的变化 22 1.1.12 首次在linux上实现了异步i/o 23 1.1.13 恢复组提交 24 1.1.14 innodb使用多个回滚段提升性能 26 1.1.15 改善清除程序进度 26 .1.1.16 ...

    简述MySql四种事务隔离级别

    隔离级别: ... 事务可以读取未提交的数据, 这也被称为脏读 (Dirty Read). 这个级别会导致很多问题,从性能上来说, READ UNCOMMITTED 不会比其他的级别好太多, 但却缺乏其他级别的很多好处, 除非真的

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【集合】HashMap在并发场景下的问题和解决方案 67 多线程put后可能导致get死循环 67 多线程put的时候可能导致元素丢失 68 解决方案 68 【集合】ConcurrentHashMap的get(),put(),又是如何实现的?ConcurrentHashMap...

Global site tag (gtag.js) - Google Analytics