realm-kotlin
realm-kotlin copied to clipboard
Realms file grows "infinitely"
I have a realms file that grows "infinitely" (theoretically). I update this file around 5 times a second and I get the latest version using a write transaction (doing the query outside a write transaction and then updating inside of it will throw an exception so this is the only way possible) and I always put each one of these write transactions inside a try-with-resources.
The logic is looking up an ID and getting a long field and add a quantity to it everytime the function is triggered.
The file grows immensity big and within a month the file grew to 23GB! When I open it with Realm Studio and export as a new realm file the resulting size is a mere 705KB - far more accurate when taking into account the small amount of data inside. I was unable to find anything in the documentation that could justify this behaviour but it's really bad to have a file grow this large unnecessarily. Why does this happen?
Hi @astatio
Sorry for the late reply.
This normally happens due to something called "version pinning", which happens when you are holding a reference to an object while other writes are happening. Realm is an MVCC database, so we track all live versions of the Realm. You can read more about this here: https://www.mongodb.com/docs/realm/sdk/swift/crud/threading/#realm-s-threading-model-in-depth
In Kotlin you can try to enable this setting https://www.mongodb.com/docs/realm-sdks/kotlin/1.0.2/library-base/-realm%20-kotlin%20-s-d-k/io.realm.kotlin/-configuration/max-number-of-active-versions.html which will catch it if this happens.
We are also in the process of making some internal changes, so the chance of this happening is much lower. See https://github.com/realm/realm-core/pull/5440
For now, if you hit this, you need to ensure that you are not holding on to objects for longer than you strictly need them. Perhaps copying their data in memory and releasing the object.
I hope that clarifies things.
@cmelchior I have the same issue here. What do you mean in practice to "Perhaps copying their data in memory and releasing the object." Is there a method we should call to release the object? Also when using frozen objects through flows, this should not be an issue because the object is not managed, right?
Also I tried logging getNumberOfActiveVersions, and it looks like it increments at each transaction, even if there is no observer at all.
Just using the exemple code :
class MainActivity : AppCompatActivity() {
private val binding by viewBinding(ActivityMainBinding::inflate)
private val config = RealmConfiguration.Builder(schema = setOf(Item::class)).maxNumberOfActiveVersions().build()
private val realm: Realm = Realm.open(config)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.btnWriteTransaction.setOnClickListener {
Log.v("MainActivity", "Number of active versions: ${realm.getNumberOfActiveVersions()}")
realm.writeBlocking {
copyToRealm(Item().apply {
summary = "Do the laundry"
isComplete = false
})
}
}
}
}
class Item() : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId.create()
var isComplete: Boolean = false
var summary: String = ""
var owner_id: String = ""
constructor(ownerId: String = "") : this() {
owner_id = ownerId
}
}
See the logs :
2022-10-21 10:28:16.875 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 1
2022-10-21 10:28:17.502 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 2
2022-10-21 10:28:17.669 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 3
2022-10-21 10:28:20.188 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 4
2022-10-21 10:28:20.336 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 5
2022-10-21 10:28:20.503 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 6
2022-10-21 10:28:20.636 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 7
2022-10-21 10:28:20.786 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 8
2022-10-21 10:28:20.920 25322-25322 MainActivity com...ple.realmkotlinactivesessions V Number of active versions: 9
2022-10-21 10:40:59.078 28723-28723 AndroidRuntime com...ple.realmkotlinactivesessions E FATAL EXCEPTION: main
Process: com.example.realmkotlinactivesessions, PID: 28723
java.lang.IllegalStateException: Cannot begin the write transaction: RealmCoreException([5]: Number of active versions (9) in the Realm exceeded the limit of 8)
Closing/Opening the realm instance between each transaction keep the number of version to 1, but the doc clearly indicates to keep a global singleton instance.
This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.
This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.
I would like to state that this was finally fixed with 1.6.0 Amazing!
Despite the bot reopening, i will close it as its fixed now.