Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 999

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css">
<title>Erlang -- Building A Mnesia Database</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/mnesia-4.7.1.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>Mnesia</strong><br><strong>User's Guide</strong><br><small>Version 4.7.1</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../../../../doc/js/flipmenu">
<li id="no" title="Introduction" expanded="false">Introduction<ul>
<li><a href="Mnesia_chap1.html">
              Top of chapter
            </a></li>
<li title="About Mnesia"><a href="Mnesia_chap1.html#id57488">About Mnesia</a></li>
<li title="The Mnesia DataBase Management System (DBMS)"><a href="Mnesia_chap1.html#id57481">The Mnesia DataBase Management System (DBMS)</a></li>
</ul>
</li>
<li id="no" title="Getting Started with Mnesia" expanded="false">Getting Started with Mnesia<ul>
<li><a href="Mnesia_chap2.html">
              Top of chapter
            </a></li>
<li title="Starting Mnesia for the first time"><a href="Mnesia_chap2.html#id61530">Starting Mnesia for the first time</a></li>
<li title="An Introductory Example"><a href="Mnesia_chap2.html#id62101">An Introductory Example</a></li>
</ul>
</li>
<li id="loadscrollpos" title="Building A Mnesia Database" expanded="true">Building A Mnesia Database<ul>
<li><a href="Mnesia_chap3.html">
              Top of chapter
            </a></li>
<li title="Defining a Schema"><a href="Mnesia_chap3.html#id67814">Defining a Schema</a></li>
<li title="The Data Model"><a href="Mnesia_chap3.html#id68070">The Data Model</a></li>
<li title="Starting Mnesia"><a href="Mnesia_chap3.html#id68125">Starting Mnesia</a></li>
<li title="Creating New Tables"><a href="Mnesia_chap3.html#id72288">Creating New Tables</a></li>
</ul>
</li>
<li id="no" title="Transactions and Other Access Contexts" expanded="false">Transactions and Other Access Contexts<ul>
<li><a href="Mnesia_chap4.html">
              Top of chapter
            </a></li>
<li title="Transaction Properties"><a href="Mnesia_chap4.html#id72980">Transaction Properties</a></li>
<li title="Locking"><a href="Mnesia_chap4.html#id73193">Locking</a></li>
<li title="Dirty Operations"><a href="Mnesia_chap4.html#id73653">Dirty Operations</a></li>
<li title="Record Names versus Table Names"><a href="Mnesia_chap4.html#id74026">Record Names versus Table Names</a></li>
<li title="Activity Concept and Various Access Contexts"><a href="Mnesia_chap4.html#id74114">Activity Concept and Various Access Contexts</a></li>
<li title="Nested transactions"><a href="Mnesia_chap4.html#id74404">Nested transactions</a></li>
<li title="Pattern Matching"><a href="Mnesia_chap4.html#id74476">Pattern Matching</a></li>
<li title="Iteration"><a href="Mnesia_chap4.html#id74822">Iteration</a></li>
</ul>
</li>
<li id="no" title="Miscellaneous Mnesia Features" expanded="false">Miscellaneous Mnesia Features<ul>
<li><a href="Mnesia_chap5.html">
              Top of chapter
            </a></li>
<li title="Indexing"><a href="Mnesia_chap5.html#id75164">Indexing</a></li>
<li title="Distribution and Fault Tolerance"><a href="Mnesia_chap5.html#id75284">Distribution and Fault Tolerance</a></li>
<li title="Table Fragmentation"><a href="Mnesia_chap5.html#id75432">Table Fragmentation</a></li>
<li title="Local Content Tables"><a href="Mnesia_chap5.html#id76375">Local Content Tables</a></li>
<li title="Disc-less Nodes"><a href="Mnesia_chap5.html#id76402">Disc-less Nodes</a></li>
<li title="More Schema Management"><a href="Mnesia_chap5.html#id76560">More Schema Management</a></li>
<li title="Mnesia Event Handling"><a href="Mnesia_chap5.html#id76675">Mnesia Event Handling</a></li>
<li title="Debugging Mnesia Applications"><a href="Mnesia_chap5.html#id77250">Debugging Mnesia Applications</a></li>
<li title="Concurrent Processes in Mnesia"><a href="Mnesia_chap5.html#id77395">Concurrent Processes in Mnesia</a></li>
<li title="Prototyping"><a href="Mnesia_chap5.html#id77432">Prototyping</a></li>
<li title="Object Based Programming with Mnesia"><a href="Mnesia_chap5.html#id77546">Object Based Programming with Mnesia</a></li>
</ul>
</li>
<li id="no" title="Mnesia System Information" expanded="false">Mnesia System Information<ul>
<li><a href="Mnesia_chap7.html">
              Top of chapter
            </a></li>
