距离上一次写博客已经过去了1年多的时间,现在看来当时写的感想博客用处还是挺大的,给我了许多的动力。在过去的1年中博主的功力也是有了渐增,以后也会多写技术博文分享经验,当然博主的实力也是有限,也希望能和大家多多交流~
废话不多说,开始说问题:
最近在学习用node写web后端时遇见了一个问题。在前端提交记录数据后,在后端写入数据库后需要获得该条记录自增长型id值,并返回给前端。这个问题就出在插入数据后获取自增长的id的过程,由于node是异步处理多用户请求,不难想象在多用户并发操作的情况下会出现:在a用户插入一条记录后未进行查找该条记录自增长型id值时,b用户紧跟插入一条数据,a再进行查找自增长型id值的情况。让我们绘制一个表格来说明这个问题:
时间序列 | 用户A | 用户B |
---|---|---|
1 | 插入记录a | |
2 | 插入记录b | |
3 | 查询记录自增id | |
4 | 查询记录自增id |
从表格过程显示不难得出结论,不能用一般的方法,即查询表最后一条插入的记录id的方式来进行查询。
博主用的是mysql模块来连接数据库的,npm安装代码:
npm install --save mysql
下面是在后端项目中的连接代码:
const db=mysql.createPool({
host:'localhost',
user:'root',
password:'wolf1234',
database:'kunpeng_note',
multipleStatements:true,
});
这里可以注意到用的是连接池的方式,避免每次连接数据库时都要重复创建连接。连接池维持着几十条连接,每次执行sql语句时直接调用连接池执行即可,连接池会选用一条连接执行sql语句:
db.query("UPDATE plans SET state=0 WHERE id="+plan.id+" AND username='"+req.session.username+"';",
function(err,data){
if (err) {
console.log(err);
res.status(200).json({ok:0}).end();
}else{
res.status(200).json({ok:1}).end();
}
});
下面开始介绍解决方案:
1、SELECT max(id) FROM TABLENAME;
即查找表最后一次插入的字段id值,但是正如之前所说解决不了多用户插入和查找的情况。
2、SELECT LAST_INSERT_ID();
LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变。在多用户交 替插入数据的情况下max(id)显然不能用。这时就该使用LAST_INSERT_ID了,因为LAST_INSERT_ID是基于 Connection 的,只要每个线程都使用独立的 Connection对象,LAST_INSERT_ID函数将返回该Connection对AUTO_INCREMENT列最新 的insert or update 操作生成的第一个record的ID。这个值不能被其它客户端(Connection)影响,保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁。使用单INSERT语句插入多条记录, LAST_INSERT_ID返回一个列表。下 面给出代码:
server.post('/index/addPlan',function(req,res){
if (req.session.login) {
plan=req.body;
console.log(plan);
db.getConnection(function(err,connection){
if (err) {
res.status(200).json({ok:0,id:0}).end();
}else{
connection.query("INSERT INTO plans (username,title,starttime,finishtime,importance,state) VALUES('"+req.session.username+"','"+plan.title+"','"+plan.starttime+"','"+plan.finishtime+"',"+plan.importance+","+plan.state+");",
function(err,data){
if(err){
console.log(err);
res.status(200).json({ok:0,id:0}).end();
}else{
connection.query("SELECT LAST_INSERT_ID();",
function(err,data){
if (err) {
res.status(200).json({ok:0,id:0}).end();
}else{
res.status(200).json({ok:1,id:data[0]['LAST_INSERT_ID()']}).end();
}
});
}
});
connection.release();
}
});
}else{
res.redirect('/login');
}
});
3、在插入后通过data.insertId来获取值;
这种办法博主并没有进行尝试,但的确是个好方法。即在db.query()中回调函数function(err,data)中data有一个f返回值data.insertId就是自增长型id的值。下面给出参考网址:
https://www.cnblogs.com/houji/p/5179705.html
https://www.2cto.com/database/201504/394487.html
感谢这两篇文章的作者,我也学到很多,在这里作为引用。
下面是博主写的一个web练习项目,代码质量很糙,欢迎修改:
https://github.com/diaopengfei/kunpeng_note.git