首页 > 那些ORM的库要怎么解决+1-1这样时的安全问题

那些ORM的库要怎么解决+1-1这样时的安全问题

简单的说就是我要执行

update table set value = value + 1 where id = XXX

这样的语句,我在可是似乎并不是所有的ORM库都支持这种操作,举个栗子,我在rails里面有看到update可以支持传入+1、-1这样的参数。可是我在nodejs的jugglingdb里面居然没有找到。

MySQL.prototype.toFields = function (model, data) {
    var fields = [];
    var props = this._models[model].properties;
    Object.keys(data).forEach(function (key) {
        if (props[key]) {
            var value = this.toDatabase(props[key], data[key]);
            if ('undefined' === typeof value) return;
            fields.push('`' + key.replace(/\./g, '`.`') + '` = ' + value);
        }
    }.bind(this));
    return fields.join(',');
};
MySQL.prototype.toDatabase = function (prop, val) {
    if (val === null) return 'NULL';
    if (val === undefined) return;
    if (val.constructor.name === 'Object') {
        var operator = Object.keys(val)[0]
        val = val[operator];
        if (operator === 'between') {
            return  this.toDatabase(prop, val[0]) +
                    ' AND ' +
                    this.toDatabase(prop, val[1]);
        } else if (operator == 'inq' || operator == 'nin') {
            if (!(val.propertyIsEnumerable('length')) && typeof val === 'object' && typeof val.length === 'number') { //if value is array
                for (var i = 0; i < val.length; i++) {
                    val[i] = this.client.escape(val[i]);
                }
                return val.join(',');
            } else {
                return val;
            }
        }
    }
    if (!prop) return val;
    if (prop.type.name === 'Number') return Number(val);
    if (prop.type.name === 'Date') {
        if (!val) return 'NULL';
        if (!val.toUTCString) {
            val = new Date(val);
        }
        return '"' + dateToMysql(val) + '"';
    }
    if (prop.type.name == "Boolean") return val ? 1 : 0;
    if (typeof prop.type === 'function') return this.client.escape(prop.type(val));
    return this.client.escape(val.toString());
};

可以看出,完全不支持。

可是这十分不应该,+1-1这种操作明显是需要线程安全的(nodejs的话就是进程级别了……)可是ORM的select操作是不带锁的(带了也没用啊……)这样出错的概率非常的大。要怎么解决这个问题?

我并不想对原有代码做太多改动,不然我也不会用ORM的库了,能否他通过一些技巧达到这个目的,或者有什么别的OR妈的库可以推荐的吗?


不是很懂node和你用的框架,对于+1-1这种操作我见过两种方法,第一种比较粗暴的就是使用事务,事务会根据隔离等级对记录加上一个独占锁使得你的修改是安全的,就是悲观锁方案;还有一种乐观锁方案,就是先读取原值,update的时候在where条件里添加'value=老值'这样的限制条件,如果记录已经被别人修改了那么你的修改返回的影响行数会是0,你就知道修改失败了,要重新读取再修改了。悲观锁在高烈度竞争下性能比较好,乐观锁在低烈度竞争下性能比较好,视情况而定了。

【热门文章】
【热门文章】