<li title="Database Configuration Data"><a href="Mnesia_chap7.html#id77779">Database Configuration Data</a></li>
<li title="Core Dumps"><a href="Mnesia_chap7.html#id77817">Core Dumps</a></li>
<li title="Dumping Tables"><a href="Mnesia_chap7.html#id77838">Dumping Tables</a></li>
<li title="Checkpoints"><a href="Mnesia_chap7.html#id77873">Checkpoints</a></li>
<li title="Files"><a href="Mnesia_chap7.html#id78113">Files</a></li>
<li title="Loading of Tables at Start-up"><a href="Mnesia_chap7.html#id78474">Loading of Tables at Start-up</a></li>
<li title="Recovery from Communication Failure"><a href="Mnesia_chap7.html#id78632">Recovery from Communication Failure</a></li>
<li title="Recovery of Transactions"><a href="Mnesia_chap7.html#id78755">Recovery of Transactions</a></li>
<li title="Backup, Fallback, and Disaster Recovery"><a href="Mnesia_chap7.html#id78876">Backup, Fallback, and Disaster Recovery</a></li>
</ul>
</li>
<li id="no" title="Combining Mnesia with SNMP" expanded="false">Combining Mnesia with SNMP<ul>
<li><a href="Mnesia_chap8.html">
              Top of chapter
            </a></li>
<li title="Combining Mnesia and SNMP "><a href="Mnesia_chap8.html#id79691">Combining Mnesia and SNMP </a></li>
</ul>
</li>
<li id="no" title="Appendix A: Mnesia Error Messages" expanded="false">Appendix A: Mnesia Error Messages<ul>
<li><a href="Mnesia_App_A.html">
              Top of chapter
            </a></li>
<li title="Errors in Mnesia"><a href="Mnesia_App_A.html#id79834">Errors in Mnesia</a></li>
</ul>
</li>
<li id="no" title="Appendix B: The Backup Call Back Interface" expanded="false">Appendix B: The Backup Call Back Interface<ul>
<li><a href="Mnesia_App_B.html">
              Top of chapter
            </a></li>
<li title="mnesia_backup callback behavior"><a href="Mnesia_App_B.html#id80051">mnesia_backup callback behavior</a></li>
</ul>
</li>
<li id="no" title="Appendix C: The Activity Access Call Back Interface" expanded="false">Appendix C: The Activity Access Call Back Interface<ul>
<li><a href="Mnesia_App_C.html">
              Top of chapter
            </a></li>
<li title="mnesia_access callback behavior"><a href="Mnesia_App_C.html#id80172">mnesia_access callback behavior</a></li>
</ul>
</li>
<li id="no" title="Appendix D: The Fragmented Table Hashing Call Back Interface" expanded="false">Appendix D: The Fragmented Table Hashing Call Back Interface<ul>
<li><a href="Mnesia_App_D.html">
              Top of chapter
            </a></li>
<li title="mnesia_frag_hash callback behavior"><a href="Mnesia_App_D.html#id80315">mnesia_frag_hash callback behavior</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>3 Building A Mnesia Database</h1>
  
  <p>This chapter details the basic steps involved when designing
    a Mnesia database and the programming constructs which make different
    solutions available to the programmer. The chapter includes the following
    sections:
    </p>
  <ul>
    <li>defining a schema</li>
    <li>the datamodel</li>
    <li>starting Mnesia</li>
    <li>creating new tables.</li>
  </ul>

  <h3><a name="id67814">3.1 
        Defining a Schema</a></h3>
    <a name="def_schema"></a>
    
    <p>The configuration of a Mnesia system is described in the
      schema. The schema is a special table which contains information
      such as the table names and each table's
      storage type, (i.e. whether a table should be stored in RAM,
      on disc or possibly on both, as well as its location).
      </p>
    <p>Unlike data tables, information contained in schema tables can only be
      accessed and modified by using the schema related functions
      described in this section. 
      </p>
    <p>Mnesia has various functions for defining the
      database schema. It is possible to move tables, delete tables,
      or reconfigure the layout of tables.
      </p>
    <p>An important aspect of these functions is that the system can access a
      table while it is being reconfigured. For example, it is possible to move a
      table and simultaneously perform write operations to the same
      table. This feature is  essential for applications that require
      continuous service.
      </p>
    <p>The following section describes the functions available for schema management,
      all of which return a tuple:
      </p>
    <ul>
      <li>
