Storing files in the DB: story of an epic failure
blog.yourlabs.org
blog.yourlabs.org
And you'll need to provide a detailed README to your DBAs and your team to explain all your special backup and restore operations.
Or, you can just live with a backup that takes longer and requires more disk space.
Doing some kind of asynchronous garbage collection (Dumping all uploaded files, dumping the filenames from DB, and deleting all that are not required anymore) might be a lot easier to get right and reliable than trying to do everything in the request path.
DB as a file service is a horrible idea except for when it's the best choice.
I can't imagine a situation where you would need strict consistency with a BLOB and a database row unless you were also modifying bits inside the BLOB (which wouldn't be true if you are hosting images).
If you just need to ensure that whenever user X says DELETE, you can put S3 infront of an API and just query the database before you return the URL. If you really need the file gone, I would rather just encrypt the image and store the key in the database row.
In a world where S3 doesn't exist, I would still build something similar because coupling my object store with my actual data store just seems like asking for trouble. Having to wait hours to backup several kilobytes of changed data in a multi-terabyte database is just inviting people to cut corners.
If you want a system where the documents are strictly linked to the account, easy to query based on account, consistent (in the DB sense), replicated and backed up with all the other very important customer info, and local so you aren't exposed to external risk factors it's the path of least resistance, and can be easily and securely implemented with very little effort.
Different solutions for different needs.
But how about waiting a whole day to dump a 5TB database? It would have been a major pain in the ass if the real-world customer I'm talking about had chosen to store all their files in the database. Thankfully the files are stored elsewhere, so the database only weighs about 80GB. That's small enough to dump, pipe to gzip, pipe to ssh, and store in a remote location every single day.
You can't get away without files either. Suggesting that you only need a database for everything implies that you store every type of data in it which is not possible long term. Some type of data just doesn't fit there, especially files.
[1] https://docs.microsoft.com/en-us/sql/relational-databases/bl...
https://docs.microsoft.com/en-us/sql/relational-databases/bl...
If all we are storing are profile pictures for a small app for a small user base, I think it is better to store things in the database rather than adding complexity of S3. I mean if you are making an image board like https://github.com/DangerOnTheRanger/maniwani you should not listen to me and use something like S3 because the images are the bread and butter of your application but often user generated images only used for profile pictures might be okay to store in a database. Why make things more complicated than they have to be?
Some seem to think "complexity" only happens when something is really hard. That's not how to think of it at all. Systems usually become overly complex by adding many little simple things. Each of those may be trivial, but together they can make your system impossible to understand and manage.
- learning about and understanding S3 in the first place.
- Billing and AWS account management (possibly requiring agreement/permission from others)
- maintaining credentials securely for your app to access S3.
- bug fixing (for e.g. it's easy to get the permissions wrong when you upload so that it's not visible)
Since you're already storing the URL in your dB, why not just store the binary data you have?
I don't think you're wrong about using something like S3 being a better solution, but it's not quite as simple as "issuing one command"
- he brought up S3, I am assuming he’s already on AWS
- you don’t have to. The role attached to your EC2 instance will have permission. If he is already on AWS, hopefully he knows that.
- From the requirements it seems like the images should be publicly accessible. If not, when you create a bucket, it’s by default private. Yes if he wants to limit access he would have to either stream from S3 to the client - I had to do that it was a quick Google search - or generate presigned URL.
Why not store binary data in the DB? It makes backups larger.
That being said, SQL Server has the filestream type that does in fact store the binary data as a separate file on disk, but gets treated as if it is part of the database for backup and restore purposes.
At the end of the day, if it works and you are aware of the business needs, that's all that matters.
> Most network file systems are either a layer over an existing filesystem (NFS, CIFS), or are develped from scratch to have separate, replicated, purpose-designed databases for metadata and object store (GFS, Glusterfs). At the same time, most database engines provide (or can be coerced into providing) replication and all the ACID properties needed for a high-performance filesystem.
> Idea: Use a database engine (Postgres, MariaDB) on raw partitions with a fast separate nVME log file; build POSIX file system semantics on top. It's pretty obvious that this could work; I'm just starting to implement it so performance and durability can be measured.
Epic fail fans and optimists alike will be excited by an actual implementation attempt, I guess :)
I've been using a combination of S3/Postgres to get filelike semantics myself, but not with a POSIX interface.
The biggest problem for general use is that S3 is really for immutable file storage, and not so much things that'll change a lot. That can be worked around, obviously.
[1] https://twitter.com/dialtone_/status/1115130667677786112
In other news, smart cars and supercars have comparable leg room, and are therefore interchangeable, depending on your use case.
And we haven't even started to talk about eventual consistency.
I am the author of goofys (which exposes s3 like a filesystem) so obviously I believe this can work, but you do need to understand the tradeoffs (or you use goofys and hope that the tradeoffs I've made are correct :-P)
0 dev ops to manage too, can actually sleep at night.
100GB / day (100M records) for $10 all costs: https://youtu.be/x_WqBuEA7s8
TrailDB much better than ours at this though.
Also not a good plan for the database to no longer fit within RAM, especially if the storage engine is evicting cached pages for blob content, only to populate a CDN.
What I've done in the past is just put a CDN in front of the file url, so the file content is stored in the db, but served from the CDN.
Even that article sort of acknowledges this, when it talks about being ultra conservative in your estimations of when this solution will start to fall apart.
Facebook can clearly not "just store all the photos and images in the db! It's less complex!" Same with Google.
To 4 or 5 or more nines of certainty, whatever you're working on doesn't now and never will have Facebook scale problems. And if it _does_, hopefully your business plan has you wallowing in cash-on-hand to pay teams of other smart engineers to help you solve that problem. (I'll respect you more if that pile of cash comes from customers buying your shit, but I'll acknowledge that wallowing in VC money you've raised on hockeystick growth or engagement numbers is also a valid path.)
If your business plan doesn't explain how you'll pay for a db.r4.16xlarge (or your cloud provider or on-prem db vendor's equivalent) with the number of users (or transactions/whatever-your-apporpriate-metric) that a topped-out vertically scaled db can support doing things the "easy and least complicated way", perhaps _that's_ a more important problem to be working on that ACID compliant deletion of user photos...
https://docs.microsoft.com/en-us/sql/relational-databases/bl...
FILESTREAM integrates the SQL Server Database Engine with an NTFS or ReFS file systems by storing varbinary(max) binary large object (BLOB) data as files on the file system. Transact-SQL statements can insert, update, query, search, and back up FILESTREAM data. Win32 file system interfaces provide streaming access to the data.
…