55 comments

[ 3.9 ms ] story [ 127 ms ] thread
This was very helpful. I am in my first project with MongoDb after a lot of experience with RDBMs and I do miss transactions. There are other things I miss more: foreign keys (dobt use dbrefs!), joins, and SQL, though.

Unfortunately this application is new, so we haven't yet seen the benefit of schemaless data changes.

At first it seems quite freeing - no schemas holding you back. Later on, after things stabilize, it stops being helpful and starts being a burden to performance and stability.
PostgreSQL + JSON gets you working transactions and schemaless.
Plus it scales well and doesn't randomly lose data. Oh, and the project leaders are professionals who are honest and transparent about the capabilities of their product.
It scales, to a point. In my opinion however, any type of sharding/clustering is still a total mess in PostgreSQL. Most projects will however probably never need to.
How DARE you, sir, imply that we are not the next "Amazon"!

Kidding aside, I suspect with a little discipline, one could design a PG DB that could be ported to Oracle (Exadata???) should the need, and budget ($$$$$), for that sort of scaling arise. Cheap and safe now, Expensive and safe later (if needed)

Also, I seem to recall that PG scales up on multiprocessor hardware fairly well (vs say MySQL), so one can explore exhausting that limit first before more drastic measures are taken.
Shameless plug here, but my side-project (http://bedquiltdb.github.io) aims to provide a nice mongo-a-like programmatic API on top of PostgreSQL and JSONB.

In theory there's no reason why we shouldn't be able to support a nice transactions API in the client drivers too, I just haven't gotten around to it yet.

I was just starting a new project and had to make a choice. I looked at the MongoDB 3.0.x release notes to see if the project has managed to improve in the last couple of years, and there are still way too many "data files are not correctly recovered following unexpected system restarts" and "race condition between inserts and checkpoints that could result in lost records" issues being fixed in each release for my liking. Different projects have different tolerances, of course.

If I was leaning towards NoSQL I would probably choose something rock solid like DynamoDB on AWS. That thing (mostly) scales by simply throwing money at it, on my last project that had tens of millions of users it worked very well, but it's definitely not cheap.

For my personal project I ended up going with PostgreSQL 9.4. The initial user experience is still as bad as I remember from years ago (after installing PostgreSQL on Ubuntu, neither the logged in user nor root have a default DB, can't even run psql, cannot create new DB's out of the box, and the tutorial(!) waxes on about "Architectural Fundamentals" instead of "Do x,y,z to install and insert a few rows of data").

With Postgres I'm able to have JSON type columns, where my unstructured documents are stored, as well as regular foreign keys, transactions and joins at the table level. So far I'm very pleased with how it's working out, I think it's a good middle ground between the flexibility of NoSQL and the reliability + querying power of SQL.

> after installing PostgreSQL on Ubuntu

Note that this is a mainly packaging and entirely the maintainer's fault: They typically run the database under a "postgres" user, so you'll have to do "sudo -u postgres createdb" or whatever. PostgreSQL itself doesn't care; if you install it from source and start the postmaster process as yourself, then you'll have full access right away.

That said, Debian/Ubuntu packages typically don't set up a default environment for you as a convenience. It's debatable what it should do. Create a user and database for root? Postgres maps, by default, POSIX users to database users. If you run "apt-get install postgresql-server-9.4", who should it create database users for?

Also, I'm not sure you're fair to the documentation you're referencing, which seems entirely reasoanble to me. Section 1.2 of the 94 manual's tutorial, "Architural Fundamentals", is pretty important, and it's short. But if you skip it, you'll get to the next section, "Creating a database", which tells you what need, and the next one goes into the SQL stuff. Both sections work if you've installed it from source (or Homebrew, which also runs Postgres as yourself). But it would be silly to expect this documentation to tell you how to specifically do it on Ubuntu.

I respectfully disagree. After reading the "Getting Started" guide, you might reasonably believe a developer would be setup and happily coding away, but in my experience it fails at the very first steps.

Which is fine, if you want to keep a high bar, but don't be surprised when people still think the product is "harder to use" than MongoDB or whatever in 2015. Blaming maintainers does nothing for the users, take ownership of the experience! If you want to be seen as approachable and easy to use, you have to actually target people new to PostgreSQL and not write the basic guide assuming you're compiling from source on Solaris or have a dedicated site DB administrator. The magic phrase "sudo -u postgres createdb" does not appear anywhere on postgresql.org that I can see, and as a experienced user you know that's not the end of it (can I use psql as my regular user after running it? No, of course not. There's many more entirely undocumented arcane incantations left!). I claim, it is in fact impossible to get up an running with no previous knowledge if all you have access to is the postgres site. Thankfully there's Stackoverflow, so at least some users are still getting through the gauntlet.