<span class="code">{atomic, ok}</span>; or,
      </li>
      <li>
<span class="code">{aborted, Reason}</span> if unsuccessful.</li>
    </ul>

    <h4>Schema Functions</h4>
      
      <ul>
        <li>
<span class="code">mnesia:create_schema(NodeList)</span>.  This function is
         used to initialize a new, empty schema. This is a mandatory
         requirement before Mnesia can be started. Mnesia is a truly
         distributed DBMS and the schema is a system table that is
         replicated on all nodes in a Mnesia system.
         The function will  fail if a schema is already present on any of
         the nodes in <span class="code">NodeList</span>. This function requires Mnesia
         to be stopped on the all
        <span class="code">db_nodes</span> contained in the parameter <span class="code">NodeList</span>.
         Applications call this function only once,
         since it is usually a one-time activity to initialize a new
         database.
        </li>
        <li>
<span class="code">mnesia:delete_schema(DiscNodeList)</span>. This function
         erases any old schemas on the nodes in
        <span class="code">DiscNodeList</span>. It also removes all old tables together
         with all data. This function requires Mnesia to be stopped
         on all <span class="code">db_nodes</span>.
        </li>
        <li>
<span class="code">mnesia:delete_table(Tab)</span>. This function
         permanently deletes all replicas of table <span class="code">Tab</span>.
        </li>
        <li>
<span class="code">mnesia:clear_table(Tab)</span>. This function
         permanently deletes all entries in table <span class="code">Tab</span>.
        </li>
        <li>
<span class="code">mnesia:move_table_copy(Tab, From, To)</span>. This
         function moves the copy of table <span class="code">Tab</span> from node
        <span class="code">From</span> to node <span class="code">To</span>. The table storage type,
        <span class="code">{type}</span> is preserved, so if a RAM table is moved from
         one node to another node, it remains a RAM table on the new
         node. It is still possible for other transactions to perform
         read and write operation to the table while it is being
         moved.
        </li>
        <li>
<span class="code">mnesia:add_table_copy(Tab, Node, Type)</span>. This
         function creates a replica of the table <span class="code">Tab</span> at node
        <span class="code">Node</span>. The <span class="code">Type</span> argument must be either of the
         atoms <span class="code">ram_copies</span>, <span class="code">disc_copies</span>, or
        <span class="code">disc_only_copies</span>. If we add a copy of the system
         table <span class="code">schema</span> to a node, this means that we want the
         Mnesia schema to reside there as well. This action then
         extends the set of nodes that comprise this particular
         Mnesia system.
        </li>
        <li>
<span class="code">mnesia:del_table_copy(Tab, Node)</span>. This function
         deletes the replica of table <span class="code">Tab</span> at node <span class="code">Node</span>.
         When the last replica of a  table is removed, the table is
         deleted.
        </li>
        <li>
          <p><span class="code">mnesia:transform_table(Tab, Fun, NewAttributeList, NewRecordName)</span>. This
            function changes the format on all records in table
            <span class="code">Tab</span>. It applies the argument <span class="code">Fun</span> to all
            records in the table. <span class="code">Fun</span> shall be a function which
            takes a record of the old type, and returns the record of the new
            type. The table key may not be changed.</p>
          <div class="example"><pre>
-record(old, {key, val}).
-record(new, {key, val, extra}). 

