lua 数据库 上锁

多进程操作数据库–锁

问题情景:

 A进程与B进程对同一个数据库进行操作,A进程不停插入数据,B进程不停删除数据

 当B在删除数据的同时A去插入数据,此时A的操作会失败,执行结果返回值为5

问题原因:

 操作数据库时,数据库会自动上锁(共享锁、排他锁等),insert语句与delete语句都会上排他锁,delete正在操作时insert无法获取锁,不能进行,该语句执行失败,然后停止。

以下是A进程的demo (A.lua):

#!/usr/bin/lua
--A进程的demo

local sqlite3 = require"lsqlite3"    --require 数据库模块

local sn = "123"
local sqlCreatApCfgTable = "CREATE TABLE apCfg(sn text,data text);"  --创建数据库表语句
local Sqlinsert =  string.format("insert into apCfg(sn,data) values('123','data123');",sn) -- 插入数据语句

local db = sqlite3.open("/test.db")   --打开数据库
db:exec(sqlCreatApCfgTable)           --执行建表语句

while true do                                                               

    ret = db:exec(Sqlinsert)         --执行插入语句
    print(Sqlinsert)               
    print(ret)                       --0为sqlite_ok,执行成功

    if ret ~= 0 then                 --执行失败即停止
        break                           
    end                 

end

 demo中循环插入数据并打印返回值,ret为sql语句执行的返回值,执行成功时ret为0(SQLITE_OK),执行失败时停止。

以下是B进程的demo (B.lua):

#!/usr/bin/lua
--B进程的demo

local sqlite3 = require("lsqlite3")
local db = sqlite3.open("/test.db")

local Sqldelete =  string.format("DELETE FROM apCfg WHERE sn = '%s';","123")

while true do
    ret = db:exec(Sqldelete)
    print(Sqldelete)
    print(ret)
end

 先运行A

lua A.lua &

 后运行B

lua B.lua &

A打印结果:

insert into apCfg (sn,data) values ('123','data123');
0
insert into apCfg (sn,data) values ('123','data123');
0
insert into apCfg (sn,data) values ('123','data123');
5
# 

经查询,5表示数据库正忙,lua的抛出异常提示信息:database is locked (注- exec() 不会抛出异常,nrows()会)

B此时执行delete,并不停止

DELETE FROM apCfg WHERE sn = '123';
0
DELETE FROM apCfg WHERE sn = '123';
0
DELETE FROM apCfg WHERE sn = '123';
0

此时多进程操作数据库,会导致有时操作失败,后续程序会出现错误,因此我们需要添加措施保障sql语句执行正常

解决方法:

  1. 使用sqlite3数据库提供的接口sqlite3_busy_handler()

  2. 使用sqlite3数据库提供的接口sqlite3_busy_timeout()

 这两个函数是C语言中的函数,注册到lua中分别为 busy_handler 与 busy_timeout ,若想在C语言中使用可百度一下。在这里我使用的是busy_handler,方法简单

 使用busy_handler 分两步

  1.定义回调函数

  2.调用busy_handler

 busy_handler设置好,启动后就可以生效了,实际代码如下:

#!/usr/bin/lua
--A进程的demo

local sqlite3 = require"lsqlite3"    --require 数据库模块

local sn = "123"
local sqlCreatApCfgTable = "CREATE TABLE apCfg(sn text,data text);"  --创建数据库表语句
local Sqlinsert =  string.format("insert into apCfg(sn,data) values('123','data123');",sn) -- 插入数据语句

local db = sqlite3.open("/test.db")   --打开数据库
db:exec(sqlCreatApCfgTable)           --执行建表语句


function callback(...)                --定义回调函数                     
    print("callback ")                                                           
    return 1                                                             
end                                                                          
db:busy_handler(callback,1)           --调用busy_handler  


while true do                                                               

    ret = db:exec(Sqlinsert)         --执行插入语句
    print(Sqlinsert)               
    print(ret)                       --0为sqlite_ok,执行成功

    if ret ~= 0 then                 --执行失败即停止
        break                           
    end                 

end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值