Sorry for the rant. I get a bit frustrated when I see a great project that I love dropping users through a bad onboarding experience (I know, contributions welcome...)

Just for reference, check out: https://docs.mongodb.org/manual/tutorial/install-mongodb-on-... https://docs.mongodb.org/getting-started/node/ In fact, you get different sets of documentations for the whole matrix of OS * ENV (Shell, Node, Python, C++, Java, C#). When the docs have their target audience down to a T ("Why yes, I AM a C++ developer on OS X! This looks like the perfect fit!"), it's easy to see why they're so popular.

If this new application is something that will be in production and important to a business, I would seriously question the decision to use MongoDB over PostgreSQL.

I'm not saying it's a bad decision or that MongoDB is bad in general. I'm saying it's a decision that should not be taken lightly. If you've done the analysis and feel strongly that MongoDB's the perfect fit, then cool.

However, I think people routinely discount the operational overhead that comes with using something like MongoDB. For example, they don't think about how it's much harder to find good devops people with experience maintaining a MongoDB sharded cluster, or they don't think about what happens when the CFO wants to hook the DB up to Excel and run some queries. And I'm not even talking about the additional development complexity due to implementing integrity checks and manual transaction rollback/compensation in your application code.

Those problems can be all be solved though. It just takes more effort/money. So, you need to be sure MongoDB offers advantages to offset that.

In my opinion, schemaless data changes are not even close to offsetting the overhead, and concerns about scaling beyond MySQL or PostgreSQL are probably premature optimization. Not that those are your reasons – just reasons I often hear.

And of course, I'm making a lot of assumptions, for example that the team has experience writing & operating systems on top of an RDBMS. If the rest of the team are MongoDB wizards and you're the only one new to it, then that's a different situation.

Plus, you can make "hybrid" tables in PostgreSQL that have some fields in separate indexable primary and foreign key columns (or other uses, as needed), but remaining fields shoveled into a JSON CLOB "column".

The E/R information between tables remains exposed and enforced, but the content details can be made fungible where desired. There is an extension to include JSON fields in queries, as well, though it won't be as fast as using a real column with an index on it.

The idea is that you won't need database-wide transactions if your data is structured into "natural aggregates" such as orders, articles, profiles, etc. In a relational database, something as simple as an "order" has components in lots of different tables -- customer, product, order, line_item, shipping_method, etc -- so you have to lock all of those tables when doing an INSERT or UPDATE.

In the ideal MongoDB implementation, an "order" would be a document of its own, and all the other parts would be attributes or nested structures. So you only really need a transaction for the document itself. Other documents could be inserted/updated at the same time without creating a conflict. That's the theory, at least. Martin Fowler has a good Youtube on "Introduction to NoSQL" that I sometimes show to my students: https://youtu.be/qI_g07C_Q5I

The other thing about NoSQL is that it's often used for write-once, then read-only applications. Twitter, Facebook, or Instagram would be good examples. When 1% of your queries are INSERTs and 99% are SELECTS (with UPDATE and DELETE almost never occurring), you really don't run as much risk of anomalies. I would not recommend NoSQL for something like a banking application where you're doing lots of updates and need to guarantee consistency.