Transformer = 
   fun(X) when record(X, old) -&gt;
      #new{key = X#old.key,
           val = X#old.val,
           extra = 42}
   end,
{atomic, ok} = mnesia:transform_table(foo, Transformer, 
                                      record_info(fields, new), 
                                      new),
          </pre></div>
          <p>The <span class="code">Fun</span> argument can also be the atom
            <span class="code">ignore</span>, it indicates that only the meta data about the table will
            be updated. Usage of <span class="code">ignore</span> is not recommended (since it creates
            inconsistencies between the meta data and the actual data) but included
            as a possibility for the user do to his own (off-line) transform.</p>
        </li>
        <li>
<span class="code">change_table_copy_type(Tab, Node, ToType)</span>. This
         function changes the storage type of a table. For example, a
         RAM table is changed to a disc_table at the node specified
         as <span class="code">Node</span>.</li>
      </ul>
    
  

  <h3><a name="id68070">3.2 
        The Data Model</a></h3>
    
    <p>The data model employed by Mnesia is an extended 
      relational data model. Data is organized as a set of 
      tables and relations between different data records can
      be modeled as additional tables describing the actual 
      relationships.
      Each table contains instances of Erlang records
      and records are represented as Erlang tuples.
      </p>
    <p>Object identifiers, also known as oid, are made up of a table name and a key.
      For example, if we have an employee record represented by the tuple
      <span class="code">{employee, 104732, klacke, 7, male, 98108, {221, 015}}</span>.
      This record has an object id, (Oid) which is the tuple
      <span class="code">{employee, 104732}</span>. 
      </p>
    <p>Thus, each table is made up of records, where the first element
      is a record name and the second element of the table is a key
      which identifies the particular record in that table. The
      combination of the table name and a key,  is an arity two tuple
      <span class="code">{Tab, Key}</span> called  the Oid. See  Chapter 4:<span class="bold_code"><a href="Mnesia_chap4.html#recordnames_tablenames">Record Names Versus Table Names</a></span>, for more information
      regarding the relationship between the record name and the table
      name.
      </p>
    <p>What makes the Mnesia data model an extended relational model
      is the ability to store arbitrary Erlang terms in the attribute
      fields. One attribute value could for example be a whole tree of
      oids leading to other terms in other tables.  This 
      type of record is hard to model in traditional relational 
      DBMSs.</p>
  

  <h3><a name="id68125">3.3 
        Starting Mnesia</a></h3>
    <a name="start_mnesia"></a>
    
    <p>Before we can start Mnesia, we must initialize an empty schema
      on all the participating nodes.
      </p>
    <ul>
      <li>The Erlang system must be started.
      </li>
      <li>Nodes with disc database schema must be defined and
       implemented with the function <span class="code">create_schema(NodeList).</span>
</li>
    </ul>
    <p>When running a distributed system, with two or more
      participating nodes, then the <span class="code">mnesia:start( ).</span> function
      must be executed on each participating node. Typically this would
      be part of the boot script in an embedded environment.
      In a test environment or an interactive environment,
      <span class="code">mnesia:start()</span> can also be used either from the
      Erlang shell, or another program. 
      </p>

    <h4>Initializing a Schema and Starting Mnesia</h4>
      
      <p>To use a known example, we illustrate how to run the
        Company database described in Chapter 2 on two separate nodes,
        which we call <span class="code">a@gin</span> and <span class="code">b@skeppet</span>. Each of these
        nodes must have have a Mnesia directory as well as an
        initialized schema before Mnesia can be started. There are two
        ways to specify the Mnesia directory to be used: 
        </p>
      <ul>
        <li>
          <p>Specify the Mnesia directory by providing an application
            parameter either when starting the Erlang shell or in the
            application script. Previously the following example was used
            to create the directory for our Company database:</p>
          <div class="example"><pre>
%<span class="bold_code">erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"'</span>
          </pre></div>
        </li>
        <li>If no command line flag is entered, then the Mnesia
         directory will be the current working directory on the node
         where the Erlang shell is started.</li>
      </ul>
      <p>To start our Company database and get it running on the two
        specified nodes, we enter the following commands:
        </p>
      <ul>
        <li>
          <p>On the node called gin:</p>
          <div class="example"><pre>
 gin %<span class="bold_code">erl -sname a  -mnesia dir '"/ldisc/scratch/Mnesia.company"'</span>
          </pre></div>
        </li>
        <li>
          <p>On the node called skeppet:</p>
          <div class="example"><pre>
