Transacciones y manipulación de datos
Realice transacciones atómicas en tablas de Mnesia para garantizar la coherencia de los datos entre nodos distribuidos.
Transacciones y manipulación de datos es una lección gratuita de Erlang OTP: Distributed & Fault-Tolerant Systems Programming en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Erlang OTP: Distributed & Fault-Tolerant Systems Programming, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Erlang OTP: Distributed & Fault-Tolerant Systems Programming incluye 4 lecciones en total.
Partes de esta lección aún no han sido traducidas y se muestran en inglés.
Why Mnesia Needs Transactions
Imagine managing important data like bank transfers. You wouldn't want money to leave one account without arriving in another, right?
This "all or nothing" principle is crucial for data consistency, and it's where transactions come in. Mnesia uses transactions to group multiple database operations into a single, atomic unit.
An atomic transaction either fully completes all its operations, or if any part fails, all changes are rolled back. This ensures your data remains consistent and reliable.
The Core: `mnesia:transaction`
In Mnesia, you perform transactional operations using the mnesia:transaction/1 function. It takes an anonymous function (a fun) as its argument.
All Mnesia read and write operations that need to be atomic must be placed inside this fun. If the fun executes successfully, the changes are committed. If an error occurs or mnesia:abort/1 is called, all changes are rolled back.
Let's see its basic structure:
-module(example_transaction).
-export([main/0]).
main() ->
mnesia:start(),
{atomic, _Result} = mnesia:transaction(fun() ->
% Mnesia operations go here
io:format("Inside the transaction!~n"),
ok
end),
io:format("Transaction completed.~n"),
mnesia:stop().Preparing Data for Transactions
Before we can manipulate data, we need a Mnesia table. Let's define a simple person record and create a table for it. This setup will be used in our transaction examples.
Remember, mnesia:create_table/2 is usually called once when your application starts up for the first time.
-module(mnesia_table_setup).
-export([main/0]).
-record(person, {id, name, age}).
main() ->
% Ensure Mnesia is started on this node
mnesia:create_schema([node()]),
mnesia:start(),
% Create table if it doesn't exist
case mnesia:create_table(person, [{attributes, record_info(fields, person)}]) of
{atomic, ok} -> io:format("Table 'person' created successfully.~n");
{aborted, {already_exists, person}} -> io:format("Table 'person' already exists.~n");
Error -> io:format("Error creating table: ~p~n", [Error])
end,
mnesia:stop().Adding & Updating Records
Inside a transaction, you use mnesia:write/1 to store or update records. If a record with the same primary key (the first field in our person record, id) already exists, it will be updated. Otherwise, a new record is inserted.
Let's add a new person to our table. Remember to start Mnesia first!
-module(write_example).
-export([main/0]).
-record(person, {id, name, age}).
main() ->
% Ensure Mnesia is started and table exists (simplified setup)
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(person, [{attributes, record_info(fields, person)}]),
mnesia:wait_for_tables([person], 5000),
% Write a new person record
Person1 = #person{id = 1, name = "Alice", age = 30},
{atomic, ok} = mnesia:transaction(fun() ->
mnesia:write(Person1)
end),
io:format("Wrote: ~p~n", [Person1]),
mnesia:stop().Fetching Records Transactionally
To retrieve data inside a transaction, use mnesia:read/1. It takes a record or a record key (like {person, 1}) and returns a list of matching records. If no record is found, it returns [] (an empty list).
Let's read the person we just added. We'll combine writing and reading in a single transaction for a fuller example.
-module(read_example).
-export([main/0]).
-record(person, {id, name, age}).
main() ->
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(person, [{attributes, record_info(fields, person)}]),
mnesia:wait_for_tables([person], 5000),
Person1 = #person{id = 1, name = "Alice", age = 30},
Person2 = #person{id = 2, name = "Bob", age = 25},
{atomic, Result} = mnesia:transaction(fun() ->
% Write two records
mnesia:write(Person1),
mnesia:write(Person2),
% Read one of them
mnesia:read({person, 1})
end),
io:format("Transaction result (read data): ~p~n", [Result]),
mnesia:stop().Modifying Data with Transactions
mnesia:write/1 handles both inserting new records and updating existing ones. To remove a record entirely, you use mnesia:delete/1, providing the full record or just its key.
Let's update Alice's age and then delete Bob from our Mnesia table, all within a single, consistent transaction.
-module(update_delete_example).
-export([main/0]).
-record(person, {id, name, age}).
main() ->
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(person, [{attributes, record_info(fields, person)}]),
mnesia:wait_for_tables([person], 5000),
% Ensure initial data for update/delete
mnesia:transaction(fun() ->
mnesia:write(#person{id = 1, name = "Alice", age = 30}),
mnesia:write(#person{id = 2, name = "Bob", age = 25})
end),
io:format("--- Before transaction ---~n"),
io:format("Alice: ~p~n", [mnesia:dirty_read({person, 1})]),
io:format("Bob: ~p~n", [mnesia:dirty_read({person, 2})]),
{atomic, _} = mnesia:transaction(fun() ->
% Update Alice's age
UpdatedAlice = #person{id = 1, name = "Alice", age = 31},
mnesia:write(UpdatedAlice),
% Delete Bob
mnesia:delete({person, 2})
end),
io:format("--- After transaction ---~n"),
io:format("Alice: ~p~n", [mnesia:dirty_read({person, 1})]),
io:format("Bob: ~p~n", [mnesia:dirty_read({person, 2})]), % Should be []
mnesia:stop().Transaction Rollbacks in Action
The power of transactions lies in their atomicity. If any operation within the fun fails or you explicitly call mnesia:abort/1, Mnesia will roll back all changes made during that transaction.
This means your database state will revert to how it was before the transaction started, preventing partial updates and maintaining consistency.
-module(rollback_example).
-export([main/0]).
-record(person, {id, name, age}).
main() ->
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(person, [{attributes, record_info(fields, person)}]),
mnesia:wait_for_tables([person], 5000),
% Ensure Alice exists initially
mnesia:transaction(fun() ->
mnesia:write(#person{id = 1, name = "Alice", age = 30})
end),
io:format("Initial Alice: ~p~n", [mnesia:dirty_read({person, 1})]),
% Attempt a transaction that will abort
Result = mnesia:transaction(fun() ->
mnesia:write(#person{id = 1, name = "Alice", age = 35}), % Update
mnesia:write(#person{id = 3, name = "Charlie", age = 22}), % New record
mnesia:abort("Something went wrong!") % Abort the transaction
end),
io:format("Transaction result: ~p~n", [Result]),
io:format("Alice after aborted transaction: ~p~n", [mnesia:dirty_read({person, 1})]),
io:format("Charlie after aborted transaction: ~p~n", [mnesia:dirty_read({person, 3})]),
mnesia:stop().`mnesia:sync_transaction/1` for Global Commit
While mnesia:transaction/1 ensures local atomicity, its return doesn't guarantee the transaction has committed on all Mnesia replicas in a distributed setup. For that, you use mnesia:sync_transaction/1.
mnesia:sync_transaction/1 blocks the caller until the transaction has been successfully committed on all nodes where the affected tables are resident. This is crucial for strong consistency guarantees in distributed systems.
Use it when you absolutely need to know that data is consistent across your entire cluster before proceeding.
-module(sync_transaction_example).
-export([main/0]).
-record(item, {id, name}).
main() ->
% This example assumes a distributed Mnesia setup.
% For a single node, it behaves like mnesia:transaction/1.
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(item, [{attributes, record_info(fields, item)}]),
mnesia:wait_for_tables([item], 5000),
Item = #item{id = 101, name = "Widget A"},
io:format("Attempting sync_transaction...~n"),
{atomic, ok} = mnesia:sync_transaction(fun() ->
mnesia:write(Item)
end),
io:format("Item written and committed across all replicas: ~p~n", [Item]),
mnesia:stop().Transaction Knowledge Check
You've learned about Mnesia transactions and how to manipulate data atomically. Let's test your understanding!
Transactions: Your Data's Safety Net
In this lesson, you mastered Mnesia transactions, a cornerstone for building robust and reliable applications.
- We learned that transactions provide atomicity, ensuring "all or nothing" data operations.
- You practiced using
mnesia:transaction/1to group Mnesia operations. - We covered
mnesia:write/1for adding/updating,mnesia:read/1for fetching, andmnesia:delete/1for removing records. - We briefly touched upon
mnesia:sync_transaction/1for strong distributed consistency.
Next, we'll dive into configuring Mnesia for distributed operation, including data replication and fault-tolerant storage across a cluster.
Aprende Erlang con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 12
- Lecciones
- 48
Preguntas frecuentes
¿La lección «Transacciones y manipulación de datos» es gratis?
Sí — el texto completo de «Transacciones y manipulación de datos» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Erlang OTP: Distributed & Fault-Tolerant Systems Programming, actualiza a CoddyKit PRO. El curso de Erlang OTP: Distributed & Fault-Tolerant Systems Programming incluye 4 lecciones en total.
¿Qué aprenderé en «Transacciones y manipulación de datos»?
Realice transacciones atómicas en tablas de Mnesia para garantizar la coherencia de los datos entre nodos distribuidos. Practicas Erlang OTP: Distributed & Fault-Tolerant Systems Programming con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Erlang OTP: Distributed & Fault-Tolerant Systems Programming?
No se requiere experiencia previa. Erlang OTP: Distributed & Fault-Tolerant Systems Programming en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «Transacciones y manipulación de datos»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Erlang OTP: Distributed & Fault-Tolerant Systems Programming?
Sí. Cada lección de Erlang OTP: Distributed & Fault-Tolerant Systems Programming incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Fundamentos y esquema de Mnesia
- Transacciones y manipulación de datos
- Mnesia distribuida y replicación
- Indexación y optimización de consultas en Mnesia