如何解决事务操作中状态不一致的现象?
2015-09-06 16:38
288 查看
昨天,一个同学问了一个关于事务处理的一个问题。问题的情景是,有一个机柜分里n层,每一层放里一些设备。现在有两个线程,分别对机柜里面的设备做操作。操作之前先检查数据库中设备是不是已经被占用,如果被占用则不去操作,没有被占用则去占用被在设备的置标志位。伪代码描述处理过程如下:
这段代码在单线程的时候运行正常,但是在多线程的时候会存在线程安全的问题,而这种线程不安全表现为事务操作的不一致性。A和B进程同时去占用同一个设备d,A检查数据库设备d的状态位false然后去占用,然后这时A虽然占用里设备d,但是没有还没有更新数据库中的状态,B去检查状态仍然可以去占用d。然后A和B同时更新数据库,就造成里数据库的不一致现象。
解决这种不一致的可以通过应用程序层事务管理或者使用数据库事务来保证占用设备和更新状态在一个原子操作中去完成。应用层可以使用一些框架如Spring实现好的事务去保证,数据库层解决需要修改下数据库的结构。将上面的代码放在一个事务中,就能保证两个线程中的代码不会被乱序执行,A检测设备状态、占用设备和修改数据库要在一步完成,不会受到线程B的打扰。新的数据库结构,新建一个表存储已经被占用设备的id,并且在DeviceId这个字段上建立一个唯一索引。这样插入提示出错就说明设备已经被占用。
if(getStateFromDbByDeviceId(DeviceId)) { 占用设备.... setStateToDbByDeviceId(DeviceId); } else { return; }
这段代码在单线程的时候运行正常,但是在多线程的时候会存在线程安全的问题,而这种线程不安全表现为事务操作的不一致性。A和B进程同时去占用同一个设备d,A检查数据库设备d的状态位false然后去占用,然后这时A虽然占用里设备d,但是没有还没有更新数据库中的状态,B去检查状态仍然可以去占用d。然后A和B同时更新数据库,就造成里数据库的不一致现象。
解决这种不一致的可以通过应用程序层事务管理或者使用数据库事务来保证占用设备和更新状态在一个原子操作中去完成。应用层可以使用一些框架如Spring实现好的事务去保证,数据库层解决需要修改下数据库的结构。将上面的代码放在一个事务中,就能保证两个线程中的代码不会被乱序执行,A检测设备状态、占用设备和修改数据库要在一步完成,不会受到线程B的打扰。新的数据库结构,新建一个表存储已经被占用设备的id,并且在DeviceId这个字段上建立一个唯一索引。这样插入提示出错就说明设备已经被占用。
相关文章推荐
- Android之获取手机上的图片和视频缩略图thumbnails
- 数据库链接字符串查询网站
- DB2实例管理
- DB2实例管理
- 保障MySQL数据安全的14个最佳方法
- mysql问答汇集
- 创建一个空的IBM DB2 ECO数据库的方法
- Access 2000 数据库 80 万记录通用快速分页类
- 开通一个数据库失败的原因的和解决办法
- 一个简单的asp数据库操作类
- CentOS下DB2数据库安装过程详解
- EasyASP v1.5发布(包含数据库操作类,原clsDbCtrl.asp)第1/2页
- sql2008 还原数据库解决方案
- Oracle 数据库自动存储管理-安装配置
- Oracle 数据库 临时数据的处理方法
- 数据库分页查询语句数据库查询
- 最近比较流行的数据库挂马
- 分割超大Redis数据库例子
- 重装主控服务器后,数据库连接失败的解决办法:请正确还原数据库。