FMDB:更新时数据库被锁定

伊丹·莫西(Idan Moshe)

我正在使用FMDBFMDatabase当我想返回一些值时,以及FMDatabaseQueue当我不需要返回任何值时,我都在使用当我添加到数据库并使用时,FMDatabaseQueue我没有任何错误(除非在删除数据库然后创建[没有要删除的数据库,以便创建一个新数据库]的开始时创建新数据库)。问题是当我database用相同的内容更新我FMDatabaseQueue出现错误:

未知错误完成或重置语句(5:数据库已锁定)

数据库查询:UPDATE traps_table SET dist = 34721.853417,dist_to_close_point = 35734.768293 WHERE _id = 10

当我尝试对数据库文件本身进行查询时,我没有收到任何错误,并且一切顺利。

代码如下:

- (void)updateTrapInDatabase:(FMDatabase*)db distance:(double)distance trapID:(int)trapID distanceToClosePoint:(double)distanceToClosePoint
{
    NSString *statment = [NSString stringWithFormat:@"UPDATE %@ SET %@=?, %@=? WHERE %@=?", TRAP_TABLE, DISTANCE, DISTANCE_TO_CLOSE_POINT, ID];
    BOOL update = [db executeUpdate:statment, @(distance), @(distanceToClosePoint), @(trapID)];
    NSLog(@"Update trapID: %i, success: %@", trapID, update?@"YES":[NSString stringWithFormat:@"NO: %@", [db lastErrorMessage]]);
}

该函数引用的代码:

- (void)UpdateDistanceToTrap_currentLocation:(CLLocation*)currentLocation old_location:(CLLocation*)old_location theAzimuth:(double)theAzimuth theSpeed:(double)theSpeed
{
    NSLog(@"UpdateDistanceToTrap()");

    __block double latColumn, lonColumn, idColumn, closePointLatColumn, closePointLonColumn, alarmDistanceColumn;
    __block int _id = -1, alarmDistance = -1;
    __block double distance;
    __block CLLocation *trap_location = nil;

    __block NSString *sqlStatment = [NSString stringWithFormat:@"SELECT * FROM %@", TRAP_TABLE];

    FMResultSet *query = [trapsDB.db executeQuery:sqlStatment];

    if ([query next]) {
        latColumn = [query doubleForColumn:LAT];
        lonColumn = [query doubleForColumn:LON];
        closePointLatColumn = [query doubleForColumn:CLOSE_POINT_LAT];
        closePointLonColumn = [query doubleForColumn:CLOSE_POINT_LON];
        idColumn = [query intForColumn:@"_id"];
        alarmDistanceColumn = [query intForColumn:ALARMDISTANCE];

        do {
            _id = [query intForColumn:@"_id"];
            alarmDistance = [query intForColumn:ALARMDISTANCE];

            if ([old_location distanceFromLocation:currentLocation] > kDISTANCE_THRESHOLD_FOR_CHECK_LOCATIONS) {
                trap_location = [[CLLocation alloc] initWithLatitude:[query doubleForColumn:LAT]
                                                           longitude:[query doubleForColumn:LON]];

                distance = [trap_location distanceFromLocation:currentLocation];

                if (distance < alarmDistance + [ref integerForKey:@"DISTANCE_OFFSET"]) {
                    [trapsDB enterOrOutFromArea_operation:kENTER andTrapID:_id];

                    [self startSaveOnMyLocations:currentLocation.coordinate.latitude
                                             lon:currentLocation.coordinate.longitude
                                            time:CreateDate()
                                           speed:theSpeed
                                         azimuth:theAzimuth
                                          trapID:_id];
                }
                else {
                    if ([trapsDB isEnterToArea_trapID:_id] == kENTER) {
                        [self startPostXml:_id];
                        [trapsDB enterOrOutFromArea_operation:kOUT andTrapID:_id];
                    }
                }
            }
            if ([query doubleForColumn:CLOSE_POINT_LAT] != 0.0 || [query doubleForColumn:CLOSE_POINT_LAT] != 0) {
                trap_location = [[CLLocation alloc] initWithLatitude:[query doubleForColumn:CLOSE_POINT_LAT]
                                                           longitude:[query doubleForColumn:CLOSE_POINT_LON]];

                double distanceToClosePoint = [trap_location distanceFromLocation:currentLocation];

                trap_location = [[CLLocation alloc] initWithLatitude:[query doubleForColumn:LAT]
                                                           longitude:[query doubleForColumn:LON]];

                distance = [trap_location distanceFromLocation:currentLocation];

                [trapsDB updateTrapInDatabase:trapsDB.db distance:distance trapID:_id distanceToClosePoint:distanceToClosePoint];
            }
            else {
                trap_location = [[CLLocation alloc] initWithLatitude:[query doubleForColumn:LAT]
                                                           longitude:[query doubleForColumn:LON]];

                distance = [trap_location distanceFromLocation:currentLocation];

                [trapsDB updateTrapInDatabase:trapsDB.db distance:distance trapID:_id distanceToClosePoint:distance];
            }
        } while ([query next]);
    }
}

