Bug 24986

Summary: Maximum row size reached soon for borrowers and deletedborrowers
Product: Koha Reporter: Julian Maurice <julian.maurice>
Component: Architecture, internals, and plumbingAssignee: Jonathan Druart <jonathan.druart>
Status: CLOSED FIXED QA Contact: Tomás Cohen Arazi <tomascohen>
Severity: critical    
Priority: P5 - low CC: aleisha, jonathan.druart, kyle, lucas, m.de.rooy, magnus, martin.renvoize, tomascohen, victor
Version: Main   
Hardware: All   
OS: All   
See Also: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=28267
Change sponsored?: --- Patch complexity: ---
Documentation contact: Documentation submission:
Text to go in the release notes:
Version(s) released in:
20.11.00, 20.05.02, 19.11.08, 19.05.13
Attachments: Bug 24986: Modify some borrowers DB fields to (TINY|MEDIUM)TEXT
Bug 24986: Modify some borrowers DB fields to (TINY|MEDIUM)TEXT
Bug 24986: Modify some borrowers DB fields to (TINY|MEDIUM)TEXT

Description Julian Maurice 2020-03-26 09:48:59 UTC
Running updatedatabase.pl I got the following error messages:

DBD::mysql::db do failed: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs [for Statement "ALTER TABLE borrowers ADD COLUMN autorenew_checkouts TINYINT(1) NOT NULL DEFAULT 1 AFTER anonymized"] at installer/data/mysql/updatedatabase.pl li
ne 21259

DBD::mysql::db do failed: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs [for Statement "ALTER TABLE deletedborrowers ADD COLUMN autorenew_checkouts TINYINT(1) NOT NULL DEFAULT 1 AFTER anonymized"] at installer/data/mysql/updatedatabas
e.pl line 21262.

After re-injecting an old clean dump and replaying the updatedatabase.pl errors are gone, so it was probably   because of other columns coming from patches not yet in master.
Maybe we should start moving some columns to other tables. An obvious candidate is all the address fields that can be moved in a patron_addresses table.
Comment 1 Magnus Enger 2020-06-03 19:18:28 UTC
I got a similar error when upgrading a straight package install from 18.11.06 to 19.11.06: 