>I would not recommend NoSQL for something like a banking Many of the leading banks in the world have replaced Oracle with NoSQL (generally MarkLogic) for key systems. Abadi explained quite clearly why NoSQL is not incompatible with transactions and updates.
https://en.wikipedia.org/wiki/FoundationDB

designers haven't solved all problem around transaction and performance, but that doesn't mean they have stopped trying

"As various NoSQL databases matured, a curious thing happened to their APIs: they started looking more like SQL. This is because SQL is a pretty direct implementation of relational set theory, and math is hard to fool."[1]

[1]http://blog.memsql.com/cache-is-the-new-ram/

As a heavy user of FoundationDB I'd point out they have a five second transaction limit. One of the big compromises made to make their system work. This limit of course makes things... interesting in the real world.
ZODB ( http://www.zodb.org/en/latest/ ) is a NoSQL database that has been around for almost twenty years now. It's a Python-specific NoSQL database that allows persisting of arbitrary objects in a tree structure. It not only has multi-object transactions, transaction savepoints for memory efficiency's sake (both optimistic and normal), a pluggable 3-way conflict resolver, two-phase commit and support for long-running branches which contain multiple transactions.
Sure, but ZODB doesn't "horizontally scale". That's what makes multi-object transactions hard in mainstream NoSQL databases. And that's what's so cool about the linked papers; they describe two different mechanisms to achieve both multi-object transactions and horizontal scaling.

Of course, the next question is whether you actually need scaling. Outgrowing a database is a "problem of success"; if you have that problem you can throw money at the problem. It's much more important to concentrate your efforts on achieving success; choose your database focusing on your business problem, not on hopeful future potential problems.

ZODB is no database. ZODB is a persistance layer. Where is the SQL in ZODB? The level of sophistication in the query interface is laughable.
It is a database, not a relational database.
The multi feature of redis kind of allows you to create some level of transactionality over multiple items, no?
Not over multiple nodes. Only on 1 node/core.
Have any of you heard of DocumentDB from Microsoft Azure? It is very similar to documentDB but It was specifically designed to have atomic transactions.
Sorry to say but we have something that is truly transactional and distributed (https://www.quasardb.net). It slows down a bit writes (because of the commit) but it scales well.

And before us FoundationDB delivered the same feature (although implemented a bit differently).

The truth is that there is a market for databases with "unreliable" writes and there are easier to design. That's why you see a lot of them.

You do not disagree with the author. Quoting from his post:

Given that distributed transactions necessitate distributed coordination, it would seem that there is a fundamental tradeoff between scalable performance and support for distributed transactions. Indeed, many practitioners assume that this is the case. When they set out to build a scalable system, they immediately assume that they will not be able to support distributed atomic transactions without severe performance degradation.

This is in fact completely false. It is very much possible for a scalable system to support performant distributed atomic transactions.

In a recent paper [http://cs-www.cs.yale.edu/homes/dna/papers/fit.pdf], we published a new representation of the tradeoffs involved in supporting atomic transactions in scalable systems.

What are you using LevelDB for? I hope not the main KV store.

Do you use 2PC or something like Raft to handle distributed transactions?

From the docs it sounds like everytime a node joins/leaves the cluster goes into a (brief?) unstable mode and failures can happen, that doesn't sound great.

I'm happy to see you've read the documentation thoroughly!

We indeed stopped using LevelDB. It has been used for a while but we couldn't work around some speed issues. LevelDB is good for many scenarii when properly configured, though.

The database is multilayered, LevelDB was the last layer, most parallel operation were managed by a massively parallel in-memory database which used LevelDB as a backend.

We do 2PC to handle distributed transactions. Raft breaks our consistency model.

When a node joins/leaves the cluster you might have some transient failures which are generally absorbed by the protocol.

I hope I answered your questions and feel free to give it a spin next week, we're about to release a major update!

Is there something particularly wrong with LevelDB? It may not have all of the bells and whistles you could possibly want from an on-disk key-value store, but it seems like a perfectly serviceable building block to put a database on top of.
What is the percentage of web applications that really need all that scaling? How many database instances does Hypothes.is need? What about Airbnb? Duolingo? Feedly?
Exactly.

To handle massive loads, you can trade away transactional integrity and get increased performance AND a whole new range of complicated problems that was more or less solved for you, that you now have to take care of yourself.

For some applications, the tradeoff is not a problem - and in others it requires a lot of work, up to more or less your own implementation of distributed transactions.

I have this feeling that I can't shake off , that a lot of people think relational (transactional) databases are complicated, and fail to see why they actually are complicated. This probably is not the category of people that truly need to solve their performance problems though.

A lot of services would be fine with some big traditional databases - StackOverflow is one example that scaled vertically instead of horizontally.

But a lot of services would also get by with a distributed DB with weak integrity guarantees. Does it really matter if a few upvotes get lost on a busy post? By the time you notice sporadic integrity issues in your DB, the startup will probably have failed or raised enough money to not care.

On the .NET stack, RavenDB[0] supports transactions on multiple items[1].

RavenDB is a nice middle ground: eventual consistency for queries for speed, but ACID for create, update, and load (one or more items by ID).

It uses transactions throughout, so a failure in the midst of 10 writes will rollback all of them, as one would expect in a traditional relational database.

[0]: http://ravendb.net/

[1]: http://ravendb.net/docs/article-page/3.0/csharp/start/gettin...

It does indeed look nice, however the pricing looks worse than MS SQL in the long run (for the enterprise version).
It's free for open source projects.

For commercial enterprise, Raven is effectively $788/core/year [0]. Quite reasonable, IMO.

Contrast this with MS SQL Server Enterprise, which appears to be $14,000/core one-time cost [1].

(Disclaimer: I'm a part-time employee for RavenDB. But I loved and used Raven on my own projects before becoming an employee.)

[0]: http://ravendb.net/buy [1]: http://www.microsoft.com/en-us/server-cloud/products/sql-ser...

How can one possibly be eventually consistent for reads and ACID for updates? Unless you are saying the datasets available for fast queries cannot be updated consistently...Or are you just saying, you can read from replicas but maintain a single master...
Direct reads (by ID) and writes are ACID.

Complex queries are eventually consistent.

Hope this helps. I'm @judahgabriel if you have more questions.

Nobody else has said it, so I'll do it: This website is horrible. The font color is #888888 on a white background, which is very hard for me to read. And I can't even fix it by disabling a CSS style in the web inspector panel like I usually would because the CSS styles are hard-coded into style attributes on spans for each paragraph! What is this, a website from the 90s? How is it so horrible, given that other random Blogspot blogs I'm checking have sensible markup?
You know how when you write something in Microsoft Word, and then copy it out into an editor, it takes terrible and broken HTML markup with it? That is exactly what has happened. The author has written the post in Word copied it to blogspot, and wham, bam, thank you ma'am, you get that clusterfuck.
Also - when you swipe the page right (to go Back in a mobile browser), it instead navigates you to the previous blog entry. Argh.
Don't despair. If you have access to the console, copy & paste this and knock yourself off:

  [].slice.call(document.querySelectorAll('#post-body-2680112629272717029  *')).forEach(ele => ele.style.color = 'black')
Misleading title: Abadi specifically called out particular NoSQL DB's, he wasn't generalizing to all NoSQL DB's. MarkLogic (http://www.marklogic.com) is an Enterprise Database used by many large organizations as a system of record for information traditionally stored in RDBMS or Mainframe.

Joe Hellerstein gave a wonderful keynote at ACM SoCC last year that is a great read for all who are interested in this subject: http://db.cs.berkeley.edu/jmh/talks/SoCC14-keynote.pdf

MarkLogic has had transactions since version 1.0. The same mechanisms that enable multi-statement transactions are also critical for overall reliability. A recent Gartner study ranked MarkLogic as #3 for reliability (not NoSQL databases, all databases).

Many on HN may have not heard of MarkLogic as we are not open source. We are, however, the largest NoSQL ISV by employee count (and probably other measures also.)

I am VP, Product Strategy for MarkLogic (ExIngres, ExCohera)

And it's a graph database as well with sparql support. Maklogic is really flexible that way.
Could you describe where your system sits on the FIT spectrum that the article discusses? Do you believe that scheme for thinking about the trade-offs between isolation, throughput, and fairness doesn't hold for marklogic?
They absolutely apply to MarkLogic. We absolutely prioritize FI over T. Coordinating transactions, along with journaling, security and many other features costs in terms of throughput. Now, that cost is relative - our ingest rates are still very quick and we linearly scale. That said, copying JSON or XML into a distributed file system is way quicker.

I'm not sure the buckets provide much guidance in real life. One can configure a system, for an insert only batch load, to prioritize T without giving up FI for the data and transactions that aren't part of that load. If an FI system can load faster than an IT system, this distinction ends up not actually mattering. Plenty of folks who need FI are using products that don't provide it because of culture + budget.

Ok, we added 'some' to the title.
Do you have info or can you point to anything where I can learn about MarkLogic without all the marketing speak on the site? It's really hard to get any info about how the software actually looks like and works and compares to other options out there...
Who were ranked as #1 and #2?
HyperDex Warp does lightweight multi-key transactions:

http://hyperdex.org/warp/

Are you using HyperDex in production? I have never heard about anyone using it -- but then good products often stay under the radar when all its users are satisfied and productive.
As previously noted, title is misleading. Also, pick a better document store (though you should note that rethink only guarantees operations on single documents as atomic):

http://rethinkdb.com/

Yes, "better" is subjective, but rethink has a good page detailing the differences (between rethink and mongo):

http://www.rethinkdb.com/docs/rethinkdb-vs-mongodb/

Feature-list type breakdown:

http://www.rethinkdb.com/docs/comparison-tables/

And pay attention to the guarantees that it provides/doesn't provide when you pick. I think this is a big part of what separates novice developers form middle-tier developers. There are always tons of choices, for just about everything in software these days, and your job is to figure out how best to solve which problem you're facing, in a way that future generations won't hate you for.

Nothing in the first paragraph is true about Cassandra except perhaps that it does allow for some limited nesting of data. The rest of the article is great though. It doesn't even need the first paragraph.
The question here is really "When do you need distributed transactions"? One of misuses is when one cannot achieve enough performance on a single node. E.g., one builds a system serving 1000 REST requests per second (RPS), achieving 2 seconds latency per request, having a DB as a bottleneck. To be honest, I've seen real software built giving 23 sec latency per only 50 RPS. Does it mean there is a need to scale it out or simply that a chosen DB is a problem? The cases I've seen through my practice are mostly on the latter.

Simply choose the most suitable solution, not the most hyped one. A mistake would be to sacrifise transactions via using some "general NoSQL database". Today, for real, you can have a single node capable of millions RPS on real-world scenarios with ACID transactions of arbitrary complexity, choosing solution like http://starcounter.io/. Please, please don't just take yet another no-transactions DB, which is no-transactions even on a single machine, having 4 db nodes on 4 cores completely separate as if they've been 4 different machine. Then you observe bad performance and start to scale things up, paying more and more for the cloud. Not the best idea to spend time and money.

And, if you DO really need distributed transactions, then it mostly means they'd be driven by a logic of your subject domain. E.g., you might have one department in Sweden, one in the USA, then you need to manage distributed accounts in the right way, where "right" is up to your banking policy. However, if you need to scale reads, there is just no problem of doing so within "no-distributed-ACID" solution. The same time, if you need to scale writes, doing distributed transactions isn't a good idea either, as you've seen from the topic starter article.

So, right tool for the right job.

Outside of the brackets I keep a topic of fighting with latency via distributed transactions. I mean those things around caching, CDN and async replication. Distributed transaction isn't a remedy there at all, since it doesn't patch speed of light by any means.