动态DDL的事务日志记录
SmartESQL 支持 SQL 数据定义语言(DDL)操作,用于创建、更改或删除表和索引。这些操作显然会导致数据库模式被修改。模式修改会在日志中反映出来,并且会透明地应用于数据库,而无需应用程序介入。
使用数据中继时也支持动态 DDL。请参阅 SDK 示例 samples\native\tl\tlogiterpipe_ddl。
请注意,当从日志还原数据库时,只有通过 SQL 或 UDA API 才能进一步访问,因为基于先前修改前模式生成的任何 API 都会失效。使用生成的 API 执行事务的尝试将导致 MCO_E_SCHEMA_CHANGED
错误,这表明应用程序必须关闭当前连接。
当从日志还原数据库时,使用 C/C++ API 的应用程序必须:
通过为 mco_db_params_t 结构体中的
max_classes
、max_indexes
和ddl_dict_size
元素(或其 SQL C++ API 对应项)分配非零值,确保为新创建的动态类和索引提供足够的内存。向数据库运行时传递一个空字典。
为了说明此过程,考虑两种情况:有和没有通过 mco_db_save()
保存的数据库快照。如果已保存了数据库的快照,那么以下代码片段演示了如何从日志文件中恢复数据库:
mco_db_h db;
mco_db_params_t db_params;
const char *db_name = "mydb";
const char *tl_log_file = "mydb.log";
mco_db_params_init ( &db_params );
/* initialize the params with default values */
...
db_params.max_classes = 100; // maximum number of classes possible in the database
// memory space reserved for the dictionary
db_params.max_indexes = 1000; // maximum number of indexes possible db_params.ddl_dict_size = 64 * 1024;
/* db_params.ddl_dict = 0; no DDL dictionary. This is required parameter.
But it is automatically zeroed by function mco_db_params_init */
...
mco_db_load(stream_handle,
input_stream_reader,
db_name,
0 /* no static dictionary */,
pdev->dev,
pdev->n_dev,
&db_params );
mco_db_connect(db_name, con);
mco_translog_apply(con, tl_log_file, MCO_TRANSLOG_ALL_LABELS );
或者,当尚未保存快照时:
mco_db_h db;
mco_db_params_t db_params;
const char *db_name = "mydb";
const char *tl_log_file = "mydb.log";
mco_db_params_init ( &db_params );
/* initialize the params with default values */
...
db_params.max_classes = 100; // maximum number of classes possible in the database
// memory space reserved for the dictionary
db_params.max_indexes = 1000; // maximum number of indexes possible db_params.ddl_dict_size = 64 * 1024;
/* db_params.ddl_dict = 0; no DDL dictionary. This is required parameter.
But it is automatically zeroed by function mco_db_params_init */
...
/* define if autooid or native fields order are required */
db_params.ddl_dict_flags = MCO_DICT_FLAGS_USE_AUTOOID |
MCO_DICT_FLAGS_PRESERVE_FIELDS_ORDER;
...
mco_db_open_dev(stream_handle,
input_stream_reader,
db_name,
0 /* no static dictionary */,
pdev->dev,
pdev->n_dev,
&db_params );
mco_db_connect(db_name, con);
mco_translog_apply(con, tl_log_file, MCO_TRANSLOG_ALL_LABELS );
从日志文件还原数据库时,请注意,如果应用程序正在迭代一个非动态管道(即创建时未使用 MCO_TRANSLOG_DYNAMIC_PIPE
标志),则“写入器”线程会收到错误 MCO_E_TL_PIPE_TERM
,表明管道已断开,当前事务未写入管道。
Java 和 C# 应用程序通过 Database::Parameters 类的 MaxClasses
、MaxIndexes
和 MaxDictionarySize
成员设置 max_classes
、max_indexes
和 max_ddl_dict_size
。
Python 应用程序将这些值作为参数 max_classes
、max_indexes
和 maxDictionarySize
传递给 open_database()
函数。
例如:
db = exdb.open_database(
dbname='opendb',
dictionary=dict,
is_disk=is_disk,
db_segment_size=128*1024*1024,
max_classes=100, max_indexes=1000,
maxDictionarySize=16*1024
)
以下 SDK 示例是很有用的示例:
- tlogbasic_ddl - 展示了如何使用 SQL C++ API 维护快照和日志文件。
- xSQL/TL - 展示了如何使用 xSQL 配置文件实现相同的功能。