Issue information

Issue ID
#7974
Status
Confirmed
Severity
None
Started
Ind
Jan 14, 2014 19:37
Last Post
Ind
Mar 29, 2014 22:16
Confirmation
N/A

Ind - Jan 14, 2014 19:37

Referring to my point brought up in [url="https://github.com/HerculesWS/Hercules/pull/252"]https://github.com/HerculesWS/Hercules/pull/252[/url][quote]
hmm, is it really necessary? new/modified player/acc regs are saved whenever a script instance ends (so pretty much the update query in sql is overwritten by char server's one)[/quote]and fyi, its not new behavior, variables have been saving whenever script instances ended since eathena[code=auto:0]if (Mission_Total == 1) query_sql("INSERT INTO `char_reg_num_db` (`char_id`,`key`,`index`,`value`) VALUES ("+getcharid(0)+",'Mission_Total','0',1)"); else query_sql("UPDATE `char_reg_num_db` SET `value` = "+Mission_Total+" WHERE `char_id` = "+getcharid(0)+" AND `key` = 'Mission_Total'"); [/code]

Euphy - Jan 16, 2014 19:04

From my experience and testing, permanent variables are [i]not[/i] loaded into SQL tables directly after a script finishes. In all the "ranking" scripts I've written, they would not function properly without an external query_sql.

AnnieRuru - Jan 16, 2014 22:43

confirm with euphy
the character data gets update interval in this setting[quote name="conf\map_athena.conf"]
// Database autosave time
// All characters are saved on this time in seconds (example:
// autosave of 60 secs with 60 characters online -> one char is saved every
// second)
autosave_time: 300

// Min database save intervals (in ms)
// Prevent saving characters faster than at this rate (prevents char-server
// save-load getting too high as character-count increases)
minsave_time: 100

// Apart from the autosave_time, players will also get saved when involved
// in the following (add as needed):
// 1: after every successful trade
// 2: after every vending transaction
// 4: after closing storage/guild storage.
// 8: After hatching/returning to egg a pet.
// 16: After successfully sending a mail with attachment
// 32: After successfully submitting an item for auction
// 64: After successfully get/delete/complete a quest
// 128: After every bank transaction (deposit/withdraw)
// NOTE: These settings decrease the chance of dupes/lost items when there's a
// server crash at the expense of increasing the map/char server lag. If your
// server rarely crashes, but experiences interserver lag, you may want to set
// these off.
save_settings: 255[/quote]you can actually adjust this setting to make your server save character data faster/slower


however, I don't like the way using global_reg_value to run the query
its too unoptimized because the `value` field isn't indexed

I would suggest using ALTER TABLE on `char` table to save the data because of several reason
1. I can index it
2. if the character is deleted, it is delete by row, so there is no garbage data if the character deleted
[url="http://rathena.org/board/topic/90971-euphys-mvp-ladder-bug-npc-hides/?p=237993"]http://rathena.org/board/topic/90971-euphys-mvp-ladder-bug-npc-hides/?p=237993[/url]
[url="http://rathena.org/board/topic/91081-mvp-rank/?p=238352"]http://rathena.org/board/topic/91081-mvp-rank/?p=238352[/url]


oh wait ... this is hercules forum lol
but I guess it shouldn't be that far off

This post has been edited by AnnieRuru on Jan 17, 2014 7:34

Ind - Jan 19, 2014 18:13

the setting is misleading, for reference eathena [url="http://eathena-project.googlecode.com/svn/trunk/src/map/script.c"]http://eathena-project.googlecode.com/svn/trunk/src/map/script.c[/url]
at the end of run_script_main[code=auto:0] if (sd->state.reg_dirty&2) intif_saveregistry(sd,2); if (sd->state.reg_dirty&1) intif_saveregistry(sd,1); [/code]the variables are saved on the spot, reg_dirty is flagged when a variable is modified, check pc_setregistry [url="http://eathena-project.googlecode.com/svn/trunk/src/map/pc.c"]http://eathena-project.googlecode.com/svn/trunk/src/map/pc.c[/url] .[code=auto:0] sd->state.reg_dirty |= 1<<(type-1); [/code]

This post has been edited by Ind on Jan 19, 2014 18:14

Ind - Jan 19, 2014 18:22

I've ran a couple tests and confirmed the var is updated right on the spot regardless if it is a new one or a old being modified.

AnnieRuru - Jan 21, 2014 14:20

Ind, I think you misunderstood this lol

its true that the value is update immediately with
set test, 1;
dispbottom test; // display 1

but its not true when the value is update to the SQL table
set test, 1;
//query_sql "select value from global_reg_value where str = 'test' and char_id = "+ getcharid(0), .@value;
// ops ! this is hercules so should be ...
query_sql "select value from char_reg_num_db where key = 'test' and char_id = "+ getcharid(0), .@value;
dispbottom .@value; // display 0

why he want to do like this ?

check his script
[url="https://github.com/HerculesWS/Hercules/blob/master/npc/custom/quests/hunting_missions.txt#L129"]https://github.com/HerculesWS/Hercules/blob/master/npc/custom/quests/hunting_missions.txt#L129[/url]
he tried to simulate a ladder, display the top 5 users with highest hunting points
and his (unoptimized) way to sort the ranking is do select ... order by value desc
--> its unoptimized because the `value` column isn't indexed ! this will search the whole table
that's why his script not only set the variable but also updates to the Sql table itself
in order to display the ranking correctly


I have tried with this script in my rathena test server[code=auto:0]prontera,158,184,5 script kjfhksdfjs 100,{ set test ,1; while (1) { query_sql "select value from global_reg_value where str = 'test' and char_id = "+ getcharid(0), .@value; if ( .@value == 1 ) break; .@loop++; sleep2 1000; } dispbottom "this one took "+ .@loop +" seconds to update"; end; }[/code][attachment=1251:screenrAthena028.jpg]

Ind, can you try this in your hercules test server ? because I still don't have one
if what you said is correct, the .@loop variable in your test server should be 0

This post has been edited by AnnieRuru on Jan 21, 2014 14:33

malufett - Jan 21, 2014 15:07

[quote]
Ind, can you try this in your hercules test server ? because I still don't have one
if what you said is correct, the .@loop variable in your test server should be 0[/quote]
I've done some script like this before like you have test on your local server..once queried the variable doesn't immediately updated on the server..map server wait for char server to fetch saved data in the database before in used.. same with using 'set' it doesn't immediately reflect on the database..
and common example of this is the occurrence of rollback once the server has terminated unexpected some data are not save cause it is still on the server's memory...

:meow:

AnnieRuru - Jan 21, 2014 16:05

thx malufett for confirming my point

however, malufett, if its you, how do you improve this script ?
hercules has fork out from rathena, you guys can always improve this script as you like

line 129[code=auto:0]ORDER BY CAST(`value` AS SIGNED)[/code]I believe this part no need to cast value as signed,
because in hercules `char_reg_num_db` table, the `value` column is already int(11)
unlike rathena `global_reg_value`, its still a varchar(255) ...

Ind - Jan 21, 2014 21:40

I'm not sure ehm...I'll run another test...
[hr][quote name="malufett" timestamp="1390316839"]

[quote]
Ind, can you try this in your hercules test server ? because I still don't have one
if what you said is correct, the .@loop variable in your test server should be 0[/quote]I've done some script like this before like you have test on your local server..once queried the variable doesn't immediately updated on the server..map server wait for char server to fetch saved data in the database before in used.. same with using 'set' it doesn't immediately reflect on the database..
and common example of this is the occurrence of rollback once the server has terminated unexpected some data are not save cause it is still on the server's memory...

:meow:

[/quote]At the risk of misunderstanding again, I think you guys didn't get what I meant, they're separate from the timed saving and are saved as soon as a script ends, thus[code=auto:0] if (Mission_Total == 1) query_sql("INSERT INTO `char_reg_num_db` (`char_id`,`key`,`index`,`value`) VALUES ("+getcharid(0)+",'Mission_Total','0',1)"); else query_sql("UPDATE `char_reg_num_db` SET `value` = "+Mission_Total+" WHERE `char_id` = "+getcharid(0)+" AND `key` = 'Mission_Total'"); close; [/code]close;^ triggers the saving, which I'd say can occur within a 3-5ms window (since it has to send char server) for it to be in the database, thats a 3-5ms window for the ladder query to have a outdated value.[quote]
char server to fetch saved data in the database before in used[/quote]to this regard, the update on [url="http://herc.ws/board/topic/3886-hercules-1st-2014-megapatch/"]http://herc.ws/board/topic/3886-hercules-1st-2014-megapatch/[/url] has improved the saving logic, so its faster and no longer relies on re-selecting the data in the database

AnnieRuru - Mar 19, 2014 21:21

[code=auto:0]prontera,158,184,5 script kjfhksdfjs 100,{ set test ,2; while (1) { query_sql "select value from char_reg_num_db where `key` = 'test' and char_id = "+ getcharid(0), .@value; if ( .@value == 2 ) break; .@loop++; sleep2 1000; } dispbottom "this one took "+ .@loop +" seconds to update"; end; }[/code]still the same
[attachment=1519:screenHercules017.jpg]
in fact I can't wait 200+ seconds, so I open/close storage, which will definitely save to SQL[code=auto:0][Info]: Saved char 150001 - EnnyRuru: status.[/code]so it doesn't save immediately

yes the value is sent to char-server.exe,
but only open/close storage and so on will save the data from char-server.exe into `char_reg_num_db` table

This post has been edited by AnnieRuru on Mar 19, 2014 21:26

Ind - Mar 29, 2014 22:16

I still think the message didn't get thru, I've made some research to ensure my posts are no longer confusing[code=auto:0]set test ,2; while (1) { query_sql "select value from char_reg_num_db where `key` = 'test' and char_id = "+ getcharid(0), .@value; if ( .@value == 2 ) break; .@loop++; sleep2 1000; } dispbottom "this one took "+ .@loop +" seconds to update"; [/code][quote]
in fact I can't wait 200+ seconds, so I open/close storage, which will definitely save to SQL[/quote]The variable updates are sent to char server as soon as the script ends aka "set value,whatever; end; <= end sends to char server"
thus my point:[code=auto:0]if (Mission_Total == 1) query_sql("INSERT INTO `char_reg_num_db` (`char_id`,`key`,`index`,`value`) VALUES ("+getcharid(0)+",'Mission_Total','0',1)"); else query_sql("UPDATE `char_reg_num_db` SET `value` = "+Mission_Total+" WHERE `char_id` = "+getcharid(0)+" AND `key` = 'Mission_Total'"); close; [/code]at the point the variable is updated/inserted, there is a close, which terminates the script, making both sql queries pointless (they'd be of use if you tried to select the data BEFORE terminating, which is not the case).
Confirmed my thesis with:[code=auto:0]prontera,150,152,6 script Raid 952,{ set test,test + 1; query_sql "select `value` from `char_reg_num_db` where `key` = 'test' and char_id = "+ getcharid(0), .@value; dispbottom "value in char: "+test; dispbottom "value in sql: "+.@value; end; }[/code]which demonstrates the value in sql is updated after every click on it.

This post has been edited by Ind on Mar 29, 2014 22:17