skeppet %<span class="bold_code">erl -sname b -mnesia dir '"/ldisc/scratch/Mnesia.company"'</span>
          </pre></div>
        </li>
        <li>
          <p>On one of the two nodes:</p>
          <div class="example"><pre>
(a@gin1)&gt;<span class="bold_code">mnesia:create_schema([a@gin, b@skeppet]).</span>
          </pre></div>
        </li>
        <li>The function <span class="code">mnesia:start()</span>  is called on both
         nodes.
        </li>
        <li>
          <p>To initialize the database, execute the following
            code on one of the two nodes.</p>
          
        </li>
      </ul>
      <p>As illustrated above, the two directories reside on different nodes, because the
        <span class="code">/ldisc/scratch</span> (the "local" disc) exists on the two different
        nodes.
        </p>
      <p>By executing these commands we have configured two Erlang
        nodes to run the Company database, and therefore, initialize the
        database. This  is required only once when setting up, the next time the
        system is started <span class="code">mnesia:start()</span> is called
        on both nodes, to initialize the system from disc.
        </p>
      <p>In a system of Mnesia nodes, every node is aware of the
        current location of all tables. In this example, data is
        replicated on both nodes and functions which manipulate the
        data in our tables can be executed on either of the two nodes.
        Code which manipulate Mnesia data behaves identically
        regardless of where the data resides.
        </p>
      <p>The function <span class="code">mnesia:stop()</span> stops Mnesia on the node
        where the function is executed. Both the <span class="code">start/0</span> and
        the <span class="code">stop/0</span> functions work on the "local" Mnesia system,
        and there are no functions which start or stop a set of nodes.
        </p>
    

    <h4>The Start-Up Procedure</h4>
      
      <p>Mnesia is started by calling the following function:
        </p>
      <div class="example"><pre>
          mnesia:start().
      </pre></div>
      <p>This function initiates the DBMS locally.  </p>
      <p>The choice of configuration will alter the location and load
        order of the tables. The alternatives are listed below:        <br>
</p>
      <ul>
        <li>Tables that are stored locally only, are initialized
         from the local Mnesia directory. 
        </li>
        <li>Replicated tables that  reside locally
         as  well as somewhere else are either initiated from disc or
         by copying the entire table from the other node depending on
         which of the different replicas is the most recent. Mnesia
         determines  which of the tables is the most recent.
        </li>
        <li>Tables that reside on remote nodes are available to other nodes as soon
         as they are loaded.</li>
      </ul>
      <p>Table initialization is asynchronous, the function
        call <span class="code">mnesia:start()</span> returns the atom <span class="code">ok</span> and
        then starts to initialize the different tables. Depending on
        the size of the database, this may take some time, and the
        application programmer must wait for the tables that the
        application needs before they can be used. This achieved by using
        the function:</p>
      <ul>
        <li><span class="code">mnesia:wait_for_tables(TabList, Timeout)</span></li>
      </ul>
      <p>This function suspends the caller until all tables
        specified in <span class="code">TabList</span> are properly initiated. 
        </p>
      <p>A problem can arise if  a replicated table on one node is
        initiated, but Mnesia deduces that another (remote)
        replica is more recent than the replica existing on
        the local node, the initialization procedure  will not proceed.
        In this situation, a call to to
        <span class="code">mnesia:wait_for_tables/2</span> suspends the caller until the
        remote node has initiated the table from its local disc  and
        the node has copied the table over the network to the local node. 
        </p>
      <p>This procedure can be time consuming however, the shortcut function 
        shown below will load all the tables from disc at a faster rate:
        </p>
      <ul>
        <li>
<span class="code">mnesia:force_load_table(Tab)</span>. This function forces
         tables to be loaded from disc regardless of the network
         situation.</li>
      </ul>
      <p>Thus, we can assume that if an application
        wishes to use tables <span class="code">a</span> and <span class="code">b</span>, then the
        application must perform some action similar to the below code before it can utilize the tables.
        </p>
      <div class="example"><pre>
          case mnesia:wait_for_tables([a, b], 20000) of
            {timeout,   RemainingTabs} -&gt;
              panic(RemainingTabs);
            ok -&gt;
              synced
          end.
      </pre></div>
      <div class="warning">
