在 Node.js 中使用 MySQL 并实现事务以解决并发竞态条件问题

const mysql = require('mysql');

// MySQL 连接配置
const connection = mysql.createConnection({
    host: 'localhost',
    user: 'your_username',
    password: 'your_password',
    database: 'your_database_name'
});

// 连接到 MySQL
connection.connect(err => {
    if (err) {
        console.error('Error connecting to MySQL: ' + err.stack);
        return;
    }
    console.log('Connected to MySQL as id ' + connection.threadId);
});

// 示例函数:增加指定 id 的 item 的值
async function incrementItemValue(itemId, incrementAmount) {
    try {
        // 开始事务
        await beginTransaction(connection);

        // 读取当前值
        const currentValue = await getItemValue(itemId);

        // 模拟一些计算或操作耗时
        await simulateProcessing();

        // 计算新值
        const newValue = currentValue + incrementAmount;

        // 更新数据库中的值
        await updateItemValue(itemId, newValue);

        // 提交事务
        await commitTransaction(connection);

        console.log(`Successfully incremented item ${itemId} value by ${incrementAmount}.`);
    } catch (error) {
        // 发生错误时回滚事务
        await rollbackTransaction(connection);
        console.error('Transaction error:', error);
    }
}

// 开始事务
function beginTransaction(connection) {
    return new Promise((resolve, reject) => {
        connection.beginTransaction(err => {
            if (err) reject(err);
            else resolve();
        });
    });
}

// 提交事务
function commitTransaction(connection) {
    return new Promise((resolve, reject) => {
        connection.commit(err => {
            if (err) {
                connection.rollback(() => {
                    reject(err);
                });
            } else {
                resolve();
            }
        });
    });
}

// 回滚事务
function rollbackTransaction(connection) {
    return new Promise((resolve, reject) => {
        connection.rollback(() => {
            resolve();
        });
    });
}

// 获取指定 id 的 item 的值
function getItemValue(itemId) {
    return new Promise((resolve, reject) => {
        connection.query('SELECT value FROM items WHERE id = ?', [itemId], (error, results) => {
            if (error) {
                reject(error);
            } else {
                resolve(results[0].value);
            }
        });
    });
}

// 更新指定 id 的 item 的值
function updateItemValue(itemId, newValue) {
    return new Promise((resolve, reject) => {
        connection.query('UPDATE items SET value = ? WHERE id = ?', [newValue, itemId], (error, results) => {
            if (error) {
                reject(error);
            } else {
                resolve();
            }
        });
    });
}

// 模拟一些处理耗时的操作
function simulateProcessing() {
    return new Promise(resolve => {
        setTimeout(resolve, Math.random() * 100); // 模拟耗时操作,随机时间
    });
}

// 并发调用模拟
async function simulateConcurrentCalls(numCalls) {
    // 创建并发调用的数组
    const calls = [];
    for (let i = 0; i < numCalls; i++) {
        calls.push(incrementItemValue(1, 10)); // 每次增加10
    }
    
    // 执行所有并发调用
    await Promise.all(calls);
    
    console.log(`All ${numCalls} concurrent calls completed.`);
}

// 执行示例:模拟100次并发调用
simulateConcurrentCalls(100).then(() => {
    console.log('Simulation of 100 concurrent calls completed.');
}).catch(error => {
    console.error('Error in concurrent calls:', error);
});

插入:小编自己封装了一个大文件上传的工具函数,支持切片上传、错误重试、上传进度、暂停和继续等,目前已发布在npm官网,感兴趣的可以看看。

https://www.npmjs.com/package/enlarge-file-upload?activeTab=versions

下载命令:npm i enlarge-file-upload

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值