DBD::mysql::db do failed: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs [for Statement "
        ALTER TABLE borrowers
            ADD COLUMN flgAnonymized tinyint DEFAULT 0
            AFTER overdrive_auth_token
    "] at /usr/share/koha/intranet/cgi-bin/installer/data/mysql/updatedatabase.pl line 18071.
DBD::mysql::db do failed: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs [for Statement "
        ALTER TABLE deletedborrowers
            ADD COLUMN flgAnonymized tinyint DEFAULT 0
            AFTER overdrive_auth_token
    "] at /usr/share/koha/intranet/cgi-bin/installer/data/mysql/updatedatabase.pl line 18077.
Upgrade to 18.12.00.049 done (Bug 21336 - Add field flgAnonymized)
Comment 2 Magnus Enger 2020-06-03 19:21:42 UTC
When I run those same updates manually they work:

MariaDB [koha_hkr]> ALTER TABLE borrowers
    ->             ADD COLUMN flgAnonymized tinyint DEFAULT 0
    ->             AFTER overdrive_auth_token;
Query OK, 0 rows affected (0.006 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [koha_hkr]> ALTER TABLE deletedborrowers
    ->             ADD COLUMN flgAnonymized tinyint DEFAULT 0
    ->             AFTER overdrive_auth_token;
Query OK, 0 rows affected (0.006 sec)
Records: 0  Duplicates: 0  Warnings: 0
Comment 3 Jonathan Druart 2020-06-04 09:57:43 UTC
What's the return of
 show variables where Variable_name = 'innodb_file_per_table';
 show variables where Variable_name = 'innodb_default_row_format';
Comment 4 Jonathan Druart 2020-06-04 10:14:42 UTC
Created attachment 105548 [details] [review]
Bug 24986: Modify some borrowers DB fields to (TINY|MEDIUM)TEXT
Comment 5 Jonathan Druart 2020-06-04 10:15:05 UTC
Can you confirm this patch resolves the problem?
Comment 7 Magnus Enger 2020-06-04 11:08:52 UTC
(In reply to Jonathan Druart from comment #3)
> What's the return of
>  show variables where Variable_name = 'innodb_file_per_table';
>  show variables where Variable_name = 'innodb_default_row_format';

MariaDB [koha]> show variables where Variable_name = 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.001 sec)

MariaDB [koha]>  show variables where Variable_name = 'innodb_default_row_format';
+---------------------------+---------+
| Variable_name             | Value   |
+---------------------------+---------+
| innodb_default_row_format | dynamic |
+---------------------------+---------+
1 row in set (0.001 sec)
Comment 8 Kyle M Hall 2020-06-04 12:10:47 UTC
> After re-injecting an old clean dump and replaying the updatedatabase.pl
> errors are gone, so it was probably   because of other columns coming from
> patches not yet in master.
> Maybe we should start moving some columns to other tables. An obvious
> candidate is all the address fields that can be moved in a patron_addresses
> table.

Another option would be to move some columns into a JSON column. MariaDB 10.2.7 and MySQL 5.7 both have JSON data types and functions to use JSON values in a query.
Comment 9 Katrin Fischer 2020-06-06 22:40:11 UTC
borrowers is heavily queried for reports I believe - I am not sure if adding JSON would make this harder. I believe it would at least be a different syntax to learn?
What about changing datatypes as the message suggests? We have quite of a mix on the table at the moment that could need a clean-up.
Comment 10 Martin Renvoize 2020-06-08 10:01:49 UTC
Created attachment 105628 [details] [review]
Bug 24986: Modify some borrowers DB fields to (TINY|MEDIUM)TEXT

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Comment 11 Martin Renvoize 2020-06-08 10:05:34 UTC
I think the patch proposed here is a good (and back portable) fix for the issue in hand so I'm signing off.

However, I do think we should certainly split out addresses into their own table and follow proper 3rd normal form for then.. but I think that should be on it's own bug.. (actually.. i thought there was already a bug for that, but I can't seem to find it).

As for using JSON.. I'm not sure what that would win us really.. I like JSON fields and used them in a postgres based system a while ago.. but the querying did end up considerably more complex in the end and I ended up converting some fields back to additional tables and using JOIN queries instead for performance and readability reasons (dbic isn't great with JSON queries yet either).. I'd say for now at least.. we don't have any cases where the advantage of JSON fields outweighs the cost.. yet..
Comment 12 Jonathan Druart 2020-06-08 10:29:08 UTC
I think we need to recreate the problem and confirm that the patch fixes it. Not only guess it will do the trick (as I did).
Comment 13 Magnus Enger 2020-06-11 12:42:48 UTC
I forgot to save a dump of the live database that had the problem, and now it has been deleted. 

I tried to make a fresh install of 18.11.x, then upgrade to master, but this did not trigger the error I saw on the live database. Sorry about that.
Comment 14 Magnus Enger 2020-06-11 12:47:14 UTC
BTW, the server where I saw the problem is running 10.3.23-MariaDB-1:10.3.23+maria~stretch, if that makes any difference.
Comment 15 Magnus Enger 2020-06-11 13:08:08 UTC
Tried again with an upgrade from 18.11.06 to 19.11.06 (so more specific than the first attempt, where I used the latest releases of 18.11.x and 19.11x), but still no luck.
Comment 16 Tomás Cohen Arazi 2020-06-11 18:03:17 UTC
Created attachment 105769 [details] [review]
Bug 24986: Modify some borrowers DB fields to (TINY|MEDIUM)TEXT

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Comment 17 Marcel de Rooy 2020-06-12 06:47:07 UTC
(In reply to Jonathan Druart from comment #12)
> I think we need to recreate the problem and confirm that the patch fixes it.
> Not only guess it will do the trick (as I did).

Your patch looks good to me too.

https://mariadb.com/kb/en/troubleshooting-row-size-too-large-errors-with-innodb/
Shows some examples with adding varchar fields to recreate ?

Does this actually mean that we should always better choose for the TEXT variants instead of VARCHAR ?
Comment 18 Marcel de Rooy 2020-06-12 07:51:23 UTC
Here is a first observation:
Not a big production database, but on a small master.
I can add 139 varchar(60) fields to borrowers and still create table x like borrowers. But if I add 140 fields, the create fails on row size.
Note that 60 is chosen so that the varchar stays on the main data page, not on the overflow.

With your patch, I hoped to add more than 140 fields. But it fails exactly at this same point! So the patch seems to make no difference??
Comment 19 Marcel de Rooy 2020-06-12 08:13:04 UTC
Well, not completely. Hang on.
Comment 20 Marcel de Rooy 2020-06-12 08:43:06 UTC
Another thing:
If I add the 140 fields before the db revision, the solution in this patch should help me to recover, but unfortunately the db rev will not execute the change on the fields but list the Row size too large on them. So I would be stuck. So the troubleshooting page here gives me a solution that I cant apply.
Comment 21 Marcel de Rooy 2020-06-12 08:47:31 UTC
With SET SESSION innodb_strict_mode=OFF;
I can do:
alter table borrowers modify column streettype varchar(256);
Comment 22 Marcel de Rooy 2020-06-12 09:28:27 UTC
Well, my conclusion for now is: I am all for pushing this change to prevent future problems.
But my test tells me that when you already ran into this problem, you cant alter table anymore and resolve it like the dbrev does.

I needed to set strict mode off to alter the 140 fields to TEXT. And even then it was not sufficient. Only when I dropped field 140, it was gone. Perhaps another limitation? InnoDB should allow 1000 columns, but I already passed some other limitation: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535.

Not sure, but it might help to combine the separate ALTERs into one statement instead of looping.
And it might help to temporarily disable strict mode for the alter, but as I saw in my test, the change might not be enough to recover?
Comment 23 Jonathan Druart 2020-06-25 09:12:33 UTC
Pushed to master for 20.11, thanks to everybody involved!
Comment 24 Lucas Gass 2020-07-13 15:25:25 UTC
backported to 20.05.x for 20.05.02
Comment 25 Aleisha Amohia 2020-07-16 04:18:47 UTC
backported to 19.11.x for 19.11.08
Comment 26 Victor Grousset/tuxayo 2020-07-22 19:25:37 UTC
Backported to 19.05.x branch for 19.05.13
Comment 27 Jonathan Druart 2020-07-30 07:33:12 UTC
Reported on the ML for "branches"

https://lists.katipo.co.nz/pipermail/koha/2020-July/054967.html

The solution was to replace the row_format's value with "Dynamic" (this is the default value).
Comment 28 Marcel de Rooy 2020-09-29 12:45:21 UTC
(In reply to Jonathan Druart from comment #27)
> Reported on the ML for "branches"
> 
> https://lists.katipo.co.nz/pipermail/koha/2020-July/054967.html
> 
> The solution was to replace the row_format's value with "Dynamic" (this is
> the default value).

I am not sure about that. My tables are all on Dynamic.
If they would not, this is a first step.
But somehow with Dynamic, we could also reproduce (see earlier comments)