<div class="label">Warning</div>
<div class="content"><p>
        <p>When tables are forcefully loaded from the local disc,
          all operations that were performed on the replicated table
          while the local node was down, and the remote replica was
          alive, are lost. This can cause the database to become
          inconsistent.</p>
      </p></div>
</div>
      <p>If the start-up procedure fails, the
        <span class="code">mnesia:start()</span> function returns the cryptic tuple 
        <span class="code">{error,{shutdown, {mnesia_sup,start,[normal,[]]}}}</span>.
        Use command line arguments  -boot start_sasl as argument to
        the erl script in order to get  more information
        about the start failure. 
        </p>
    
  

  <h3><a name="id72288">3.4 
        Creating New Tables</a></h3>
    <a name="create_tables"></a>
    
    <p>Mnesia provides one function to create new tables. This
      function is: <span class="code">mnesia:create_table(Name, ArgList).</span></p>
    <p>When executing this function, it returns one of the following
      responses:
      </p>
    <ul>
      <li>
<span class="code">{atomic, ok}</span> if the function executes
       successfully
      </li>
      <li>
<span class="code">{aborted, Reason}</span> if the function fails.
      </li>
    </ul>
    <p>The function arguments are:
      </p>
    <ul>
      <li>
<span class="code">Name</span> is the atomic name of the table. It is
       usually  the same name as the name of the records that
       constitute the table. (See <span class="code">record_name</span> for more
       details.)
      </li>
      <li>
        <p><span class="code">ArgList</span> is a list of <span class="code">{Key,Value}</span> tuples.
          The following arguments are valid:
          </p>
        <ul>
          <li>
            <p><span class="code">{type, Type}</span> where <span class="code">Type</span> must be either of the
              atoms <span class="code">set</span>, <span class="code">ordered_set</span> or <span class="code">bag</span>. 
              The default value is
              <span class="code">set</span>. Note: currently 'ordered_set' 
              is not supported for 'disc_only_copies' tables.
              A table of type <span class="code">set</span> or <span class="code">ordered_set</span> has either zero or
              one record per key.  Whereas a table of type <span class="code">bag</span> can
              have an arbitrary number of records per key. The key for
              each record is always the first attribute of the record.</p>
            <p>The following example illustrates the difference between
              type <span class="code">set</span> and <span class="code">bag</span>: </p>
            <div class="example"><pre>
 f() -&gt; F =  fun() -&gt;
     mnesia:write({foo, 1, 2}), mnesia:write({foo, 1, 3}),
     mnesia:read({foo, 1}) end, mnesia:transaction(F).             </pre></div>
            <p>This transaction will return the list <span class="code">[{foo,1,3}]</span> if
              the <span class="code">foo</span> table is of type <span class="code">set</span>.  However, list
              <span class="code">[{foo,1,2}, {foo,1,3}]</span> will return if the table is
              of  type <span class="code">bag</span>. Note the use of <span class="code">bag</span> and
              <span class="code">set</span> table types. </p>
            <p>Mnesia tables can never contain
              duplicates of the same record in the same table.  Duplicate
              records have attributes with the same contents and key. 
              </p>
          </li>
          <li>
            <p><span class="code">{disc_copies, NodeList}</span>, where <span class="code">NodeList</span> is a
              list of the nodes where this table will reside on disc.</p>
            <p>Write operations to a table replica of type
              <span class="code">disc_copies</span> will write data to the disc copy as well
              as to the RAM copy of the table. </p>
            <p>It is possible to have a
              replicated table of type <span class="code">disc_copies</span> on one node, and
              the same table stored as a different type on another node.
              The default value is <span class="code">[]</span>. This arrangement is
              desirable if we want the following operational
              characteristics are required:</p>
            <ul>
              <li>read operations must be very fast and performed in RAM
              </li>
              <li>all write operations must be written to persistent
               storage.</li>
            </ul>
            <p>A write operation on a <span class="code">disc_copies</span> table
              replica will be performed in two steps. First the write
              operation is appended to a log file, then the actual
              operation is performed in RAM.
              </p>
          </li>
          <li>
            <p><span class="code">{ram_copies, NodeList}</span>, where <span class="code">NodeList</span> is a
              list of the nodes where this table is stored in RAM. The
              default value for <span class="code">NodeList</span>  is <span class="code">[node()]</span>. If the
              default value is used to create a new table, it will be
              located on the local node only. </p>
            <p>Table replicas of type
              <span class="code">ram_copies</span> can be dumped to disc with the function
              <span class="code">mnesia:dump_tables(TabList)</span>.
              </p>
          </li>
          <li>
