• Stopping an expensive calculation temporarily freezing the server
    10 replies, posted
So I've got some mysqloo database things which run every minute or so but they cause tiny freezes every time. I know coroutines can help with this but I've not got the slightest clue how to use them. I have researched but I still don't get it.
Make sure you're not forcing the module to "wait" until the query is finished. MySQLOO and TMySQL both work asynchronously meaning they spread themselves out over x frames ( like how co-routines work ) so unless you specify in the query for it to wait, it should be fine...
Why do you need some queries to run every few minutes in the first place?
And saving values periodically is better than saving the values as soon as they change why?
I'm using it to sync evolve playerinfo to an external database, and PlayTime for example updates it every minute, so I figured a 60 second timer would be a good interval, but I could experiment with setting them as soon as they change, not sure it would help the lag however. Some current code: [code] for k,v in pairs(diff) do local q local t=evolve.PlayerInfo[v] if t then --print("Updating "..t.Nick..".") local values="" for a,b in ipairs(fields) do local val=t[b] if tonumber(val) or val==true then values=values..db:escape(tostring(val)) else values=values.."\""..db:escape(tostring(val)).."\"" end if a~=#fields then values=values.."," end end local qs="replace into playerinfo ("..table.concat(fields,",")..") values("..values..")" --print(qs) q=db:query(qs) else --print("Removing ID: "..v) q=db:query("delete from playerinfo where UID="..v) end if q then function q:onError( err, sql ) print(err) print(sql) end q:start() end end [/code] diff is a table of UIDs that have changes, the entire database is downloaded prior to this to check changes. That's my sort of 'master sync' function, though maybe I could have a separate one just to update values as they come in (by adding it to evolve:SetProperty and Player:SetProperty). Do you think that it's the downloading database or the queries that cause the freezes? I've noticed that the spike is heavier with more players online (and therefore more queries) which indicates that the queries are causing the lag somehow.
I ran into this before with MySQLOO. Very bad performance. I tried wrapping my statements with START TRANSACTION and COMMIT and that relieved some of the hit but I still had reports of lag spikes coming from players. I'd suggest tmysql instead.
Should I be disconnecting and reconnecting to the database each time or keep a persistent connection?
[QUOTE=MattJeanes;46361024]Should I be disconnecting and reconnecting to the database each time or keep a persistent connection?[/QUOTE] Keep a persistent connection, but be able to handle loss of connection.
[QUOTE=MattJeanes;46361024]Should I be disconnecting and reconnecting to the database each time or keep a persistent connection?[/QUOTE] I Also suggest trying to run it as a single query instead of per player. Mysql has a multivalue updater. Table Before the query [IMG]http://andreblue.com/sharex/uploaded/2014-10-30_01:13:01.png[/IMG] After the query [IMG]http://andreblue.com/sharex/uploaded/2014-10-30_01:18:30.png[/IMG] You mark per case where it should be and what to. You also specify a default if you want else you can remove the ELSE 'value' before the end. [CODE]UPDATE test SET rank = CASE WHEN ids=1 THEN 'owner' ELSE 'user' END, rank = CASE WHEN ids=2 THEN 'user' END WHERE ids IN (1,2)[/CODE]
Alright I've fixed the issue based on experiments and your feedback so thank you. Basically gave the code a reshuffle and changed how it works, and now it seems to run async where it didn't before somehow. Full code for anyone interested (uses mysqloo): [code] -- MySQLoo require( "mysqloo" ) local lost=false function Abyss:SQL(callback) if not Abyss.DB or lost then if Abyss.DB then Abyss.DB=nil end --Abyss:Print("New database") local db = mysqloo.connect( -redacted- ) db:connect() function db:onConnected() Abyss.DB = db callback(Abyss.DB) end function db:onConnectionFailed( err ) Abyss:Print("Failed to connect to database: "..err) end else callback(Abyss.DB) end end function Abyss:Query(qs,callback) local db=Abyss:SQL(function(db) local q=db:query(qs) q:start() function q:onSuccess(data) --Abyss:Print("Query successful: "..qs) if callback then callback(data) end end function q:onError(err,sql) Abyss:Print("Query failed: "..err) local status=db:status() if status==mysqloo.DATABASE_NOT_CONNECTED or status==mysqloo.DATABASE_INTERNAL_ERROR then Abyss:Print("Query failed: Database connection lost") lost=true Abyss:Query(qs,callback) end end end) end function Abyss:Escape(str) return sql.SQLStr(str,true) -- Why not end function Abyss:TestQuery() Abyss:Query("select 1+1", function(data) PrintTable(data) end) end [/code]
Sorry, you need to Log In to post a reply to this thread.