I think this is legally fine, but not technically feasible.
You're proposing that a library is linked into a binary both statically and dynamically, with the statically linked version serving as a fallback in case no dynamically loadable library has been provided. This seems to meet the LGPL-3.0's definition of a “suitable mechanism”. The phrasing of that definition says you must be able to operate properly with a dynamically loaded library provided by the user, not that it must be possible to remove the old version.
But this is easier said than done. You might have to effectively implement your own static and dynamic linker for this to work. With static linking, calls are resolved at compile time, and optimizations such as inlining are possible. This would be incompatible with your goal of linking the library dynamically instead. The dynamic linker would also need to know that this library is optional. An alternative might be to load the library explicitly via dlsym() and to make all calls through a function pointer table that you create yourself, but that might be error-prone. There could also be interesting conflicts if the library in question uses global variables or has initializers/finalizers. All that I know about ELF points toward this approach being a bad idea.
I think the most realistic approaches are going to be:
- Just use dynamic linking. This is going to be the easiest solution by far. Relocation is cheap compared to the effort of combining static with dynamic linking, unless you're operating at massive scale.
- Just use static linking, and recompile with modified library versions if necessary. It seems that the software in question will only be used within your organization and by its agents, not e.g. by customers or external partners. It is questionable whether the LGPL would even impose any conditions in this scenario.