<span class="code">{disc_only_copies, NodeList}</span>. These table
           replicas are stored on disc only and are therefore slower to
           access. However, a disc only replica consumes less memory than
           a table replica of the other two storage types. 
          </li>
          <li>
<span class="code">{index, AttributeNameList}</span>, where
          <span class="code">AttributeNameList</span> is a list of atoms specifying the
           names of the attributes Mnesia shall build and maintain. An
           index  table will exist for every element in the list.  The
           first field of a Mnesia record is the key and thus need no
           extra index. 
                    <br>
The first field of a record is the second element of the
           tuple, which is the representation of the record.  
          </li>
          <li>
<span class="code">{snmp, SnmpStruct}</span>. <span class="code">SnmpStruct</span> is
           described in the SNMP User Guide. Basically, if this attribute
           is present in  <span class="code">ArgList</span> of <span class="code">mnesia:create_table/2</span>,
           the table is immediately accessible by means of the Simple
           Network Management Protocol (SNMP). 
                    <br>
It is easy to design applications which use SNMP to
           manipulate and control the system. Mnesia provides a direct
           mapping between the logical tables that make up an SNMP
           control application and the physical data which make up a
           Mnesia table. <span class="code">[]</span>
           is default.
          </li>
          <li>
<span class="code">{local_content, true}</span> When an application needs  a
           table  whose contents  should  be  locally unique on each
           node,
          <span class="code">local_content</span>  tables may be used. The name of the
           table  is  known  to all  Mnesia  nodes,  but its contents is
           unique for each node. Access to this type of table must  be
           done locally. </li>
          <li>
            <p><span class="code">{attributes, AtomList}</span> is a list of the attribute
              names for the records that are supposed to populate the
              table. The default value is the list <span class="code">[key, val]</span>. The
              table must at least have one extra attribute besides the
              key. When accessing single attributes in a record, it is not
              recommended to hard code the attribute names as atoms. Use
              the construct <span class="code">record_info(fields,record_name)</span>
              instead. The expression
              <span class="code">record_info(fields,record_name)</span> is processed by the
              Erlang macro pre-processor and returns a list of the
              record's field names. With the record definition
              <span class="code">-record(foo, {x,y,z}).</span> the expression
              <span class="code">record_info(fields,foo)</span> is expanded to the list
              <span class="code">[x,y,z]</span>. Accordingly, it is possible to provide the
              attribute names yourself, or to use the <span class="code">record_info/2</span>
              notation.  </p>
            <p>It is recommended that
              the <span class="code">record_info/2</span> notation be used  as it is easier to
              maintain the program and it will be more robust with regards
              to future record changes.
              </p>
          </li>
          <li>
            <p><span class="code">{record_name, Atom}</span> specifies the common name of
              all records stored in the table. All records, stored in
              the table, must have this name as their first element.
              The <span class="code">record_name</span> defaults to the name of the
              table. For more information see  Chapter 4:<span class="bold_code"><a href="Mnesia_chap4.html#recordnames_tablenames">Record Names Versus Table Names</a></span>.</p>
          </li>
        </ul>
      </li>
    </ul>
    <p>As an example, assume we have the record definition:</p>
    <div class="example"><pre>
      -record(funky, {x, y}).
    </pre></div>
    <p>The below call would create a table which is replicated on two
      nodes, has an additional index on the <span class="code">y</span> attribute, and is
      of type
      <span class="code">bag</span>.</p>
    <div class="example"><pre>
      mnesia:create_table(funky, [{disc_copies, [N1, N2]}, {index,
      [y]}, {type, bag}, {attributes, record_info(fields, funky)}]).
    </pre></div>
    <p>Whereas a call to the below default code values: </p>
    <div class="example"><pre>
mnesia:create_table(stuff, [])    </pre></div>
    <p>would return a table with a RAM copy on the
      local node, no additional indexes and the attributes defaulted to
      the list <span class="code">[key,val]</span>.</p>
  
</div>
<div class="footer">
<hr>
<p>Copyright © 1997-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>