New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Session table improvements #19708
Session table improvements #19708
Conversation
@@ -76,7 +76,7 @@ public function write($id, $data) | |||
$query = $db->getQuery(true) | |||
->update($db->quoteName('#__session')) | |||
->set($db->quoteName('data') . ' = ' . $db->quote($data)) | |||
->set($db->quoteName('time') . ' = ' . $db->quote((int) time())) | |||
->set($db->quoteName('time') . ' = ' . (int) time()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
time()
returns an integer. Do we need (int)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I should do this as in php5 there is an extension apd
, pecl install apd
and there is a function override_function()
, which can change time()
function to something else.
For now, I leave it as it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By that argument you can't rely on any of the core PHP functions to do as they document. Should someone be running one of those types of override tools or custom compiling PHP and changing C level internals, it's a problem for them and it's not something we can account for at our level without not using the language features.
we should take care of the update path, of course, but a good move |
Is this something that may happen again switching to VARBINARY? |
I do not know yet. |
There are people joining the session table on that column for reasons I do not comprehend (I didn't in 2015 and I don't in 2018, I have not found one legitimate use case where my database schema needs a FK to a table storing the session identifier). |
A common use case to join the session table is for example when dealing with a chat extension allowing communication between guest users. |
I did simple tests with success: SELECT s.session_id, old.session_id FROM `j38_session` s INNER JOIN `j38_session_old` old ON s.`session_id` = old.`session_id`;
SELECT * FROM `j38_session` WHERE session_id = '4m82kgvd3nr49s3melhnmejqlg'; |
I did tests too, using MySQL 5.1, 5.5 and 5.7 |
@joeforjoomla Please mark your test at Issue Tracker. Thanks. |
It is too early to mark the test as a success. This PR probably has to wait until #19687 will be merged. |
`client_id` tinyint(3) unsigned DEFAULT NULL, | ||
`guest` tinyint(4) unsigned DEFAULT 1, | ||
`time` varchar(14) DEFAULT '', | ||
`guest` tinyint(3) unsigned DEFAULT 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should not be changed from 4
to 3
since it is not done during updates?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
5eda21f
to
6b58c8a
Compare
Yes, we can probably use the |
* Add missing alter table for guest * Remove cast to int for the result of time()
6b58c8a
to
104f824
Compare
I updated the code. Now this PR is ready for testing. |
@joeforjoomla Could you re-test this PR. |
@BrainforgeUK Because you know the subject well, could you test it? |
@csthomas I re-tested this PR again up to MySQL 8.0 without any issue when joining between #__session.session_id AS varinary(192) and #__customtable.session_id AS varchar(191) However i can't ensure that everything will work correctly on other RDBMS such as MariaDB, Postgresql, etc |
@joeforjoomla thanks, It is enough, great, now we need one more test and one of the maintainers will decide. |
@joeforjoomla please mark your Test as successfully:
|
I have tested this item ✅ successfully on 104f824 This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/19708. |
ALTER TABLE "#__session" ALTER COLUMN "session_id" TYPE bytea USING "session_id"::bytea; | ||
ALTER TABLE "#__session" ALTER COLUMN "session_id" SET NOT NULL; | ||
ALTER TABLE "#__session" ALTER COLUMN "time" DROP DEFAULT, | ||
ALTER COLUMN "time" TYPE integer USING "time"::integer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above will work when executing the file on upgrade,
but will it work with the Database "Fix" button ?
The SQL parsing code for every ALTER TABLE statement seems to handle only 1 altering sub-clause case per ALTER TABLE statement
(i have not tested i just reviewed the following file and i think remember similar case for Mysql in the past)
libraries\src\Schema\ChangeItem\PostgresqlChangeItem.php
(same limitation i think applies for MysqlChangeItem too class)
So I think it should become
ALTER TABLE "#__session" ALTER COLUMN "time" DROP DEFAULT;
ALTER TABLE "#__session" ALTER COLUMN "time" TYPE integer USING "time"::integer;
If it can handle multiple sub-clauses then please ignore this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above will work when executing the file on upgrade,
but will it work with the Database "Fix" button ?
Yes
In short, joomla will see only the last sub-clause (to compare difference with db), but db did all clauses. Explanation for PostgreSQL,
** The first line ** removes the default value of the We use two operations in one "ALTER TABLE" so that joomla can not see the change in the first line. This is useful when we can not directly change the default value (or change the INDEX of column), but first we need to remove the default value and then add another value. I have tested it again a few minutes ago (by update) and in pgAdmin3 now I have:
|
I have tested this item ✅ successfully on 104f824 This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/19708. |
Ready to Commit after two successful tests. |
Thank you all for your interest. |
Merged to 3.9-dev via 6d1e90f |
Summary of Changes
This PR provides an improvement in the performance of high-traffic sites.
session_id
fromvarchar
tovarbinary
.time
fromvarchar
tointeger
.Why I changed
time
column to integer?Before this PR the value of
time
column is stored as text.Comparing text to text such as "a" <'b' can not use the index key.
When joomla deletes all expired sessions then need to scan whole table because the index (of
time
column) is useless.Drawback of varchar:
varchar
type use language processing on comparison, it is slowervarchar
takes up to 4 bytes per character when it is loaded into RAMWhy I changed
session_id
column to varbinary?A good explanation is at https://github.com/symfony/http-foundation/blob/master/Session/Storage/Handler/PdoSessionHandler.php#L214
Testing Instructions
com_patchtester
.For PostgreSQL database you should apply additional PR Repair the update of database schema changes on postgreSQL #19707- it is merged.Expected result
All works as before.