我的代码有什么问题?

编辑:

TrapService.mm:

- (void)UpdateDistanceToTrap_currentLocation:(CLLocation*)currentLocation old_location:(CLLocation*)old_location theAzimuth:(double)theAzimuth theSpeed:(double)theSpeed;

#define trapsDB     ([SQLiteHandler sharedDatabase])

SQLiteHandler.m:

@property (strong, nonatomic) FMDatabase *db;

- (void)updateTrapInDatabase:(FMDatabase *)db distance:(double)distance trapID:(int)trapID distanceToClosePoint:(double)distanceToClosePoint;

编辑2:更新了我的固定代码。

您正在inDatabase通话中,遍历SELECT语句,然后尝试进行另一个inDatabase通话。如果要执行此操作,则可能需要将FMDatabase作为参数传递给方法,而不要inDatabase再次调用

- (void)updateTrapInDatabase:(FMDatabase *)db distance:(double)distance trapID:(int)trapID distanceToClosePoint:(double)distanceToClosePoint
{
    NSString *sqlStatment = [NSString stringWithFormat:@"UPDATE %@ SET %@=?, %@=? WHERE %@=?", TRAP_TABLE, DISTANCE, DISTANCE_TO_CLOSE_POINT, ID];

    BOOL update = [db executeUpdate:sqlStatment, @(distance), @(distanceTpClosePoint), @(trapID)];
    NSLog(@"Update trapID: %i, success: %@", trapID, update?@"YES":[NSString stringWithFormat:@"NO: %@", [db lastErrorMessage]]);
}

并替换为:

[trapsDB updateTrapDistance:distance andTrapID:_id andDistanceToClosePoint:distanceToClosePoint];

与:

[trapsDB updateTrapInDatabase:db distance:distance trapID:_id distanceToClosePoint:distanceToClosePoint];

(顺便说一句,?在您的SQL中通常使用占位符(避免与float变量相关的精度问题,避免SQL注入问题和NSString变量引用问题),因此我也对上述SQL进行了调整。此外,如果SQL语句失败,我始终记录日志lastErrorMessage,否则我只是在猜测SQL为什么失败。请根据需要使用或忽略这些无关的调整。)

但是主要的一点是,inDatabase在已经进入通话状态的时候不要打电话inDatabase不过,令人好奇的是,通常inDatabase在已经存在的inDatabase情况下进行调用会导致死锁,而不是“数据库已锁定”错误。坦白地说,的全部目的FMDatabaseQueue是调解来自不同线程的数据库请求,以使数据库永远不会繁忙。你通常会得到唯一的一次“数据库被锁定”如果你有一个以上的错误FMDatabaseQueueFMDatabase对象。您的应用在任何给定时间都只能打开一个数据库对象。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

无法使用SWIFT更新数据库FMDB中的字段

来自分类Dev

无法使用SWIFT更新数据库FMDB中的字段

来自分类Dev

从FMDB数据库中获取数据

来自分类Dev

在实时数据库上更新之前删除索引

来自分类Dev

Firebase实时数据库不会更新值

来自分类Dev

如何更新Firebase实时数据库中的位置?

来自分类Dev

从 Google Cloud Functions 原子更新实时数据库

来自分类Dev

Ionic + Firebase - 实时数据库不更新视图

来自分类Dev

创建/更新/删除 Firebase 实时数据库规则

来自分类Dev

异时数据库

来自分类Dev

实时数据库

来自分类Dev

使用实时数据库更新 Android 应用程序的内部数据库

来自分类Dev

在并发数据库更新时锁定实体框架代码

来自分类Dev

PDO SQLite无法更新记录:“数据库已锁定”

来自分类Dev

SQLite 数据库在更新后被 C# 锁定?

来自分类Dev

更新时如何修复“数据库被锁定”?

来自分类Dev

使用join语句更新数据库时,FMDB语法错误

来自分类Dev

更新Laravel 5.2时数据库中的数据未更新

来自分类Dev

更新Laravel 5.2时数据库中的数据未更新

来自分类Dev

Android 应用程序:从实时数据库到 Firestore - 将数据更新到数据库

来自分类Dev

关于FMDB(Objective-C数据库库)的错误

来自分类Dev

关于FMDB(Objective-C数据库库)的错误

来自分类Dev

火力地堡实时数据库更新数据 - 的Android的Java

来自分类Dev

保留数据时更新实时数据库的最佳方法?

来自分类Dev

Swift Firebase 更新旧数据 - 实时数据库触发器

来自分类Dev

如何使用FMDB在SQLite数据库中保存数据?

来自分类Dev

Firebase实时数据库addValueEventListener

来自分类Dev

实时数据库与Firestore

来自分类Dev

Firebase实时数据库-规则

Related 相关文章

热门标签

归档